9.1 KiB
status, created, owner
| status | created | owner |
|---|---|---|
| building | 2026-07-30 | kdlbs |
Claude Fork Review Allowlist
Decision: ADR-2026-07-31-isolate-manual-pr-review-content; ADR-2026-08-07-claude-allowlist-label-bridge; ADR-2026-08-22-persistent-fork-approval-labels
Why
Trusted fork contributors listed in the repository's Claude review allowlist should receive an automatic review when they open a pull request, without requiring a maintainer to label it. Further review rounds should be explicit so pushes do not repeatedly consume Claude tokens. The workflow must pass the already-authorized contributor to Claude's separate non-write-user permission gate.
The same trusted contributors should also receive the repository's existing review and preview approval markers, so maintainers do not need to maintain a second identity list or apply two labels manually. Maintainers also use those labels for unallowlisted fork pull requests and expect an explicit approval to remain valid across routine follow-up commits.
What
- A fork pull request actor listed in
CLAUDE_REVIEW_ALLOWLISTreceives one automatic review when they open a pull request and passes both the workflow job gate and the Claude action's non-write-user gate. CLAUDE_REVIEW_ALLOWLISTremains a JSON array for safe use in GitHub Actions expressions.- The Claude action receives the already job-authorized pull request author through its
allowed_non_write_usersinput. - When an allowlisted fork pull request opens, the base-controlled workflow adds both existing labels,
safe-to-reviewandsafe-to-test, to the pull request. The label operation is idempotent and applies only to fork pull requests whose opening author matches the allowlist. - The
CLAUDE_REVIEW_ALLOWLISTgate remains a direct authorization path for the fork review job, so adding labels with the repositoryGITHUB_TOKENdoes not create a second review run through thelabeledevent. - The preview workflow treats an author in
CLAUDE_REVIEW_ALLOWLISTas trusted for fork preview deployment on every non-closed pull-request-target event it already handles (opened,synchronize,reopened, andlabeled). A maintainer-appliedsafe-to-testlabel remains valid across latersynchronizeevents and also authorizes the preview deployment path for the current fork head. - A maintainer-applied
safe-to-reviewlabel remains valid across latersynchronizeevents and authorizes the existing OpenCode fork-review path for the current fork head. The label is not removed automatically after a push. - Approval labels remain until a maintainer removes them. A contributor push does not revoke either label or require the maintainer to repeat the same approval for each follow-up commit.
- A maintainer may apply
safe-to-reviewto request the initial review of an untrusted fork pull request. - Pushes, ready-for-review transitions, and reopenings do not automatically start another Claude review. A maintainer can request a later review by commenting
@claude reviewon the pull request. That requested review reads the current pull request head, including files newly added by the pull request. - Manual pull request reviews keep the trusted default branch at the workflow root and do not check out pull request content. Claude may use read-only local tools for trusted surrounding code, reads the current diff through constrained GitHub commands, and reads complete current-head PR files only through a path-validated, size-limited GET helper bound to the event's PR number. Its only write capability is posting review comments.
- Other Claude mentions keep the generic workflow behavior and trusted default-branch checkout.
- The same-repository review path remains unchanged except for the open-only trigger policy.
- Empty, malformed, or non-matching allowlists continue to fail closed at the workflow job gate.
Permissions
- Only the base-controlled
pull_request_targetworkflow may add the two labels. It does not check out or execute pull-request content for the labeling step. - A matching
CLAUDE_REVIEW_ALLOWLISTentry authorizes the existing fork review path and the preview workflow's fork deployment path, which has access to the preview deployment credentials. Repository maintainers are responsible for keeping this variable restricted to trusted contributors. - A non-allowlisted fork author still needs the existing maintainer-applied labels. Those labels authorize the current and subsequent fork heads until a maintainer removes them; maintainers are responsible for revoking approval when the contributor or proposed change is no longer trusted.
Failure modes
- An empty, malformed, or non-matching
CLAUDE_REVIEW_ALLOWLISTproduces no automatic labels and does not authorize the review or preview jobs. - If the label API call fails or either repository label does not exist, the labeling job fails visibly. The direct review and preview gates still evaluate the allowlist independently; a label-write failure does not turn an untrusted author into a trusted one.
- Labels added with
GITHUB_TOKENdo not themselves launch a new workflow run. The review and preview workflows therefore must retain their direct allowlist gates rather than depending only on the resultinglabeledevent.
Scenarios
- GIVEN
CLAUDE_REVIEW_ALLOWLISTis["ClemDNL"], WHENClemDNLopens a fork pull request, THEN the fork review job suppliesClemDNLthroughallowed_non_write_usersand Claude does not reject the run solely because the actor has repository permissionread. - GIVEN
CLAUDE_REVIEW_ALLOWLISTis["ClemDNL"], WHENClemDNLopens a fork pull request, THEN the pull request receives bothsafe-to-reviewandsafe-to-testlabels without a maintainer action. - GIVEN an allowlisted fork pull request has a new commit pushed, WHEN the preview workflow handles the
synchronizeevent, THEN the preview deploy job remains eligible throughCLAUDE_REVIEW_ALLOWLISTand any existing approval labels remain present. - GIVEN an unallowlisted fork pull request has
safe-to-test, WHEN its contributor pushes a follow-up commit, THENsafe-to-testremains present and the preview deploy job is eligible for the current head on thesynchronizeevent. - GIVEN an unallowlisted fork pull request has
safe-to-review, WHEN its contributor pushes a follow-up commit, THENsafe-to-reviewremains present and the OpenCode fork-review job is eligible for the current head on thesynchronizeevent. - GIVEN a maintainer removes an approval label from a fork pull request, WHEN the contributor pushes another commit, THEN the corresponding workflow path is not authorized by that removed label.
- GIVEN a fork pull request has received its initial review, WHEN its contributor pushes another commit, marks it ready for review, or reopens it, THEN the Claude review workflow does not run again.
- GIVEN a fork contributor is absent from
CLAUDE_REVIEW_ALLOWLIST, WHEN they open or update their pull request withoutsafe-to-review, THEN the fork review job does not run. - GIVEN a fork contributor is absent from
CLAUDE_REVIEW_ALLOWLIST, WHEN they open a pull request, THEN the automatic labeling job adds neither approval label and the preview workflow does not deploy unless its existingPREVIEW_ENV_ALLOWLISTorsafe-to-testpath authorizes it. - GIVEN a maintainer applies
safe-to-reviewto a fork pull request, WHEN the labeled event runs, THEN the existing maintainer-approved review path remains available. - GIVEN a maintainer wants another review round, WHEN they comment
@claude reviewon the pull request, THEN the existing Claude mention workflow recognizes the@claudemention and starts the requested review. - GIVEN a pull request adds a file after its initial review, WHEN a maintainer comments
@claude review, THEN Claude can read and review that added file rather than ending without a review because the file is absent from the default-branch checkout. - GIVEN a changed file depends on code outside its diff hunks, WHEN Claude performs a manual review, THEN it can explore the trusted default-branch codebase and request the complete UTF-8 version of a specific file from the current PR head for semantic context.
- GIVEN a user mentions
@claudeon an issue that is not a pull request, WHEN the generic Claude mention workflow runs, THEN it continues to use the default-branch checkout. - GIVEN a pull request changes Claude project settings or repository instructions, WHEN a maintainer comments
@claude review, THEN the trusted default branch remains the agent workspace and pull request content is read only through constrained GitHub commands or the bound GET-only file helper.
Out of scope
- Changing the pinned Claude Code Action version.
- Changing the Claude OAuth token, GitHub token, or OIDC strategy.
- Creating a second preview-specific allowlist or removing
PREVIEW_ENV_ALLOWLIST. - Changing the Claude automatic follow-up review policy; approval-label persistence does not add a
synchronizetrigger to the Claude review workflow. - Changing the automatic review behavior for same-repository pull requests.