feat: GitHub Action with Sigstore attestation and pinned-version verification (#6) - #17
Conversation
Incomplete TDD state; resume from here. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In GitHub Actions the report's verification block upgrades to verified, recording provider, repository, workflow ref, run id/url, and a pointer to the Sigstore attestation with the exact gh verify command. Outside CI the explicit unverified block stands. The HTML verification section now surfaces the producing workflow identity and verify command. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fication docs - action.yml builds the CLI from the pinned action source, generates report.json + report.html, attests report.json with actions/attest-build-provenance, and uploads artifacts. All step actions pinned by commit SHA. - .github/workflows/coderepute-report.yml is the canonical reusable workflow: its job_workflow_ref is the machine-checkable identity, so gh attestation verify --signer-workflow fails for modified forks; it checks out the action source at github.job_workflow_sha so the binary cannot diverge from the pinned version. - .github/workflows/demo-report.yml: workflow_dispatch demo exercising both consumption paths against this repository. - docs/verification.md documents the trust chain, the two-step verification, exactly what passing proves, and platform requirements. - README gains a CI usage section. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
workflow_dispatch is not dispatchable until the workflow exists on the default branch; a push trigger scoped to this branch gives a live run. Removed before merge. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The restricted job token blocked the CLI's pull list with 403 Resource not accessible by integration. Documented in the action header, the reusable-workflow usage snippet, README, and verification docs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Persisting attestations is unavailable for user-owned private repos; this lets the demo upload the CI-produced report artifact as evidence. Temporary, removed before merge with the push trigger. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… claim Removes the temporary branch push trigger and the attest skip used to capture live evidence while the repo is private. Adds a docs note that the report's verification block is untrusted until gh attestation verify passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0f3b9f5 to
6976761
Compare
Pre-review rebaseRebased Conflicted files and resolutions
No other files conflicted. This branch did not touch Test results
|
Review round 1 — approvedIndependent review of PR #17 against issue #6. Built, vetted, and tested the rebased head Acceptance criteria
Security
Parallel-work contractClean. Diff vs Owner follow-up (required to close the loop on criterion 1)Once the repo is public (or from any public consumer repo pinning this workflow): gh workflow run demo-report.yml -R grkanitz/CodeRepute
gh run download <run-id> -R grkanitz/CodeRepute -n coderepute-report-reusable -D out
gh attestation verify out/report.json --repo grkanitz/CodeRepute
gh attestation verify out/report.json --repo grkanitz/CodeRepute \
--signer-workflow grkanitz/CodeRepute/.github/workflows/coderepute-report.ymlThe last command is the fork-fails check and must pass only for artifacts attested by the canonical workflow. |
Closes #6
Summary
The GitHub trust chain for CodeRepute reports:
report/verification.go, new): inside GitHub Actions the report's mandatoryverificationblock upgrades toverifiedand recordsprovider,repository,workflow_ref,run_id,run_url, plus anattestationpointer (type, attestations URL, exactgh attestation verifycommand). Outside CI the explicitunverifiedblock fromBuildstands — the CLI never claims more than its environment proves. The CLI seam is additive: onereport.CIVerification(getenv)call incmd/coderepute/main.go.action.yml, new): builds the CLI from the action's own pinned source, generatesreport.json+report.html, attestsreport.jsonwithactions/attest-build-provenance, uploads both as artifacts. All step actions pinned by commit SHA..github/workflows/coderepute-report.yml, new): the machine-checkable identity. Consumers pingrkanitz/CodeRepute/.github/workflows/coderepute-report.yml@vX.Y.Z; the Sigstore certificate'sjob_workflow_refthen names this file at the pinned version, sogh attestation verify --signer-workflow grkanitz/CodeRepute/.github/workflows/coderepute-report.ymlfails for a modified fork. It checks out the action source atgithub.job_workflow_sha, so the binary cannot diverge from the pinned workflow version.docs/verification.md, new): the trust chain, the two-step verification (attestation + workflow-identity-vs-canonical-action), exactly what passing proves and what it does not, pinned-version convention, platform requirements. README gains a CI usage section..github/workflows/demo-report.yml, new):workflow_dispatch, exercises both consumption paths against this repo.Test output
Live demo evidence (runs 27398528483, 27398606723)
workflow_dispatchis not dispatchable until the workflow exists on the default branch, so the demo was run live via a temporary branch-scopedpushtrigger (removed again in the final commit).What the live runs proved end-to-end on a real runner:
report.jsonfrom run 27398606723 (artifactcoderepute-report-action):GitHub artifact attestations require a public repository (or GitHub Enterprise Cloud for private ones). This repo is user-owned private, so no plan setting unblocks it short of going public.
Post-merge verification (once the repo is public, or from any public consumer repo)
The last command is the fork-fails check: an artifact attested by a fork's copy of the workflow carries a different
job_workflow_refand fails.Parallel-work contract
Shared files touched, all additive:
report/report.go(new optional fields on theVerificationsub-struct I own),cmd/coderepute/main.go(one 3-line CI seam),README.md(new section),render/render_test.go+cmd/coderepute/main_test.go(new tests only),render/templates/sections/20-verification.tmpl(verification section, my territory). No metrics,ActivitySet, collaboration/cadence/coverage, or adapter files touched.🤖 Generated with Claude Code