Parent: #750
Depends on: cluster fingerprint child issue (filed alongside), #739 (BOM)
Summary
Define a versioned, signed evidence bundle format and add aicr validate --emit-evidence <out> that produces it. The bundle is what a community contributor attaches to a recipe PR; aicr verify-evidence (separate child issue) consumes it.
Format — in-toto attestation with custom AICR predicate
The bundle is a single tar.gz archive whose payload is an in-toto Statement carrying a custom predicate. The Statement is signed via cosign keyless OIDC (matching aicr bundle --attest); KMS support is deferred.
Predicate type: https://aicr.nvidia.com/recipe-evidence/v1
Predicate fields (illustrative):
{
"_type": "https://in-toto.io/Statement/v1",
"predicateType": "https://aicr.nvidia.com/recipe-evidence/v1",
"subject": [{
"name": "recipe:<recipe-name>",
"digest": { "sha256": "<canonical-recipe-yaml-hash>" }
}],
"predicate": {
"schemaVersion": "1.0.0",
"aicrVersion": "<v>",
"validatorCatalogVersion": "<v>",
"validatorImages": { "<name>": "<digest>" },
"recipe": "<canonical YAML>",
"snapshot": "<snapshot YAML>",
"fingerprint": { ... },
"fingerprintMatch": { "matched": true, "diff": [] },
"phases": {
"deployment": { "status": "passed", "ctrf": {...}, "logs": [...] },
"performance": { "status": "passed", "ctrf": {...}, "logs": [...] },
"conformance": { "status": "passed", "ctrf": {...}, "logs": [...] }
},
"bom": { "ref": "bom.cdx.json", "digest": "sha256:..." },
"manifest": { "files": [...], "hashes": {...} }
}
}
The tarball layout:
evidence-bundle.tar.gz
├── attestation.intoto.jsonl # signed in-toto Statement
├── recipe.yaml # subject material
├── snapshot.yaml # subject material
├── bom.cdx.json # CycloneDX from #739
├── phases/
│ ├── deployment/{ctrf.json, logs/*}
│ ├── performance/{ctrf.json, logs/*}
│ └── conformance/{ctrf.json, logs/*}
└── manifest.json # file inventory + content hashes
The attestation references content by hash; the supporting files are bundled alongside for reviewer convenience and offline verification.
Why in-toto + cosign
- Sigstore tooling verifies it natively today.
- Custom predicate gives us schema control without forking standards.
- Path forward to SLSA Verification Summary Attestation (VSA) interop later — a VSA can be derived from this bundle.
- Rekor transparency log entry on signing gives durable third-party-verifiable provenance.
Proposed approach
- Specify the schema as a versioned JSON Schema document under
docs/spec/recipe-evidence-v1.md (or api/). Treat it as a public stability boundary.
- Implement
pkg/evidence/bundle (or extend pkg/evidence) with a Build(ctx, opts) (Bundle, error) API that takes recipe + snapshot + per-phase results + BOM and returns a signed bundle.
- Wire
aicr validate --emit-evidence <out> so a successful (or even failed — still useful) validation run produces the bundle.
- Use cosign keyless OIDC by default; make the signing surface pluggable so KMS can land later without breaking callers.
- Cover with unit tests for predicate construction + integration tests for end-to-end bundle creation against a kwok cluster.
Success criteria
aicr validate --recipe r.yaml --snapshot s.yaml --emit-evidence ./out/ produces a single tar.gz containing the signed in-toto attestation and supporting material.
- The attestation is verifiable with vanilla
cosign verify-blob-attestation against the public Rekor log (no AICR-specific tooling needed for raw verification).
- Schema is documented and versioned; predicate type is
https://aicr.nvidia.com/recipe-evidence/v1.
- Round-trip test: the bundle can be unpacked, the predicate parsed, every referenced file's digest matches, and the recipe-snapshot fingerprint binding holds.
Out of scope
- The verifier UX (
aicr verify-evidence) — separate child issue.
- KMS-backed signing — future extension.
- Long-term storage / hosting of bundles.
Parent: #750
Depends on: cluster fingerprint child issue (filed alongside), #739 (BOM)
Summary
Define a versioned, signed evidence bundle format and add
aicr validate --emit-evidence <out>that produces it. The bundle is what a community contributor attaches to a recipe PR;aicr verify-evidence(separate child issue) consumes it.Format — in-toto attestation with custom AICR predicate
The bundle is a single tar.gz archive whose payload is an in-toto Statement carrying a custom predicate. The Statement is signed via cosign keyless OIDC (matching
aicr bundle --attest); KMS support is deferred.Predicate type:
https://aicr.nvidia.com/recipe-evidence/v1Predicate fields (illustrative):
{ "_type": "https://in-toto.io/Statement/v1", "predicateType": "https://aicr.nvidia.com/recipe-evidence/v1", "subject": [{ "name": "recipe:<recipe-name>", "digest": { "sha256": "<canonical-recipe-yaml-hash>" } }], "predicate": { "schemaVersion": "1.0.0", "aicrVersion": "<v>", "validatorCatalogVersion": "<v>", "validatorImages": { "<name>": "<digest>" }, "recipe": "<canonical YAML>", "snapshot": "<snapshot YAML>", "fingerprint": { ... }, "fingerprintMatch": { "matched": true, "diff": [] }, "phases": { "deployment": { "status": "passed", "ctrf": {...}, "logs": [...] }, "performance": { "status": "passed", "ctrf": {...}, "logs": [...] }, "conformance": { "status": "passed", "ctrf": {...}, "logs": [...] } }, "bom": { "ref": "bom.cdx.json", "digest": "sha256:..." }, "manifest": { "files": [...], "hashes": {...} } } }The tarball layout:
The attestation references content by hash; the supporting files are bundled alongside for reviewer convenience and offline verification.
Why in-toto + cosign
Proposed approach
docs/spec/recipe-evidence-v1.md(orapi/). Treat it as a public stability boundary.pkg/evidence/bundle(or extendpkg/evidence) with aBuild(ctx, opts) (Bundle, error)API that takes recipe + snapshot + per-phase results + BOM and returns a signed bundle.aicr validate --emit-evidence <out>so a successful (or even failed — still useful) validation run produces the bundle.Success criteria
aicr validate --recipe r.yaml --snapshot s.yaml --emit-evidence ./out/produces a single tar.gz containing the signed in-toto attestation and supporting material.cosign verify-blob-attestationagainst the public Rekor log (no AICR-specific tooling needed for raw verification).https://aicr.nvidia.com/recipe-evidence/v1.Out of scope
aicr verify-evidence) — separate child issue.