From 5576005855fe8124e7fcc23d2dfcae328c666fae Mon Sep 17 00:00:00 2001 From: 0xLeif Date: Sat, 4 Jul 2026 13:17:52 -0600 Subject: [PATCH 1/3] Add: record attest provenance on merged commits Wires attest into CI so spec-sync builds a signed-provenance ledger and its /trust/ attest pip lights (it was dark: spec-sync never ran attest). A dedicated main-only job records an attestation after the gates (test, fmt, audit, spec-check) pass and pushes refs/notes/attest. Public Linux binary, checksum- verified, no token; additive and best-effort, so it can never fail CI. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01ApSS1xj22zGwbUSkRs3mmE --- .github/workflows/ci.yml | 41 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4dd4f41..485db3bb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -229,3 +229,44 @@ jobs: review-on-pr: "true" context: ${{ steps.status.outputs.context }} job-status: ${{ steps.status.outputs.result }} + + attest: + name: Record attestation + runs-on: ubuntu-latest + needs: [test, fmt, audit, spec-check] + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + # contents: write lets the step push refs/notes/attest. + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + # After the gates pass, record a provenance attestation on this commit and + # push it to refs/notes/attest, so spec-sync builds a trust ledger (and its + # /trust/ attest pip lights). attest ships a public Linux binary + # (checksum-verified), so no token is needed; the step is additive and + # best-effort, so a hiccup logs a warning and never fails CI. + - name: Record attestation (attest) + env: + ATTEST_VERSION: v0.5.0 + run: | + base="https://github.com/CorvidLabs/attest/releases/download/${ATTEST_VERSION}" + bin="${RUNNER_TEMP}/attest"; sum="${bin}.sha256" + retry="--retry 5 --retry-connrefused --retry-delay 1" + if curl -fsSL $retry "${base}/attest-linux-x86_64" -o "$bin" \ + && curl -fsSL $retry "${base}/attest-linux-x86_64.sha256" -o "$sum" \ + && want="$(awk '{print $1}' "$sum")" && [ -n "$want" ] \ + && printf '%s %s\n' "$want" "$bin" | sha256sum -c - ; then + chmod +x "$bin" + git config user.email "github-actions[bot]@users.noreply.github.com" + git config user.name "github-actions[bot]" + git fetch origin "+refs/notes/attest:refs/notes/attest" 2>/dev/null || true + if "$bin" sign --commit HEAD --reviewer agent:ci --confidence 0.9 --tests-passed \ + --verdict proceed --note "CI: cargo test + fmt + audit + spec-check green" \ + && git push origin refs/notes/attest ; then + echo "attestation recorded for $(git rev-parse --short HEAD)" + else + echo "::warning::attest sign/push failed; provenance not recorded this run" + fi + else + echo "::warning::attest download/verify failed; provenance not recorded this run" + fi From 4fab4f4deefb724484b95db7ad894e957956dd17 Mon Sep 17 00:00:00 2001 From: 0xLeif Date: Mon, 6 Jul 2026 07:18:49 -0600 Subject: [PATCH 2/3] Gate the attestation on every CI job, not a subset Addresses review: the attest job recorded 'proceed' after only test/fmt/audit/ spec-check, so coverage, site, vscode-extension, or validate-action could fail on a main push while the attestation still signed off. Depend on all gate jobs. Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_01ApSS1xj22zGwbUSkRs3mmE --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 485db3bb..77c4cdc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -233,7 +233,10 @@ jobs: attest: name: Record attestation runs-on: ubuntu-latest - needs: [test, fmt, audit, spec-check] + # Depend on every gate job, not just a subset: an attestation records + # "proceed", so it must not sign off on a commit where any real check failed. + # (corvid-pet is a PR-comment mascot, not a gate, so it is intentionally out.) + needs: [test, fmt, audit, coverage, site, vscode-extension, validate-action, spec-check] if: github.event_name == 'push' && github.ref == 'refs/heads/main' # contents: write lets the step push refs/notes/attest. permissions: From 0288b34a888352505b3ddce28e4a1e4ac801d26e Mon Sep 17 00:00:00 2001 From: 0xLeif Date: Mon, 6 Jul 2026 19:13:14 -0600 Subject: [PATCH 3/3] Update: make attest note reflect full CI gating + checkout@v5 Addresses Kyntrin's CHANGES_REQUESTED on #327: - The attest job's `needs` already gates on all 8 merge-gating jobs (test, fmt, audit, coverage, site, vscode-extension, validate-action, spec-check) as of the prior commit, so a partial-CI failure can no longer record a "proceed" provenance note. Updated the now-stale --note text (it still read "cargo test + fmt + audit + spec-check green") to enumerate the full gate set so the ledger entry cannot be under- or mis-read. - Bumped the attest job's actions/checkout@v4 -> v5 for consistency with the rest of the workflow (non-blocking nit). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77c4cdc9..bee31dae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -242,7 +242,7 @@ jobs: permissions: contents: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # After the gates pass, record a provenance attestation on this commit and # push it to refs/notes/attest, so spec-sync builds a trust ledger (and its # /trust/ attest pip lights). attest ships a public Linux binary @@ -264,7 +264,7 @@ jobs: git config user.name "github-actions[bot]" git fetch origin "+refs/notes/attest:refs/notes/attest" 2>/dev/null || true if "$bin" sign --commit HEAD --reviewer agent:ci --confidence 0.9 --tests-passed \ - --verdict proceed --note "CI: cargo test + fmt + audit + spec-check green" \ + --verdict proceed --note "CI green: test, fmt, audit, coverage, site, vscode-extension, validate-action, spec-check" \ && git push origin refs/notes/attest ; then echo "attestation recorded for $(git rev-parse --short HEAD)" else