Expand description
Fixity — content checksums that let prov detect bit-rot, not just broken links.
Link validation in the higher-level prov crate answers “does the graph
still hold together?”; fixity answers the other archival question: “are the
bytes still the bytes?” A stored hash, recomputed on read and compared,
catches the silent corruption an archive most fears — a flipped bit in a
decade-old attachment that no link check would ever notice.
§Why this sits in the read core
Everything here is a pure function of bytes: a policy enum, a digest, and
two predicates over a recorded string. None of it opens a file, and none of
it can change one — the same reason identity sits here
rather than above the read boundary. The writes that record a digest
(attach, save, the manifest verbs) live in prov, and the pass that
reads bytes back to compare them is prov’s check.
§Why SHA-256
The algorithm is SHA-256, and a hash is recorded as sha256:<hex> — the
prefix names the algorithm, so the field is self-describing and a future one
can be added without ambiguity. SHA-256 is the archival lingua franca: a
prov workspace’s fixity is verifiable by anyone, with standard tools
(sha256sum, BagIt validators), not only by prov — the same
tool-agnostic, self-describing ethos the whole crate is built on.
The compression function comes from sha2 rather than being written out
here. This module did once carry its own, on the reasoning that guards
exec::block_on and the journal’s FNV checksum —
keep the dependency surface tiny and WASM-clean. It is the one place that
reasoning loses: sha2 is pure Rust and no_std-capable, so it costs no
build toolchain and compiles on wasm32-unknown-unknown like everything
else here, while a hand-written loop cannot reach the hardware path — sha2
dispatches to SHA-NI on x86-64 and to the ARMv8 crypto extensions on
aarch64, and stamp --all hashes every covered file in the workspace.
What does not change is that correctness here is checked, not trusted:
SHA-256 is a fully specified, deterministic function with published test
vectors, and the tests below pin this module’s output to the NIST vectors
and to what sha256sum produces — now testing the binding rather than a
local compression loop, which is exactly what they are for.
Enums§
- Fixity
- How far content checksums cover a workspace.
Functions§
- digest
- The fixity digest of
bytes, spelledsha256:<lowercase-hex>— the form recorded in a sidecar, a frontmatter field, or a recycle-bin tombstone, and the formverifychecks against. Thesha256:prefix names the algorithm, so the record is self-describing and a future digest can be distinguished. - is_
recognized - Whether
recordedis a fixity digest prov can actually check — the predicate that separates “verified” from “unverifiable” so a caller can tell a matching hash from one it had to take on faith. - verify
- Whether
bytesstill hash to therecordeddigest.truewhen the recorded value is empty — nothing was ever recorded, so there is nothing to contradict (a document predating fixity is not “corrupt”). A recorded value prov cannot recognize (a future algorithm) is treated as unverifiable, which is alsotrue: fixity never raises a false alarm over a hash it does not understand, it simply cannot vouch for it.