SvEx. Baseline
(SvEx v0.4.2)
Provenance and drift checking for the checked-in generator baselines.
Every function is pure over a directory — nothing here shells out to a generator, so the drift check runs offline on every commit and 100% coverage never depends on having phx_new installed.
This module must NOT share a normaliser with SvEx.Hash. They require
opposite semantics: the manifest hash ignores an added comment (a
# credo:disable-for-next-line must not lock a project out of updates),
while a comment added to a baseline IS drift.
Summary
Functions
Names an archive from its inner tar's sha.
A single digest over the whole tree.
Selects one baseline's archive members.
Replaces phx.new's four crypto:strong_rand_bytes values with placeholders.
Reads the provenance record.
Recomputes every entry's derived fields from disk.
Builds one baseline's self-verifying snapshot.
Builds reproducible, uncompressed tar bytes from in-memory members.
Maps every relative path under dir to the sha256 of its normalised bytes.
Functions
Names an archive from its inner tar's sha.
Only the last 8 characters: the full digest is recorded as archive_sha256 in
the manifest and again inside the archive itself, so the filename only has to
be short and distinguishing.
A single digest over the whole tree.
Selects one baseline's archive members.
Contents come from disk but membership comes from the entry's files map,
never from a fresh wildcard — that is what makes it structurally impossible
for the archive and the manifest to disagree about the baseline.
Names are project-relative, identical to the files keys, so each archive
unpacks as a standalone snapshot of that generated project and a member name
can be looked up in files directly.
Replaces phx.new's four crypto:strong_rand_bytes values with placeholders.
Anchors on the key name, never on a bare length match: the alphabet is
unpadded base64, so values contain + and / and may start with /.
Reads the provenance record.
Not every entry is a generator baseline. derived_from: marks one produced
by applying a plugin — mix sv_ex.baseline.compose — and such an entry
has no argv:, generator: or generator_version:. A test that drives a
generator must select entries that carry them rather than iterating all.
Recomputes every entry's derived fields from disk.
files and tree_digest are recomputed; every other field is passed through
untouched. generator_version above all must never be sourced from the
running toolchain — it is the pin that makes the toolchain test fail with one
line on a phx_new bump instead of a 45-file hash diff.
:file_count is dropped: files supersedes it and map_size/1 is exact.
archive_sha256 is recorded here rather than in a sidecar file. It is not
circular: the archive holds only the project's files, so the manifest is not
an input to its own recorded hash and one pass converges.
Builds one baseline's self-verifying snapshot.
The .tar.gz is an OUTER tar holding two members: baseline.tar — the
project's files — and baseline.sha256, its checksum. The checksum sits
beside the inner tar rather than inside it, which is the only placement that
terminates: a file recording a tar's hash cannot also be a member of it.
Returns {sha, gzipped} where sha is the hex sha256 of the INNER tar.
Builds reproducible, uncompressed tar bytes from in-memory members.
Members are {name_charlist, contents} and are sorted here rather than by the
caller, so member order cannot vary with map iteration.
Maps every relative path under dir to the sha256 of its normalised bytes.