Part of #1431.
Summary
Let AICR produce a "mostly-formed" pointer and bundle without a signature, and add a separate path that signs an already-pushed bundle and patches its pointer in place. This decouples the network-light work (compute digest, assemble bundle, push to registry, write pointer skeleton) from the Fulcio-bound work (sign + log to Rekor + fill in signer identity/index). Today signing is mandatory whenever --push is set — there is no no-sign path — which couples the whole flow to a network that can reach Fulcio.
Motivation / Context
- The pointer types already model an unsigned state:
signer.rekorLogIndex is a pointer that is nil when unsigned (pkg/evidence/attestation/types.go). The schema supports it; the CLI doesn't produce it.
- This is what the fork-based signing workflow consumes: contributor publishes unsigned + commits pointer locally; CI fills in the signature.
Proposed approach
(a) Push-without-sign: add --no-sign (or --unsigned) to validate --emit-attestation and/or evidence publish that:
- assembles the bundle and pushes it to the registry (content-addressed, unsigned), and
- writes a pointer with
bundle.oci / bundle.digest populated and signer empty / rekorLogIndex nil.
(b) Sign-existing: add an evidence sign <pointer> path (or extend evidence publish) that takes the already-pushed bundle referenced by the pointer, signs it with ambient OIDC, logs to Rekor, and patches the pointer's signer block in place — without re-emitting the bundle. This is exactly what the fork workflow calls.
(c) Verifier: evidence verify should treat an unsigned pointer as a distinct "pending signature" status rather than "invalid," so an in-flight PR isn't flagged as broken (gate stays warning-only).
Acceptance criteria
References
pkg/evidence/attestation/types.go (Pointer, PointerSigner.RekorLogIndex *...)
pkg/evidence/attestation/pointer.go, publish.go
pkg/cli/evidence_publish.go, pkg/cli/validate.go
- Unblocks the fork-based signing workflow issue.
Part of #1431.
Summary
Let AICR produce a "mostly-formed" pointer and bundle without a signature, and add a separate path that signs an already-pushed bundle and patches its pointer in place. This decouples the network-light work (compute digest, assemble bundle, push to registry, write pointer skeleton) from the Fulcio-bound work (sign + log to Rekor + fill in signer identity/index). Today signing is mandatory whenever
--pushis set — there is no no-sign path — which couples the whole flow to a network that can reach Fulcio.Motivation / Context
signer.rekorLogIndexis a pointer that is nil when unsigned (pkg/evidence/attestation/types.go). The schema supports it; the CLI doesn't produce it.Proposed approach
(a) Push-without-sign: add
--no-sign(or--unsigned) tovalidate --emit-attestationand/orevidence publishthat:bundle.oci/bundle.digestpopulated andsignerempty /rekorLogIndexnil.(b) Sign-existing: add an
evidence sign <pointer>path (or extendevidence publish) that takes the already-pushed bundle referenced by the pointer, signs it with ambient OIDC, logs to Rekor, and patches the pointer'ssignerblock in place — without re-emitting the bundle. This is exactly what the fork workflow calls.(c) Verifier:
evidence verifyshould treat an unsigned pointer as a distinct "pending signature" status rather than "invalid," so an in-flight PR isn't flagged as broken (gate stays warning-only).Acceptance criteria
aicr ... --no-signproduces a committable pointer with bundle digest set and signer empty, and pushes the unsigned bundle.signer.identity,signer.issuer,signer.rekorLogIndexfrom the committed pointer without re-emitting the bundle.evidence verifyreports unsigned pointers as a non-failing "pending" state.pkg/evidence/attestation.References
pkg/evidence/attestation/types.go(Pointer,PointerSigner.RekorLogIndex *...)pkg/evidence/attestation/pointer.go,publish.gopkg/cli/evidence_publish.go,pkg/cli/validate.go