Emit unsigned normalization attestations with --attest - #41
Merged
Merged
Conversation
There was a problem hiding this comment.
🟢 Approval recommended
The implementation matches the stated contract (determinism, opt-in behavior, write ordering, and gate semantics) and is backed by targeted unit and CLI tests.
Pull request overview
This pull request adds optional in-toto Statement v1 emission to rio normalize so each normalized SBOM can be accompanied by an unsigned, deterministic attestation that binds the output digest to the complete per-artifact index record plus tool and manifest identity. This fits rio’s model of producing offline, self-contained run artifacts (SBOMs + index.json) that downstream tooling can later sign/verify.
Changes:
- Adds
--attesttorio normalizeto write<artifact-id>.intoto.jsonstatements (unsigned) beforeindex.json. - Introduces
internal/index.MarshalStatementsto generate deterministic, pretty-printed Statement v1 JSON using the normalized index representation. - Documents the predicate contract and local-path semantics in
README.md, and notes the planned signing tooling intools/README.md.
File summaries
| File | Description |
|---|---|
| tools/README.md | Adds documentation pointing to the new attestation contract and clarifies that signing/verification is planned (issue #14). |
| README.md | Documents --attest, the Statement v1 contract, predicate type, determinism guarantees, and path semantics. |
| internal/index/attestation.go | Implements Statement v1 marshaling per artifact, reusing index normalization to preserve shape and determinism. |
| internal/index/attestation_test.go | Adds unit tests ensuring lossless artifact/tool/manifest round-tripping, normalization behavior, and invalid-index rejection without partial output. |
| internal/cli/normalize.go | Wires --attest into normalize flow; writes statements after SBOMs and before index.json, preserving existing bytes when flag is absent. |
| internal/cli/attest_test.go | Adds end-to-end CLI tests for opt-in behavior, determinism, digest agreement with on-disk files, gate-mode behavior, and write-failure handling. |
Review details
- Files reviewed: 6/6 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
rio normalize --attestnow writes one unsigned in-toto Statement v1 per normalized SBOM. Each statement binds the output digest to the complete artifact record plus the tool and manifest identity, so consumers can sign the normalization claim in the follow-up tooling.Statements use
<artifact-id>.intoto.jsonand the versionedhttps://rebaze.com/attestation/sbom-normalization/v1predicate. They preserve every index artifact field, including optional integrity findings, and are written atomically beforeindex.json. Gate failures still produce statements under both gate modes. Existing SBOM and index bytes are unchanged.The README documents the predicate and local-path semantics. Statements remain unsigned; signing and verification tooling is tracked in #14.
Validation:
go test -race ./..., including the no-network import checkgo vet ./...,go mod tidy -diff, formatting and diff checksCGO_ENABLED=0 go build -trimpath -o rio ./cmd/rioand CLI help smoke checksFixes #13