5.3 KiB
spec, created, status
| spec | created | status |
|---|---|---|
| docs/specs/integrations/requirements/claude-fork-review-allowlist.md | 2026-08-22 | implemented |
Implementation Plan: Persist Fork Approval Labels
Overview
Change the fork approval workflows so safe-to-test and safe-to-review are
durable maintainer approvals. Remove the synchronize-time cleanup jobs, allow
the existing label paths on follow-up pushes, and add contract coverage that
prevents either workflow from silently returning to per-commit re-approval.
Update the related security decision and allowlist spec in the same change.
Confirmed root cause
PR #2815 is a fork pull request. The GitHub audit trail shows both labels added
by a maintainer and later removed by github-actions[bot] after contributor
pushes. The corresponding successful workflow runs executed
strip-safe-to-test and strip-safe-to-review. The jobs and the
event.action != 'synchronize' guards are explicit in the current workflow
files.
Workflow changes
.github/workflows/preview-env.yml- Keep
safe-to-testin thedeploy-forkauthorization expression. - Remove the
github.event.action != 'synchronize'exclusion from that label path so an existing approval authorizes the current fork head after pushes. - Remove the
strip-safe-to-testjob and stale per-commit comments.
- Keep
.github/workflows/opencode-code-review.yml- Keep
safe-to-reviewin the fork review authorization expression. - Remove the synchronize exclusion from that label path.
- Remove the
strip-safe-to-reviewjob and stale per-commit comments.
- Keep
.github/workflows/lint-action-pinning.yml- Run the OpenCode workflow contract test in the existing always-on workflow contract suite.
Contract tests
.github/scripts/preview-env-workflow-contract_test.py- Assert the preview workflow keeps the label authorization path.
- Assert the synchronize exclusion and
strip-safe-to-testjob are absent.
.github/scripts/opencode-code-review-workflow-contract_test.py- Add focused coverage for the fork label gate, synchronize eligibility, and
absence of
strip-safe-to-review/removeLabelcleanup.
- Add focused coverage for the fork label gate, synchronize eligibility, and
absence of
- Keep the Claude workflow contract test passing to prove the separate open/labeled-only Claude review policy remains unchanged.
Documentation and decision records
- Amend
docs/specs/integrations/requirements/claude-fork-review-allowlist.mdwith durable-label scenarios and the changed OpenCode/preview behavior. - Amend
docs/decisions/2026-08-07-claude-allowlist-label-bridge.mdto point the superseded per-commit clause at the new decision. - Add
docs/decisions/2026-08-22-persistent-fork-approval-labels.mdand index it indocs/decisions/INDEX.md.
Tests
- What: The preview label path authorizes a fork
synchronizeevent and no cleanup job removessafe-to-test. File:.github/scripts/preview-env-workflow-contract_test.py. How: Read the workflow text and assert the label expression remains, the synchronize exclusion is absent, and the cleanup job is absent. - What: The OpenCode label path authorizes a fork
synchronizeevent and no cleanup job removessafe-to-review. File:.github/scripts/opencode-code-review-workflow-contract_test.py. How: Read the workflow text and assert the trigger, label gate, and absence of cleanup and synchronize exclusion. - What: Existing fork allowlist labeling and Claude review behavior remain
intact.
File:
.github/scripts/claude-code-review-workflow-contract_test.py. How: Run the existing contract suite without changing its open/labeled assertions.
Verification commands
Run from the repository root:
python3 .github/scripts/preview-env-workflow-contract_test.py
python3 .github/scripts/opencode-code-review-workflow-contract_test.py
python3 .github/scripts/claude-code-review-workflow-contract_test.py
python3 .github/scripts/lint-action-pinning_test.py
python3 .github/scripts/lint-action-pinning.py
zizmor .github/workflows
git diff --check
Implementation Waves
Wave 1 (sequential; one coupled security-boundary change):
Risks and out of scope
- This intentionally makes a maintainer label approval apply to future fork heads. Maintainers must remove labels when trust should be revoked.
CLAUDE_REVIEW_ALLOWLISTand the other direct allowlist paths remain independent and fail-closed.- The Claude review workflow does not gain a
synchronizetrigger in this change. This task does not alter same-repository review behavior or add a new token/App-based label event bridge.
Verification Results
- RED: The new preview and OpenCode contract assertions failed against the pre-change workflows because the synchronize exclusions and cleanup jobs were still present.
- GREEN:
preview-env-workflow-contract_test.py(2 tests),opencode-code-review-workflow-contract_test.py(3 tests), and the existingclaude-code-review-workflow-contract_test.py(9 tests) pass. - Security checks:
lint-action-pinning_test.py(9 tests) andlint-action-pinning.pypass;git diff --checkpasses. zizmor .github/workflowsran but exits non-zero on existing repository-wide findings, including pre-existing dangerous-trigger, permissions, artifact, cache, and template-injection findings. This change did not expand that audit scope.