Repository navigation
feat: transcoding attestation protocol, Nix flake, SLSA L3 artifacts - #58
Merged
Merged
Conversation
…tifacts Phase 2.4: Implement TranscodingPredicate (wsc.dev/transcoding/v1) for carrying cryptographic provenance across the WASM→native compilation boundary. Builder pattern, in-toto Statement wrapper, 16 tests. Issue #48 / FEAT-3: Add flake.nix with Rust 1.90.0 (rust-overlay), Bazel 8, cargo-fuzz/audit/deny, direnv integration, and rust-toolchain.toml for reproducible builds (SLSA L3 prerequisite). Rivet artifacts: FEAT-6, DD-5, REQ-12, CR-17, CD-17, CD-18, CV-25, CV-26, DF-16 for full traceability of new work. Implements: FEAT-6, FEAT-3 Refs: CR-17, CD-17, CD-18 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5 tasks
avrabe
added a commit
that referenced
this pull request
Oct 21, 2026
…solve in CI With #307 unfreezing the rivet binary the compliance job stops panicking in Export and fails one step later, in Validate: `rivet validate` exited 1 on 22 errors, and the action's run_validate.sh (rivet #953) propagates that as the step's exit. So the compliance evidence for v0.12.0 stayed unobtainable even after the pin fix. This closes it: **Result: PASS, exit 0.** Every one of the 22 was mechanical, and all were fixed with `rivet modify` / `rivet link` rather than hand-edited YAML: **11 x off-vocabulary `status: in-progress`.** `in-progress` was never in rivet's canonical lifecycle (draft -> proposed -> approved -> implemented -> verified -> released, plus accepted/deprecated/rejected). rivet gained enforcement of that enum in REQ-162 / #352 — the value had been passing silently before. Mapped by checking each artifact against the code, not by picking whichever value validated: FEAT-2,6,7,8,9,10,11 -> implemented the implementing code exists — format/mcuboot.rs, transcoding.rs + intoto.rs, container/digest.rs + bundle.rs, keyless/proof_cache.rs, container/referrer.rs, formal-verification.yml, src/component CV-20, CV-21, CV-22 -> approved deliberately NOT `implemented`. These are the Verus and Rocq verification activities, and all three steps exit 1 behind continue-on-error today (CV-22 is a stub; audit C-1 records `assume(false)` in the Verus side). A verification that does not discharge is scoped, not implemented. REQ-14 -> approved its proofs are the three above. `draft` would have validated too, and for the coverage rules it is the cheaper answer — a draft artifact is exempt from them. That is exactly why it was not used: it would have bought a PASS by making the gate look away. `approved` keeps all three CVs and REQ-14 inside the coverage rules, which is where the 182 warnings come from. **6 x `satisfies` declared with zero targets** (DD-8..DD-13). Linked to the requirement each decision actually serves rather than deleting the empty key, which would only have moved DD-10's failure to the design-decision coverage rule: DD-8 -> REQ-17 HW-preferred verify with SW fallback <- the wsc:crypto hardware-verify interface with curve negotiation DD-9 -> REQ-15 "a wasm component via meld/loom/synth, NOT a hand-carved no_std staticlib" is the design choice FOR REQ-15 DD-10 -> REQ-19 MAX_SLICE_LEN = 256MB exists to hold the large embedded core-module section REQ-19 names DD-11 -> REQ-23 offline keyless verify: SET mandatory, Merkle not checked DD-12 -> REQ-23 offline verify cannot check SCTs (no CT key in the bundle) DD-13 -> REQ-24 DSSE extracted to wsc-dsse, not into wsc-verify-core **3 x undeclared `related-to` link type** (H-36/37/38). No STPA link type expresses hazard-to-hazard adjacency — `prevents` is constraint->hazard, `leads-to-hazard` is uca->hazard — so the relation had been written with a type the schema never declared, which made it unenforceable and invisible to coverage rules. Declared in schemas/stpa-sec.yaml (sigil's own on-disk schema) rather than deleted: that three hazards are variants of H-25, H-33/34 and H-14 is real analysis, and it is explicitly NOT `sub-hazard` — they are peers, so neither inherits the other's constraints. **1 x duplicate artifact id, which is the one real defect in the set.** CV-25 was declared twice in the same file: "Transcoding attestation roundtrip test" (#58) and "Mechanised sister logic for compositional attestation-chain trust" (#94). rivet's own words: "the second definition silently overwrites the first" — so since #94 the transcoding roundtrip verification has not been in the trace at all, along with its `verifies` link. The newcomer is renumbered to CV-35 (`rivet next-id`); the original keeps CV-25. Nothing else referenced the id, so no links needed rewiring. This is the one edit made by hand: rivet can *detect* a duplicate id but offers no `--set-id` and no rename/renumber subcommand, so there is no command to do it with. Filed as friction in rivet. Both callers of the compliance action now clone synth before invoking it. rivet.yaml declares `synth` as an external at ../synth, and ONE unresolvable external makes rivet abandon cross-ref checking for all of them — reporting "cross-refs NOT CHECKED — externals failed to load" and counting sigil's 9 valid synth links as broken. A single-repo checkout has no sibling, so CI saw 31 errors where a developer with ../synth checked out saw 22. #307's kiln removal does nothing about that; this does. actions/checkout refuses to write outside GITHUB_WORKSPACE, hence a direct `git clone`. Pinned to v0.87.0 rather than main, deliberately: a compliance bundle is audit evidence and re-running a release must re-derive the same report, which a moving HEAD cannot promise. The cost is stated in the workflow comment — a cross-ref sigil still claims could rot in synth's later commits without this job noticing. That drift shows up in a developer's local run and when the pin is next raised. claims.yaml gains SYNTH-PIN-AGREES so the two callers cannot pin different refs and validate the release-time report against a different store than the on-demand one. Negative controls, each run: callers pin v0.86.0 vs v0.87.0 -> RED, names both files, exit 1 one clone step deleted -> RED, 1 < min-captures 2, exit 1 claim's pattern has no group -> RED, named, exit 1 Writing that claim found a real fault in `captures-agree` itself: a pattern whose group 1 does not participate (easy with an alternation) yielded None and raised TypeError inside the sort — which aborted main() and left **every later claim unevaluated**. The run still exited non-zero, so no false green, but the silently-skipped tail is the dangerous half: fixing the broken claim later re-enables claims nobody has looked at since. Both shapes are now named as claim defects and reported, deduped, with the suite running to the end. Prerequisite for tagging v0.12.0: the release's compliance report is the V-model evidence, and it has not been produced since 2026-09-08. Refs #284, #300 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012aR3Md1h46K9wAUWMQiESH
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.
Summary
TranscodingPredicate(wsc.dev/transcoding/v1) — in-toto predicate for carrying cryptographic provenance across the WASM→native compilation boundary (synth integration). Builder pattern,create_transcoding_statement()helper, 16 tests.flake.nixwith Rust 1.90.0 via rust-overlay, Bazel 8, cargo-fuzz/audit/deny,rust-toolchain.toml,.envrcfor direnv. SLSA Level 3 prerequisite.New files
src/lib/src/transcoding.rsflake.nixrust-toolchain.toml.envrcTest plan
cargo check— workspace compiles cleancargo test -p wsc -- transcoding— 16/16 tests passnix flake check --no-buildpassesnix developprovides rustc 1.90.0 with wasm32-wasip2Closes #48
🤖 Generated with Claude Code