Reproducibility¶
Atlas declares reproducibility scenarios for crates, a Docker image, a Helm
chart, the docs site, and the release bundle. The current repository-wide
reproduce command validates metadata determinism and source lineage; it does
not execute those five rebuilds.
Declared Objective¶
ops/reproducibility/spec.json requires three signal classes:
source_snapshot_hashscenario_resultsartifact_hashes
The catalog names five intended rebuild scenarios. Three fixtures identify known-good inputs for crates, docs, and chart packaging. The catalog and fixtures define vocabulary and expected shape; they are not completed rebuild evidence.
flowchart LR
Catalog[Five declared rebuild scenarios] --> Metadata[Current reproduce run]
Source[Tracked checkout] --> SourceHash[Source snapshot hash]
Controls[Cargo.lock and reproducibility controls] --> ControlHashes[Control-file hashes]
SourceHash --> Metadata
ControlHashes --> Metadata
Metadata --> DoubleRun[Generate metadata twice]
DoubleRun --> Verify[Compare normalized reports]
Rebuild[Build each artifact twice] -. not performed .-> Verify
What the Current Commands Prove¶
| Command | Current behavior | Safe conclusion |
|---|---|---|
reproduce run |
hashes tracked source and selected control files; lists catalog scenarios | source/control identity was summarized |
reproduce verify |
checks five scenario IDs exist and compares two normalized metadata payloads | metadata generation is deterministic for one checkout |
reproduce lineage-validate |
requires hashes for Cargo.lock and three reproducibility control files |
those lineage inputs were present and hashed |
reproduce audit-report |
timestamps and persists the verification result | the metadata verification was recorded |
reproduce metrics |
counts scenarios and hashed control files | inventory counts were emitted |
artifact_hashes in this command refers to control files such as Cargo.lock
and the reproducibility specifications. It does not contain hashes of rebuilt
crate packages, OCI images, chart archives, the docs site, or a release bundle.
The emitted offline_safe: true value is a static property of the report
payload. The verification checks that value; it does not instrument or prove
the absence of network access during an artifact rebuild.
Separate Repeatability, Reproducibility, and Hermeticity¶
These properties answer different questions and need different experiments:
| Property | Required experiment | Claim limit |
|---|---|---|
| deterministic metadata. | Generate and normalize the same report twice in one checkout. | Report construction is stable for those inputs. |
| build repeatability. | Build twice with the same builder, caches, and controlled environment. | One environment can repeat its own output. |
| independent reproducibility. | Build the same source with isolated builders and independently acquired dependencies. | Separate builders agree on the governed artifact identity. |
| hermeticity. | Deny undeclared filesystem, environment, clock, credential, and network inputs during the build. | The output depends only on the declared input closure. |
| offline rebuild. | Populate a declared local dependency set, deny network access, and rebuild from it. | The retained local set is sufficient for that target. |
Passing a weaker property does not imply a stronger one. In particular, offline execution can consume mutable local inputs, and a hermetic build can be non-reproducible when its declared inputs contain time or randomness.
Release-Specific Reproducibility¶
The separate release reproducibility report command checks required build
environment values, release-manifest build metadata, and a declared versus
computed bundle hash. That is stronger for a concrete release bundle, but it
still needs the referenced manifest and bundle to exist for the selected
version.
In release-candidate.yml, a nonzero result from that command is converted into
a warn gate artifact and the workflow continues. The lane therefore records
the failure but does not enforce reproducibility as a hard candidate gate.
Evidence Required for a Rebuild Claim¶
To claim that a release artifact is reproducible, retain:
- an immutable source revision and clean input snapshot
- pinned toolchain, dependency, base-image, and environment identities
- two isolated builds with controlled environment differences
- canonicalization rules for timestamps, archive ordering, paths, and metadata
- hashes of the actual output artifacts from both builds
- a scenario result explaining equality or classified differences
- provenance binding the compared outputs to their builders and inputs
Artifact-specific normalization matters. A deterministic JSON report does not make a tar archive deterministic, and equal chart sources do not prove equal packaged chart bytes.
Compare the Right Equivalence¶
Byte equality is the strongest result when the artifact format permits it. When canonicalization is necessary, define the transformation before building and retain both original outputs. A post hoc rule created to erase an observed difference is not reproducibility evidence.
| Artifact | Identity to pin | Differences to control or explain |
|---|---|---|
| Rust packages | source, lockfile, Rust toolchain, target, feature set | archive metadata, compiler inputs, native dependencies |
| OCI image | source, base-image digest, builder, platform | layer ordering, timestamps, labels, package repositories |
| Helm chart | chart source, dependency locks, Helm version | archive order, modes, timestamps, generated metadata |
| documentation site | source, documentation toolchain, theme and plugin versions | generated timestamps, search indexes, asset ordering |
| release bundle | complete member inventory and member hashes | archive metadata, ordering, signing and provenance attachments |
flowchart TD
Spec[Predeclared scenario and normalization] --> BuildA[Isolated build A]
Spec --> BuildB[Isolated build B]
BuildA --> OriginalA[Original artifact and provenance]
BuildB --> OriginalB[Original artifact and provenance]
OriginalA --> Compare{Byte-equal?}
OriginalB --> Compare
Compare -- yes --> Exact[Exact reproducibility result]
Compare -- no --> Normalize[Apply predeclared canonicalization]
Normalize --> Canonical{Canonical outputs equal?}
Canonical -- yes --> Explained[Canonical reproducibility plus original difference report]
Canonical -- no --> Fail[Classified reproducibility failure]
The result must say whether equality was exact or canonicalized. It must also name every ignored field and retain the unexplained-difference report.
Triage a Rebuild Divergence¶
A mismatch is the start of attribution, not permission to expand the ignored field list. Preserve both original artifacts and compare from the outside in:
flowchart TD
Mismatch[Output hashes differ] --> Inventory{Member inventory equal?}
Inventory -->|no| Inputs[Trace source, dependency, feature, and packaging inputs]
Inventory -->|yes| Metadata{Only predeclared metadata differs?}
Metadata -->|yes| Canonical[Apply declared canonicalization and retain originals]
Metadata -->|no| Content[Locate first content or layer difference]
Content --> Builder[Compare toolchain, platform, environment, and execution]
Canonical --> Verdict{Canonical outputs equal?}
Builder --> Finding[Classified reproducibility failure]
Verdict -->|yes| Qualified[Canonical reproducibility result]
Verdict -->|no| Finding
| Divergence class | Investigation focus |
|---|---|
| member set | omitted or additional build input, feature, generated file, or packaging rule |
| content bytes | source snapshot, dependency resolution, compiler, native library, platform, or nondeterministic execution |
| ordering or archive metadata | declared packaging and canonicalization rules |
| image layers or platform manifest | builder, base and package digests, target platform, labels, timestamps, and layer construction |
| signature or provenance attachment | signer identity, signing mode, attachment order, and whether signatures are inside the compared payload |
Run the diagnosis from retained outputs rather than rebuilding repeatedly until two samples happen to match. Repeated attempts belong in the evidence series; intermittent equality indicates nondeterminism, not a successful reproducible build.
Independence and Custody¶
Two invocations in one populated workspace can reuse caches, generated files, credentials, or mutable dependencies. Prefer isolated builders with separate output roots and controlled differences. Record network policy, dependency source, cache policy, locale, timezone, platform, and environment allowlist.
Bind each output hash to its source and builder provenance. Store the comparison result with both artifact identities. A signed statement can protect custody, but signing two different artifacts does not make them reproducible.
Decision Boundary¶
Use current reproduce output as repository metadata and lineage evidence.
Use the release-specific report as bundle consistency evidence. Do not describe
either as successful execution of all five declared rebuild scenarios until
the commands actually build and compare those artifacts.
Authorities¶
ops/reproducibility/spec.jsonops/reproducibility/scenarios.jsonops/reproducibility/fixtures/ops/reproducibility/ci-scenario.jsoncrates/bijux-atlas-dev/src/application/reproduce.rs.github/workflows/release-candidate.yml