Repository navigation
Authenticate CI Claude review with an API key in a main-only environment - #968
Merged
seathatflowsinourveins merged 1 commit intoOct 10, 2026
Merged
Conversation
The owner ruled on 2026-10-10 (relayed by the command center, paraphrased) that CI Claude review authenticates with an Anthropic API key, not workload identity federation, which refused every run so far. The key is the environment secret ANTHROPIC_API_KEY of `claude-review`, whose deployment branch policy allows main only, so a workflow pushed on another branch gets no key. claude-pr-review.yml, claude-pr-toolkit-review.yml and harness-audit.yml pass anthropic_api_key from that secret and no federation input. The job that uses the key declares environment: claude-review, and no job holds id-token: write. They pass github_token, so the pinned action (2dca132f) requests no GitHub OIDC token (src/github/token.ts:160-168, base-action/src/workload-identity.ts:43-47). Every other guard is unchanged: dispatch and schedule on main only, the owner and first-attempt guards, the bounds step, the daily ceiling and the read-only tools. The federation exemption and the three id-token write grants leave tests/test_workflow_policy.py. The new tests.test_workflow_hardening.ClaudeApiKeyAuthTests requires the secret once per workflow, the key-using job in the environment, no federation input, no id-token, no pull request trigger, and the secret in no other workflow. It fails on main's workflows and passes here. The decision records and docs/github-automation.md carry the ruling, paraphrased. #961's federation diagnostics record is marked superseded for CI review; its vendor snapshots stay retained and tested, and its two workflow-header tests now require the API-key environment and no federation claim. #961's error_class logic in the three workflows is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Dependency limit exceeded — report not shown. This pull request scan exceeded the 10,000-dependency limit applied to this scan, so the results are incomplete and may be inaccurate. To avoid reporting false positives, Socket has not posted a report. Upgrade your plan to raise the dependency limit and get complete reports, or view the partial scan in the dashboard. Socket is always free for open source. If this is a non-commercial open source project, contact us to request a free Team account. |
seathatflowsinourveins
marked this pull request as ready for review
October 10, 2026 16:32
seathatflowsinourveins
deleted the
claude/api-actions-ci-api-key-20261010
branch
October 10, 2026 16:44
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 10, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 10, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 10, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 10, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
… git The GPT read at 13d1eb7 asked, under the correction rule, for: - the upstream sources of the environment reading: GitHub's workflow syntax for jobs.<job_id>.environment (a name, or an object with name and url) and YAML 1.2.2's block and flow mappings, quoted keys and comments, cited with page digests in the record and next to the regression cases; - a regression for the corrected inverse pin: RetirementInversePinTests reads the pin from the record and checks it is #968's merge commit holding the three workflows. It fails on the former SHA (no such commit) and is skipped, with the reason, only outside a worktree or in a shallow clone (CI clones with fetch-depth 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
… git The GPT read at 13d1eb7 asked, under the correction rule, for: - the upstream sources of the environment reading: GitHub's workflow syntax for jobs.<job_id>.environment (a name, or an object with name and url) and YAML 1.2.2's block and flow mappings, quoted keys and comments, cited with page digests in the record and next to the regression cases; - a regression for the corrected inverse pin: RetirementInversePinTests reads the pin from the record and checks it is #968's merge commit holding the three workflows. It fails on the former SHA (no such commit) and is skipped, with the reason, only outside a worktree or in a shallow clone (CI clones with fetch-depth 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
… git The GPT read at 13d1eb7 asked, under the correction rule, for: - the upstream sources of the environment reading: GitHub's workflow syntax for jobs.<job_id>.environment (a name, or an object with name and url) and YAML 1.2.2's block and flow mappings, quoted keys and comments, cited with page digests in the record and next to the regression cases; - a regression for the corrected inverse pin: RetirementInversePinTests reads the pin from the record and checks it is #968's merge commit holding the three workflows. It fails on the former SHA (no such commit) and is skipped, with the reason, only outside a worktree or in a shallow clone (CI clones with fetch-depth 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins
added a commit
that referenced
this pull request
Oct 11, 2026
* Retire Claude review inside GitHub; AI reviews run locally The owner decided on 2026-10-10 (about 17:15Z, relayed by the command center) that Claude review no longer runs inside GitHub: AI reviews run on the local host and GitHub enforces the gates. The API refused every request that carried claude-code-action's attribution (CLAUDE_CODE_ENTRYPOINT=claude-code-github-action, base-action/src/parse-sdk-options.ts:284 at 2dca132f) on all five Console keys, while the same keys work from the CLI and the Agent SDK (the command center's correction #141, measured). Removed: claude-pr-review.yml, claude-pr-toolkit-review.yml, harness-audit.yml and their three test modules, their zizmor-coverage entries and their local-pages inventory paths. test_claude_federation_diagnostics keeps its retained-snapshot and decision-claim tests. A new InGitHubClaudeReviewRetiredTests keeps the three files absent and no workflow running the Claude action or naming an Anthropic key. New record docs/decisions/2026-10-10-retire-in-github-claude-review.md (cause, what remains, revisit triggers, inverse); supersession notes in the four claude-actions/federation records and the decision-record index; docs/github-automation.md's current practice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Pin the repository grant count at 90 after the retirement The three removed workflows were in the local-pages repository grants. At the landing base, main f38116f (93 grants), the test's own derivation (grants.inventory_paths over git ls-files) gives 90 for this branch, equal to the policy's repository grants, and the test pins 90. At the earlier bases eb31d23 and 9d4c00c the same derivation gave 90 and 89. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Take up the command center's notes on the retirement - .github/actions-permissions.json drops anthropics/claude-code-action@* and oven-sh/setup-bun@*: no workflow uses them; a new test keeps every allowed pattern in use, and the record's inverse puts them back. - docs/github-automation.md: the allow-list text, no "harness description", no "still awaits hosted acceptance" clause. - The retirement test catches the claude-review environment in its plain, name: and quoted forms, and reads *.yaml as well. - Record nits: #953 marked open, the check is named sota-sources, and the federation-diagnostics note says the three workflows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cite #968's real merge commit in the inverse The record's inverse named a SHA that does not exist; #968's merge commit is 9d4c00c (git rev-parse 9d4c00c). The federation note now says the history of those workflows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Read each job's environment in the retirement guard The GPT read at 48e4bd3 found three valid YAML forms of the claude-review environment that the regex guard let through: a flow mapping, a quoted name key, and a comment after the key. The guard now reads each job's environment as a scalar or a mapping's name (job_environments), cross-checked against PyYAML when it is installed; all three forms are regressions, each caught here and missed at e46f68e, and actionlint accepts each fixture. The record names the claude-native-practice skill rows as a dated follow-up for cc-native-practice (the command center's ruling at 20:19Z). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Word the skill-row follow-up without the pinned-copy premise The command center's correction #146: no personal copy of claude-native-practice is installed on this host; sessions load the checkout's project skill. The follow-up is now stated neutrally: the skill rows for the retired route are updated in a cc-native-practice pull request, then re-pinned. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * State what the environment reading covers, and what PyYAML covers The docstring claimed comments in general; the text reading handles a comment after the key, not a comment line before name: at the job's indentation or a multi-line flow mapping. The PyYAML comparison covers those, and CI runs it (validate run 38084944806, passed, not skipped). The command center's micro at 08a76ab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cite the environment forms' sources, and test the inverse pin against git The GPT read at 13d1eb7 asked, under the correction rule, for: - the upstream sources of the environment reading: GitHub's workflow syntax for jobs.<job_id>.environment (a name, or an object with name and url) and YAML 1.2.2's block and flow mappings, quoted keys and comments, cited with page digests in the record and next to the regression cases; - a regression for the corrected inverse pin: RetirementInversePinTests reads the pin from the record and checks it is #968's merge commit holding the three workflows. It fails on the former SHA (no such commit) and is skipped, with the reason, only outside a worktree or in a shallow clone (CI clones with fetch-depth 0). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.
Scope
claude-pr-review.yml,claude-pr-toolkit-review.yml,harness-audit.yml) authenticates with an Anthropic API key, the environment secretANTHROPIC_API_KEYof the main-onlyclaude-reviewenvironment, instead of workload identity federation. This follows the owner's ruling of 2026-10-10 (about 13:44Z, relayed by the command center, paraphrased): use the keys; federation stays unconfigured. Its acceptance dispatch, run 38056354892, was refused like the runs of 10-08.e1c88ff3d(main after Fence the headless /skill-doctor run #925).lane:foundation.tests/test_workflow_hardening.py,tests/test_workflow_policy.py,tests/test_claude_pr_review_workflow.py,tests/test_claude_pr_toolkit_review_workflow.py,tests/test_claude_harness_audit_bounds.py,tests/test_claude_federation_diagnostics.py; four decision records;docs/github-automation.md;manifests/evidence.json.What changed:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}and no federation input.environment: claude-review, and no job holdsid-token: write.github_token, so the pinned action requests no GitHub OIDC token.error_classlogic.The secret:
ANTHROPIC_API_KEYholds the inventory entryanthropic-api-3, the cold spare, so CI spend stays separate from the local worker's api-4.credential_run.py, with the value on stdin only. It was first a repository secret (2026-10-10T13:49:43Z), then an environment secret ofclaude-review(2026-10-10T13:55:05Z); the repository copy was deleted.mainonly, the environment holds the secret, and the repository has no secret of that name.Policy and tests:
id-token: writewrite grants leavetests/test_workflow_policy.py.tests.test_workflow_hardening.ClaudeApiKeyAuthTestsrequires:claude-reviewenvironment, and no other job in one;id-tokenand no pull request trigger;SOTA sources
anthropic_api_keyinput with${{ secrets.ANTHROPIC_API_KEY }};id-token: writeneeded for the default GitHub App authentication and for the federation exchange.2dca132ff0e0c4094ce6048b422c6915a071210b(v1.0.247):action.yml:67-89(theanthropic_api_key, federation andgithub_tokeninputs);src/github/token.ts:160-168(no OIDC request whengithub_tokenis given);base-action/src/workload-identity.ts:43-47(federation only when its inputs are set).secrets-outside-envaudit, auditor persona: on main it reports six findings in these three files; here, none.Evidence-class table
claude-reviewenvironment, carry no federation input, hold noid-token, and have no pull request trigger; no other workflow names the secretsynthetictests.test_workflow_hardening.ClaudeApiKeyAuthTests(fails on main's workflows, passes here)github_tokenpassed, the pinned action requests no OIDC tokensource_reviewmainonly and holds the secret; the repository has no secret of that namenative_provengh api repos/…/environments/claude-reviewand its deployment-branch-policies;gh secret list --env claude-review;gh secret list(names and times only, 14:11Z)total_cost_usd> 0, non-emptymodelUsage)Local commands run
Decision record
docs/decisions/2026-10-08-claude-actions-pr-review.md, "Authentication by API key (the owner's ruling, 2026-10-10)". Short dated notes in2026-10-04-ci-least-privilege.md(federation exemption withdrawn),2026-10-08-claude-actions-harness-audit-bounds.md,2026-10-09-claude-actions-pr-toolkit-review.mdand2026-10-10-claude-federation-diagnostics.md.🤖 Generated with Claude Code