Part of #1431.
Summary
Add a GitHub Actions workflow that a contributor runs in their fork to complete the signing leg of evidence publishing. The contributor first does the network-light work locally with AICR: publish the unsigned bundle to their own registry and commit the pointer (see two-phase publish issue). The workflow then operates purely on the branch — it discovers any pointer in recipes/evidence/*.yaml whose signer is empty / rekorLogIndex is nil, signs the bundle that pointer already references (ambient OIDC → Fulcio/Rekor), patches the pointer's signer block in place, and commits it back. No recipe-name or bundle-ref inputs to thread through workflow_dispatch.
Why this shape
- Eliminates the friction of passing a bundle artifact or recipe name into the workflow — the committed pointer is the work item, and it already carries
bundle.oci + bundle.digest.
- The only step that genuinely needs Fulcio (signing) runs where Fulcio is reachable (Actions); everything else stays local and VPN-friendly. Sigstore keyless signing from a laptop is currently blocked on corporate VPN and some home networks (upstream Fulcio IP-level rejection).
- The signer becomes the GitHub Actions OIDC identity, not a personal one.
Contributor flow
- Local (on VPN, no Fulcio):
aicr validate ... --emit-attestation ./out --push ghcr.io/<owner>/aicr-evidence --no-sign → unsigned bundle pushed, pointer written with empty signer (two-phase publish issue).
- Make the fork's
aicr-evidence package public so verify pulls don't 403.
- Commit the pointer, push the branch.
- Workflow runs → signs, logs to Rekor, patches
signer.identity / issuer / rekorLogIndex, commits back.
Trigger — open design question (resolve in this issue)
- Option A (explicit):
workflow_dispatch only — predictable, no surprise commits, but one manual click.
- Option B (automatic on push): trigger on push to fork branches when an unsigned pointer is present. Lowest friction, but a workflow that commits back to the branch that triggered it needs loop-guards (skip when no unsigned pointers; don't re-trigger on its own signing commit) and clear behavior on forks where Actions /
id-token may be disabled by default.
- Recommend landing A first, with B as a fast-follow once the discover-and-patch path is proven.
Acceptance criteria
References
- Discovery target:
recipes/evidence/*.yaml; pkg/evidence/attestation/types.go (Pointer, nil RekorLogIndex = unsigned)
- Signing:
pkg/cli/evidence_publish.go sign-existing path; ambient OIDC pkg/bundler/attestation/oidc.go (FetchAmbientOIDCToken)
- Depends on the two-phase push-without-sign issue.
Part of #1431.
Summary
Add a GitHub Actions workflow that a contributor runs in their fork to complete the signing leg of evidence publishing. The contributor first does the network-light work locally with AICR: publish the unsigned bundle to their own registry and commit the pointer (see two-phase publish issue). The workflow then operates purely on the branch — it discovers any pointer in
recipes/evidence/*.yamlwhosesigneris empty /rekorLogIndexis nil, signs the bundle that pointer already references (ambient OIDC → Fulcio/Rekor), patches the pointer'ssignerblock in place, and commits it back. No recipe-name or bundle-ref inputs to thread throughworkflow_dispatch.Why this shape
bundle.oci+bundle.digest.Contributor flow
aicr validate ... --emit-attestation ./out --push ghcr.io/<owner>/aicr-evidence --no-sign→ unsigned bundle pushed, pointer written with empty signer (two-phase publish issue).aicr-evidencepackage public so verify pulls don't 403.signer.identity/issuer/rekorLogIndex, commits back.Trigger — open design question (resolve in this issue)
workflow_dispatchonly — predictable, no surprise commits, but one manual click.id-tokenmay be disabled by default.Acceptance criteria
.github/workflows/evidence-publish.yaml, runnable in a fork,permissions: id-token: write(+contents: writefor commit-back); no required inputs.aicr-evidencepackage must be reachable for verification — documented, and the workflow fails with a clear message if it can't pull the bundle it's about to sign (ties to the gate-error-feedback issue).References
recipes/evidence/*.yaml;pkg/evidence/attestation/types.go(Pointer, nilRekorLogIndex= unsigned)pkg/cli/evidence_publish.gosign-existing path; ambient OIDCpkg/bundler/attestation/oidc.go(FetchAmbientOIDCToken)