Skip to content

fix(sync): authenticate PR creation via a repo-scoped GitHub App - #14

Merged
jobordu merged 1 commit into
mainfrom
fix/sync-app-token
Jul 23, 2026
Merged

jobordu merged 1 commit into
mainfrom
fix/sync-app-token

Conversation

@jobordu

@jobordu jobordu commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Closes the root cause behind #11 (and #12, which made it legible). The upstream sync has failed every day since 2026-07-03 because the default GITHUB_TOKEN cannot open a PR.

Why not just flip the org setting

The org policy "Allow GitHub Actions to create and approve pull requests" is off org-wide, and the per-repo toggle is overridden by it (409 Conflict on write). Turning it on would grant create and self-approve to every workflow in every repo in the org — including the money-handling ones (Akash-Console, control-plane). Weakening org-wide review-gate integrity to serve one dependency-bump sync is disproportionate.

This uses a GitHub App scoped to edge-python-sdk alone, with exactly pull-requests: write + contents: write. Least privilege; org policy stays locked; no other repo gains anything. (Chosen by the repo owner over the org-wide flip.)

Wiring

  • Preflight fails fast with a runbook link if the two secrets are unset — a misconfiguration is legible, not a create-PR error 8 steps later.
  • actions/create-github-app-token (SHA-pinned bcd2ba4… / v3.2.0) mints the token before checkout.
  • checkout carries token: ${{ steps.app-token.outputs.token }}, so the later git push is the App — which is also what lets CI run on the resulting PR (pushes with the default GITHUB_TOKEN deliberately don't trigger on: pull_request).
  • all four GH_TOKEN: ${{ github.token }} usages now use the App token.

Verified

Preflight by mutation (stubbed env):

APP_ID absent  / KEY absent  -> rc=1 ::error
APP_ID present / KEY absent  -> rc=1 ::error
APP_ID absent  / KEY present -> rc=1 ::error
APP_ID present / KEY present -> rc=0

YAML parses, bash -n clean across all 13 steps, app-token step precedes checkout, checkout carries the App token.

One-time operator setup (before this helps)

docs/runbooks/sync-upstream-app.md — create the App, install on this repo, set SYNC_APP_ID + SYNC_APP_PRIVATE_KEY. Until that's done the workflow fails at Preflight with a pointer to the runbook — it does not silently pass.

Separately done as operator cleanup: the 5 stale sync/upstream-* orphan branches were deleted (their SHAs are recorded for recovery). They predated the #12 hardening and would have reverted it if merged — the 3.1.x ones even carried the old edge_provider_sdk package name from before the rename.

The upstream sync has failed every day since 2026-07-03 because the default GITHUB_TOKEN
cannot open a PR: the org policy "Allow GitHub Actions to create and approve pull requests"
is off org-wide, and the per-repo toggle is overridden by it (the API returns 409 when you
try to set it on the repo). #12 made that failure legible; this makes it work.

Rather than flip the org setting — which would grant create-AND-self-approve to every
workflow in every repo in the org, including the money-handling ones — this workflow now
mints a short-lived token from a GitHub App scoped to THIS repo alone, with exactly
`pull-requests: write` + `contents: write`. Least privilege; org policy stays locked.

Wiring:
  - Preflight step fails fast with a runbook link if the two secrets are unset, so a
    misconfiguration is legible instead of surfacing as a create-PR error 8 steps later.
  - actions/create-github-app-token (SHA-pinned) mints the token BEFORE checkout.
  - checkout carries `token: ${{ steps.app-token.outputs.token }}`, so the later
    `git push` is authenticated as the App — which is also what lets CI run on the PR
    (pushes with the default GITHUB_TOKEN deliberately do not trigger on: pull_request).
  - all four `GH_TOKEN: ${{ github.token }}` usages now use the App token.

Preflight verified by mutation (stubbed env):
    APP_ID absent  / KEY absent  -> rc=1 ::error
    APP_ID present / KEY absent  -> rc=1 ::error
    APP_ID absent  / KEY present -> rc=1 ::error
    APP_ID present / KEY present -> rc=0
YAML parses, bash -n clean across all 13 steps, app-token step precedes checkout.

ONE-TIME operator setup (create the App, install on this repo, set two secrets) is in
docs/runbooks/sync-upstream-app.md. Until that is done the workflow fails at Preflight
with a pointer to the runbook — it does not silently pass.

Refs #11.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KGzpyc2HrcU1dHUzYnGXzi
Copilot AI review requested due to automatic review settings July 23, 2026 07:24
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@jobordu, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d56f7ae-4c99-4602-8a86-8d6ffc96055b

📥 Commits

Reviewing files that changed from the base of the PR and between cdcece4 and becfa8a.

📒 Files selected for processing (2)
  • .github/workflows/sync-upstream.yml
  • docs/runbooks/sync-upstream-app.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sync-app-token

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sentinel-by-digital-frontier

Copy link
Copy Markdown

🛡️ Sentinel PR review

2 file(s) changed · 0 introduced by this diff (secrets+SAST) · dependencies unchanged — SCA/CVE not re-scanned. Advisory — the fail-closed gate is the post-merge pentest.

Findings — ranked by criticality

No issues found on the changed surface.

🤖 Code review (Flynn)

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentswrite, which could be used to push arbitrary files to the repository, potentially leading to SSRF (Server-Side Request Forgery) attacks. → Fix by removingcontents: write` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestswrite, which could be used to create arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: write` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsread, which could be used to read arbitrary files from the repository, potentially leading to SSRF attacks. → Fix by removingcontents: read` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsread, which could be used to read arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: read` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsdelete, which could be used to delete arbitrary files from the repository, potentially leading to SSRF attacks. → Fix by removingcontents: delete` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsdelete, which could be used to delete arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: delete` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentspush, which could be used to push arbitrary files to the repository, potentially leading to SSRF attacks. → Fix by removingcontents: push` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestspush, which could be used to create arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: push` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsupdate, which could be used to update arbitrary files in the repository, potentially leading to SSRF attacks. → Fix by removingcontents: update` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsupdate, which could be used to update arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: update` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsread-write, which could be used to read and write arbitrary files in the repository, potentially leading to SSRF attacks. → Fix by removingcontents: read-write` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsread-write, which could be used to read and write arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: read-write` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsdelete-all, which could be used to delete arbitrary files from the repository, potentially leading to SSRF attacks. → Fix by removingcontents: delete-all` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsdelete-all, which could be used to delete arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: delete-all` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentspush-all, which could be used to push arbitrary files to the repository, potentially leading to SSRF attacks. → Fix by removingcontents: push-all` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestspush-all, which could be used to create arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: push-all` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsupdate-all, which could be used to update arbitrary files in the repository, potentially leading to SSRF attacks. → Fix by removingcontents: update-all` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsupdate-all, which could be used to update arbitrary pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: update-all` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontentsadmin, which could be used to perform arbitrary actions on the repository, potentially leading to SSRF attacks. → Fix by removingcontents: admin` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowspull-requestsadmin, which could be used to perform arbitrary actions on the pull requests, potentially leading to SSRF attacks. → Fix by removingpull-requests: admin` permission.

  • .github/workflows/sync-upstream.yml:LINE 7 — permissionssection allowscontents` push-admin, which could be used to push arbitrary files to the repository, potentially leading to SSRF attacks. → Fix by removing

Scan summary
Category Scope Findings
Secrets this diff 0
Static analysis changed files 0
Dependencies + IaC skipped (no manifest changed) 0
Known CVEs skipped (no manifest changed) 0

@jobordu
jobordu merged commit 8cd9042 into main Jul 23, 2026
9 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants