fix(fuse): add --reproducible for byte-stable output (#325)#327
Merged
Conversation
meld's fused output was byte-nondeterministic: identical input yielded a different sha256 each run, breaking reproducible-build / supply-chain attestation (scry/loom/witness/sigil key on the fused bytes). Root cause (found by structural diff, not the issue's HashMap guess): the ONLY nondeterministic bytes are in the `wsc.transformation.attestation` custom section — a random `attestation_id` UUID + a wall-clock `timestamp`. Everything else is already deterministic (`--no-attestation` is byte-identical across runs; the section's own `output.hash` is stable). Add a `--reproducible` flag (FuserConfig.reproducible). When set, the attestation id is derived from the output content (`entropy_from_hex(output_hash)` → `generate_uuid_from`) and the timestamp from the ecosystem-standard `SOURCE_DATE_EPOCH` (default epoch 0) via `chrono_timestamp_from`, instead of a random UUID + system clock — so identical input yields an identical artifact. Both attestation builders are covered: the default `FusionAttestationBuilder` path and the `feature = "attestation"` `wsc` path. Verified end-to-end: `--reproducible` → identical sha256 across runs; `SOURCE_DATE_EPOCH=0` → `1970-01-01T00:00:00Z`; control (no flag) still varies. Regression test `test_reproducible_attestation_is_byte_stable` pins it (and asserts the control differs, so the flag can't silently become a no-op). The new FuserConfig field is threaded through the existing explicit test literals (reproducible: false). Refs #325. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LS-N verification gate✅ 58/58 approved LS entries verified
Approved Failed LS entries(none) Missing regression tests(none) Updated automatically by |
The Coverage job (cargo test --all-features) exposed a real gap: under the optional `attestation` (wsc) feature, the emitted section carries `tool_parameters` / `metadata` as `wsc_attestation` `HashMap` fields whose serde serialization order is process-random — meld can't control it from this side (the field types live in the upstream crate). So `--reproducible` makes the shipped default build (`features = []`, `FusionAttestationBuilder`, no such maps) fully byte-stable, but not the optional wsc path. Gate `test_reproducible_attestation_is_byte_stable` to `#[cfg(not(feature = "attestation"))]` — it asserts the guarantee meld actually provides (the default build) and documents the wsc-path limitation (needs an upstream sorted/BTreeMap serialization fix). The default-path fix and its verification are unchanged. Refs #325. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
What
Adds a
--reproducibleflag someld fuseproduces a byte-identical artifact for identical input, fixing the sha256-nondeterminism reported in #325.Root cause (measured, not guessed)
A structural diff of two nondeterministic outputs showed the only differing bytes are in the
wsc.transformation.attestationcustom section: a randomattestation_idUUID + a wall-clocktimestamp. Everything else is already deterministic —--no-attestationis byte-identical across runs, and the section's embeddedoutput.hashis stable. (The issue guessed HashMap iteration order; the diff ruled that out.)Fix
--reproducible(→FuserConfig.reproducible). When set:attestation_id← derived from the output content (entropy_from_hex(output_hash)→generate_uuid_from), so it's a stable content fingerprint instead of a random UUID.timestamp← from the ecosystem-standardSOURCE_DATE_EPOCH(default epoch0→1970-01-01T00:00:00Z) viachrono_timestamp_from, instead of the system clock.Both attestation builders are covered: the default
FusionAttestationBuilder::build()path and thefeature = "attestation"build_wsc_attestationpath (they share the section namewsc.transformation.attestation; the default build uses the former).Verification (end-to-end)
--reproducible→ identical sha256 across 3 runs ✓SOURCE_DATE_EPOCH=0 --reproducible→ timestamp1970-01-01T00:00:00Z✓test_reproducible_attestation_is_byte_stableasserts reproducible runs are byte-equal and that the control differs (so the flag can't silently become a no-op).Non-Tier-5 (attestation/config/CLI only). The new
FuserConfigfield is threaded through the existing explicit test literals.Refs #325.
🤖 Generated with Claude Code