fix(evidence): pull by digest and auto-tag pushes instead of :v1#1168
Conversation
Evidence verification pulled the OCI artifact by the pointer's bundle.oci tag, then checked the pulled digest against bundle.digest. Because the tag is registry-rewritable, a later push to the same tag floated it to a different artifact and broke re-verification of any already-committed pointer. The push side made this worse by defaulting every tag-less push to a shared ":v1", so unrelated recipes collided on one tag immediately. Verifier: when the pointer carries a content digest, pull by digest (registry/repo@sha256:... derived from bundle.oci) rather than by the tag, so the exact attested bytes are fetched regardless of tag drift. The post-pull digest cross-check stays as defense-in-depth. Emitter: drop the ":v1" default. When --push omits a tag, derive a unique per-recipe tag, <recipe-slug>-<fingerprint>, where the fingerprint is the first 12 hex of the bundle's manifest digest (deterministic, not random). Push now requires an explicit tag; tag derivation lives in the emit/publish orchestration. An operator-supplied tag is still honored. Docs: explain that the sha256 digest is the canonical pin (verify pulls by digest), the tag is a human-readable label, and aicr auto-derives a unique one; correct the pointer-pull description across the CLI reference, demo, validation, and recipe-development guides. Tests: cover pointerPullRef, deriveEvidenceTag/sanitizeOCITag/ manifestFingerprint, and Push's tag-required error.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (10)
💤 Files with no reviewable changes (1)
📝 WalkthroughWalkthroughThis PR refactors evidence attestation push and verification to support optional OCI tags with automatic per-recipe derivation. The push pipeline now requires explicit tags at the Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Summary
Make recipe-evidence verification pin on the content digest and stop defaulting
evidence pushes to a shared
:v1tag — so a committed pointer stays verifiableregardless of registry tag drift, and distinct attestations never collide on one
tag. Includes the doc clarifications that motivated the change.
Motivation / Context
aicr evidence verifypulled the OCI artifact by the pointer'sbundle.ocitag, then checked the pulled digest against
bundle.digest. Because tags areregistry-rewritable, a later push to the same tag floated it to a different
artifact and broke re-verification of any already-committed pointer (the pull
returned the new artifact; the digest check then failed). The push side made this
worse: every tag-less
--pushdefaulted to a shared:v1, so unrelated recipescollided on one tag immediately. Users and agents also tended to copy the
human-readable
bundle.ocitag intoverify, which refuses tag-only refs.Fixes: N/A
Related: N/A
Type of Change
Component(s) Affected
docs/,examples/)pkg/evidence(recipe-evidence emit + verify)Implementation Notes
pkg/evidence/verifier/fetch.go): when the pointer carries acontent digest,
materializeFromPointernow pulls by digest(
registry/repo@sha256:…derived frombundle.ocivia the newpointerPullRef), not by the tag — so the exact attested bytes are fetched evenif the tag has since moved. The post-pull digest cross-check stays as
defense-in-depth. The no-digest path (local pointer +
--bundle) is unchanged.pkg/evidence/attestation): dropped the:v1default. When--pushomits a tag, the emit/publish orchestration derives a unique per-recipetag,
<recipe-slug>-<fingerprint>, where the fingerprint is the first 12 hex ofthe bundle's manifest digest (deterministic, not random). An operator-supplied
tag is still honored.
attestation.Pushnow returnsErrCodeInvalidRequestif handed a tag-less reference instead of silentlydefaulting — tag derivation is the orchestration layer's responsibility
(
effectiveEvidenceRef). Both real flows (validate --emit-attestationandevidence publish) derive a tag first, so this only affects direct API callers.explain that the
sha256:digest is the canonical pin (verify pulls by digest),the tag is a human-readable label, and aicr auto-derives a unique one.
Testing
New tests:
pointerPullRef(digest-pinning, tag drop, passthrough, invalid ref);deriveEvidenceTag/sanitizeOCITag/manifestFingerprint;Pushtag-requirederror. Per-package coverage:
pkg/evidence/attestation72.8%,pkg/evidence/verifier64.7% (new functions covered).
Risk Assessment
changes an exported function's contract (
Pushnow requires a tag).Rollout notes: Backward-compatible for existing committed pointers — they carry
bundle.digest, so verification now pulls by digest (and can even re-verifypointers whose tag had drifted, as long as the digest still resolves). No pointer
schema change.
Checklist
make testequivalent on affected packages, with-raceviago test)golangci-lint, 0 issues)git commit -S)