Skip to content

fix(fuse): add --reproducible for byte-stable output (#325)#327

Merged
avrabe merged 2 commits into
mainfrom
fix/325-reproducible-output
Jul 10, 2026
Merged

fix(fuse): add --reproducible for byte-stable output (#325)#327
avrabe merged 2 commits into
mainfrom
fix/325-reproducible-output

Conversation

@avrabe

@avrabe avrabe commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What

Adds a --reproducible flag so meld fuse produces 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.attestation custom section: a random attestation_id UUID + a wall-clock timestamp. Everything else is already deterministic — --no-attestation is byte-identical across runs, and the section's embedded output.hash is 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-standard SOURCE_DATE_EPOCH (default epoch 01970-01-01T00:00:00Z) via chrono_timestamp_from, instead of the system clock.

Both attestation builders are covered: the default FusionAttestationBuilder::build() path and the feature = "attestation" build_wsc_attestation path (they share the section name wsc.transformation.attestation; the default build uses the former).

Verification (end-to-end)

  • --reproducible → identical sha256 across 3 runs ✓
  • SOURCE_DATE_EPOCH=0 --reproducible → timestamp 1970-01-01T00:00:00Z
  • control (no flag) → still varies (2 distinct) ✓
  • Regression test test_reproducible_attestation_is_byte_stable asserts reproducible runs are byte-equal and that the control differs (so the flag can't silently become a no-op).
  • Pre-commit gate green: fmt, clippy, full test suite.

Non-Tier-5 (attestation/config/CLI only). The new FuserConfig field is threaded through the existing explicit test literals.

Refs #325.

🤖 Generated with Claude Code

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>
@github-actions

Copy link
Copy Markdown

LS-N verification gate

58/58 approved LS entries verified

count
Passed (≥1 test, all green) 58
Failed (≥1 test failure) 0
Missing (no ls_*_NN_* test found) 0

Approved loss-scenarios.yaml entries are expected to have a
regression test named ls_<letter>_<num>_* (e.g. LS-A-11
ls_a_11_*). The gate runs each prefix via cargo test --lib --no-fail-fast and aggregates pass/fail/missing.

Failed LS entries

(none)

Missing regression tests

(none)

Updated automatically by tools/post_verification_comment.py.
Source of truth: safety/stpa/loss-scenarios.yaml.

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>
@avrabe avrabe merged commit f177fb4 into main Jul 10, 2026
14 checks passed
@avrabe avrabe deleted the fix/325-reproducible-output branch July 10, 2026 14:42
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.

1 participant