feat(agent/pr-reviewer): migrate to GitHub App auth (spec 033, Base F1)#6
Merged
Conversation
Validates the GitHub App migration path end-to-end before refactoring production code. Mints a JWT with the App's private key, exchanges it for an installation access token, and verifies App identity via /app. Stdlib-only — no new production deps. Throwaway tool that documents the auth flow; production integration will use ghinstallation/v2. Phase A + B verified against #2 on 2026-05-21: - POST review as ben-s-pull-request-reviewer[bot] → id 4340102652 - GET /reviews returns the review (Spammy filter no longer applies) Adds docs/github-app-setup.md with App identity table, auth-flow explanation, mint-iat usage (teamvault-pipe / file / env), rotation procedure, and gotchas (no GET /user, bot login has brackets, required-approvals gates need testing). Tracks F1 of [[GitHub Code Reviewer Agent - Base]].
Dev and prod must use distinct App identities so dev test verdicts cannot be mistaken for prod verdicts by auto-merge gates, and so a dev compromise cannot reach prod. Same permission set, different scope: - Prod: ben-s-pull-request-reviewer (all bborbe/* repos) - Dev: ben-s-pull-request-reviewer-dev (bborbe/go-skeleton only) Both Apps verified end-to-end via cmd/mint-iat on 2026-05-21.
The agent task controller mounts Secret keys via envFrom: secretRef:
(agent_configuration.go), not as files. The previous Config CR had
PEM_KEY_FILE=/etc/github-app/pem pointing at a non-existent path, and
the Secret used teamvaultPassword (which returns empty for file-type
Teamvault entries) instead of teamvaultFileBase64.
Fixes:
- Secret YAML: PEM (teamvaultPassword) -> PEM_KEY (teamvaultFileBase64)
so envFrom exposes the PEM content as env var \$PEM_KEY directly.
- Config CR: drop PEM_KEY_FILE; main.go's PEMKey field reads \$PEM_KEY
from the Secret-derived env. Comment updated.
- cmd/{cli,mint-iat,run-task}/Makefile: add no-op buca/apply stubs so
Makefile.folder's recursion succeeds (cmd binaries are CLI tools
installed via go install, not k8s services).
Verified end-to-end on dev cluster:
- kubectlquant -n dev get secret maintainer-agent-pr-reviewer
shows PEM_KEY=1679 decoded bytes (valid RSA key)
- Config CR has APP_ID=3800041, INSTALLATION_ID=134435225,
BOT_GITHUB_LOGIN=ben-s-pull-request-reviewer-dev[bot]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates
agent/pr-reviewerfrom PAT-on-user authentication (pr-review-of-ben, flagged "Spammy" by GitHub Trust & Safety → reviews invisible via REST/reviews) to GitHub App authentication.Two Apps registered, installed, smoke-tested end-to-end (Phase A + B, commit
c1a105d,cmd/mint-iat):3798945134414316kLoejwbborbe/*3800041134435225eqKj8Lbborbe/go-skeletononlyPhase B verified prod review id
4340102652POSTed and visible via REST API asben-s-pull-request-reviewer[bot].What's in this PR
cmd/mint-iatsmoke-test tool (stdlib-only) +docs/github-app-setup.mdreferencelib/githubapp)bradleyfalzon/ghinstallation/v2;NewClientreturns auth-injectinghttp.Client;MintIATreturns the IAT forGH_TOKENcallers. 95.5% test coverage.APP_ID,INSTALLATION_ID,PEM_KEY_FILE,BOT_GITHUB_LOGIN. Pod startup mints IAT and assigns toa.GHTokenso downstream code (githubposter,githubauth, Claude subprocess) is unchanged.pkg/authmode.goresolver: App auth wins overGH_TOKEN; pod refuses to start if neither is set.DefaultBotLoginflipped toben-s-pull-request-reviewer[bot].checkBotIdentityreworked (no moreGET /user).steps_gh_token.goerror messages no longer say "rotate teamvault entry".teamvaultPasswordtemplate. Config CRenv:exposesAPP_ID,INSTALLATION_ID,BOT_GITHUB_LOGIN,PEM_KEY_FILE.dev.env/prod.envupdated withAGENT_PR_REVIEWER_APP_ID/INSTALLATION_ID/BOT_LOGIN/PEM_KEYexports. LegacyGH_TOKENSecret key retained as fallback.Out of scope (sibling specs)
GH_TOKENenv (kept as fallback)APPROVE— observed in Rung 3, documented, not changedTest plan
cd lib && make precommit→ green (95.5% cov onlib/githubapp)cd agent/pr-reviewer && make precommit→ green (87 tests, 86.2% avg cov, 0 lint/sec issues)bborbe/go-skeleton→ confirm review visible via REST asben-s-pull-request-reviewer-dev[bot]bborbe/*→ confirm review visible via REST asben-s-pull-request-reviewer[bot]pr-review-of-benPATRelated
specs/in-progress/033-migrate-pr-reviewer-to-github-app.mdagent/pr-reviewer/docs/github-app-setup.md