Skip to content

feat(ci): aggregate target-scoped verification receipts - #354

Closed
MChorfa wants to merge 13 commits into
sbom-tool:mainfrom
MChorfa:feat/pipeline-receipt-fan-in
Closed

MChorfa wants to merge 13 commits into
sbom-tool:mainfrom
MChorfa:feat/pipeline-receipt-fan-in

Conversation

@MChorfa

@MChorfa MChorfa commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

Deferred workflow reference

This draft preserves the producer/fan-in experiment and maintainer corrections
at 877d544dc78258a52136fa8b1442fe51ff3bd500. It is not proposed for merge.

The agreed first unit is now the single contract-only PR #353, directly based
on current upstream main. Its scope is Rust contracts, schemas, local
generation/verification, documentation, schema-binding tests, and cross-OS
fingerprint tests. It carries applicable fixes from this branch without its
workflow/action/job-manifest changes.

Later workflow adoption requires the baseline, source-of-truth topology,
reusable CLI/cache measurement, trust model, and artifact-transport recovery
criteria recorded in #350. Cargo-deny advisories remain informational. The
earlier passing checks on this reference do not establish workflow approval
or a performance improvement.

Mohamed Chorfa added 7 commits August 29, 2026 19:33
Establish a versioned, fail-closed receipt and aggregation
boundary before workflow fan-in is wired. Unsigned v1 receipts
cannot authorize promotion, and local filesystem fingerprint
generation remains non-promotable.

Refs sbom-tool#350
Keep digest and trust-context derivation in tested Rust instead of
workflow shell logic. Hosted metadata remains self-asserted and all
v1 receipts are unsigned and non-promotable.

Refs sbom-tool#350
Keep the receipt foundation green while upstream review completes
on the dedicated remediation in PR sbom-tool#352.
CodeQL treats policy-derived aggregate cardinalities as sensitive
data reaching cleartext output. Keep the public aggregate result while
emitting only a constant CLI success message.

Refs sbom-tool#350
Keep runtime digest and trust derivation in tested Rust so static
manifests can define target topology without embedding gate logic in
workflow YAML. Generated policies remain unsigned and non-promotable.

Refs sbom-tool#350
Translate checked-in shard manifests and hosted runner outcomes into
validated receipts without embedding evidence rules in workflow shell.
Runner identity and context mismatches fail closed.

Refs sbom-tool#350
Make Rust and Bindings jobs publish one fail-closed receipt per
native target, then preserve CI and add a Bindings fan-in gate over
checked-in topology and lock contracts.

Refs sbom-tool#350
Mohamed Chorfa added 3 commits August 29, 2026 22:00
Git Bash receives Windows-style RUNNER_TEMP values, so normalize them before snapshot and receipt filesystem operations while retaining native artifact upload paths.
Encode source and lock path identities with forward-slash-separated UTF-8 components before hashing. This keeps identical Git archives fingerprint-equivalent across Linux, macOS, and Windows runners.

Refs: sbom-tool#350
Disable checkout line-ending conversion while creating exact-SHA receipt snapshots. Add an action contract test that rejects environment-dependent archive generation.

Refs: sbom-tool#350
@MChorfa

MChorfa commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Exact-head hosted verification: 24bd0b6222013843632dcf62bdb833a558644a27

  • 26 passed
  • 0 failed
  • 0 pending
  • 1 expected skip: Bench run (baseline)
  • Bindings aggregate: passed in 2m01s
  • preserved Rust CI aggregate: passed in 1m56s
  • Linux, macOS, and Windows producers: passed
  • Dagger CI: passed in 12m46s

The fan-in path is now verified on the exact PR head. The two prior failed runs remain documented as evidence of fail-closed behavior and the cross-platform snapshot corrections.

Boundary: this is an unsigned, non-promotable receipt slice. The PR remains draft, review-required, and stacked behind #353/#352. No performance improvement is claimed; the additional receipt CLI builds remain measured overhead to address in the next optimization slice.

@matrosov

Copy link
Copy Markdown
Member

On hold pending the design discussion on #350 — see #350 (comment) (defect items 6–9 apply here on top of 1–5 from the foundation). One thing that comes out regardless of where the design lands: the cargo-deny advisories flip from informational to blocking reverses a deliberate repo policy and isn't part of any slice — that's a separate maintainer decision.

alexm-anthropic and others added 3 commits August 30, 2026 20:35
Addresses the nine confirmed findings from the maintainer review on
issue sbom-tool#350 (see the defect-list comment there):

- Root-anchor the source-fingerprint exclusions and make them
  directory-only; symlinks are rejected before exclusion so an excluded
  name cannot mask one. Nested vendored target/ dirs and files named
  "receipts" now stay in the evidence.
- Unify exit-code classification: read_receipt and the aggregate policy
  loader now two-phase parse like the generator paths, so malformed
  JSON is operational (exit 3) and readable-but-violating documents are
  gate verdicts (exit 1) on every receipt subcommand.
- Align serde strictness with the published schemas: nullable fields
  the schemas list as required (run_id, dagger_trace,
  failure_classification, binding_runtime, head_repository, hosted) now
  require key presence; is_portable_scope matches the schema pattern
  exactly (segments must start alphanumeric).
- Accept the unambiguous github.ref_name short forms (N/merge, default
  branch) in hosted classification; bare tag names stay rejected with a
  pointer at the canonical full-ref form. Documented in both schemas.
- Publish the two missing contracts: pipeline-shard-job-manifest/v1
  gets a schema file, and AggregatePolicy gains a schema discriminator
  (aggregate-policy/v1) with its own schema file, enforced on load.
- Bind schemas to code with a new test suite
  (pipeline_receipt_schema_binding_tests) covering pattern agreement,
  property/required parity, presence-strictness, and the checked-in job
  manifests.
- Replace the unsafe env::set_var test (UB under parallel libtest) with
  a subprocess that injects RUNNER_TEMP via child environment.
- Pin core.autocrlf/core.eol on the aggregate jobs' git archive so
  their snapshot matches emit-receipt byte-for-byte, with a contract
  test covering both workflows.
- Restore the deliberate advisories gating policy: cargo-deny
  advisories stays informational (continue-on-error) and leaves the
  receipt evidence set entirely, since a failed receipt would fail the
  aggregate closed and re-block PRs on surprise CVEs indirectly.
- Bound the new build cost: producer and aggregate jobs that build the
  receipt CLI share a receipt-cli rust-cache.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Lxk48j7VVWwJr3QUZEVm6
aggregate-policy-context/v1 lists hosted as required-but-nullable; the
struct now enforces key presence like the other nullable-required
fields.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015Lxk48j7VVWwJr3QUZEVm6
@MChorfa

MChorfa commented Sep 16, 2026

Copy link
Copy Markdown
Contributor Author

Closing this workflow experiment in favor of the agreed contract-only scope
in #353. Its applicable contract corrections have been carried into that PR.

Workflow adoption remains deferred under #350's baseline, artifact reuse,
trust, and recovery criteria. This branch and discussion remain available as
reference; closing the PR does not indicate that the workflow design was
approved or delivered.

The separate baseline CI repair is tracked in #369.

@MChorfa MChorfa closed this Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants