Skip to content

Replace the archive digest with the property it was there to show - #214

Merged
iderex merged 1 commit into
mainfrom
documentation/the-archive-digest-is-a-property-rather-than-a-value
Aug 29, 2026
Merged

Replace the archive digest with the property it was there to show#214
iderex merged 1 commit into
mainfrom
documentation/the-archive-digest-is-a-property-rather-than-a-value

Conversation

@iderex

@iderex iderex commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

What was wrong

docs/serving-the-bundle.md pastes one digest twice as the evidence that
packing a checkout twice produces the same archive. That paste does not
reproduce at the mainline. Packing fa8c04f by the three commands the document
itself quotes:

git rev-parse HEAD
fa8c04f66e826679dbd3b41e00ab5ca6491a021a
go run . build > /dev/null
(cd dist && find . -type f -print0 | sort -z | xargs -0 sha256sum > ../SHA256SUMS)
tar --sort=name --owner=0 --group=0 --numeric-owner \
    --mtime='UTC 1970-01-01' --format=gnu \
    -cf - dist SHA256SUMS | gzip -n > site-bundle.tar.gz
sha256sum site-bundle.tar.gz
3d51fd9a68f94a9603cfa8a004e3464ab988787d0107f5bc80a073df74501428 *site-bundle.tar.gz

against the c0c27bcd42ef373f774f0d907bd4a1787c192624ac5ead66dc770efba831442b
the document carries. Run 2026-08-29, in a clone outside the working tree.

The bytes under the archive are not what moved. The same build output and the
same archive digest come out at four commits, so nothing between them explains
the difference:

for c in fa8c04f 2a1e214 21bc843 3db5bc8; do
  rm -rf dist SHA256SUMS p.tar.gz; git checkout -q $c; go run . build > /dev/null
  (cd dist && find . -type f -print0 | sort -z | xargs -0 sha256sum > ../SHA256SUMS)
  tar --sort=name --owner=0 --group=0 --numeric-owner --mtime='UTC 1970-01-01' \
      --format=gnu -cf - dist SHA256SUMS | gzip -n > p.tar.gz
  printf '%s  sums=%s  pack=%s\n' "$c" "$(sha256sum SHA256SUMS | cut -c1-16)" \
         "$(sha256sum p.tar.gz | cut -c1-16)"
done
fa8c04f  sums=dd3fe422931addfc  pack=3d51fd9a68f94a96
2a1e214  sums=dd3fe422931addfc  pack=3d51fd9a68f94a96
21bc843  sums=dd3fe422931addfc  pack=3d51fd9a68f94a96
3db5bc8  sums=dd3fe422931addfc  pack=3d51fd9a68f94a96

and the built tree in that clone is byte for byte the one the working checkout
produces:

diff -r --brief G:/Github/site/dist <clone>/dist ; echo "exit=$?"
exit=0

Both run 2026-08-29, with the local path of the clone elided.

What decides the rest of the value is the compressor, and that is the part that
matters more than the stale figure. One tar stream under three gzip levels
gives three digests, and the default is a level rather than the absence of one:

T() { tar --sort=name --owner=0 --group=0 --numeric-owner \
          --mtime='UTC 1970-01-01' --format=gnu -cf - dist SHA256SUMS; }
for level in -1 -6 -9; do
  printf '%s %s\n' "$level" "$(T | gzip -n $level | sha256sum | cut -d' ' -f1)"
done
-1 09903694fbaa1b5a231b0b321e51667bf7687836d400f0ac2b8b9a9ee9a36905
-6 3d51fd9a68f94a9603cfa8a004e3464ab988787d0107f5bc80a073df74501428
-9 f280bc92eaee1e091fa32c29d3e44eeedba7981c647859abc7637778a8f6203d
tar --version | head -1
tar (GNU tar) 1.35
gzip --version | head -1
gzip 1.14

Run 2026-08-29. So an archive digest written into this document is a fact about
the machine that packed it as well as about the bundle, and no re-take makes it
reproduce for a reader whose gzip differs. That is what separates this figure
from the five re-taken beside it yesterday, which are all functions of the tree
and go stale only when the tree moves.

I did not establish where the c0c27bcd reading came from, and I am not
claiming a cause for it. What is measured above is that it does not reproduce
here and that the tree does not explain it.

What this does

Two edits to docs/serving-the-bundle.md, one topic.

## Checking what you downloaded hands over the comparison instead of the
value. The command now returns the property the paste was there to show, which
is that both archives carry one digest, and the paragraph tells an operator to
compare their own pack against their own download rather than against anything
written in the document.

## What is not measured here carries the measurement above, so the reason the
value is gone is readable at the place that already holds the bounds of this
document, and the paragraph listing what was repaired yesterday says that one of
those figures was not a number re-taking could fix.

The failure it prevents is an operator reading a mismatch against a stale paste
as a corrupted or substituted download, which is the one conclusion this section
exists to let them draw correctly.

Closes

Nothing. #54 stays open: two of its three clauses start from a published
archive, there is no release, and the version scheme and release workflow are
#53.

gh release list --repo Flowfin/site --limit 5
gh issue view 53 --repo Flowfin/site --json state,title --jq '"\(.state) \(.title)"'
OPEN The version scheme and the release workflow

Run 2026-08-29. The release listing returns nothing. This is a repair to the
document behind the clause that is already met.

What was run

go run . ci
gate: 7 legs, in order: format, vet, test, build, links, sitemap, invariants
  needs-network was not asked for. Asking costs a request to the public name from whatever machine runs it, and a verdict that moves when somebody else's service does rather than when this tree changes. Ask with: go run ./harness/needs-network
  format: ok, 74 file(s)
  vet: ok
  test: ok, 37 test file(s)
  build: ok, 22 file(s)
  links: every reference that stays inside this site resolves to a file the build wrote
  sitemap: every page the build wrote is listed once, and every entry has a page behind it
  invariants: ok, 39 rule(s) decided, 1 owed and not decided
7 of 7 legs ran. None was skipped.

go run . hygiene origin/main HEAD
hygiene: 1 non-merge commit(s) in origin/main..HEAD, origin internal
  939057c530d3: subject carries its reference
1 commit(s) judged, none refused.

Both run 2026-08-29 at the commit being pushed. needs-network is the one leg
the gate names as not asked for, and it is not asked for here: this change reads
no network and the harness reports on a public name rather than on this tree.

The block the document now pastes was run back out of the file rather than
typed beside it, so what is in the document is what a reader gets:

sed -n '/^    T() {/,/^    done$/p' docs/serving-the-bundle.md | sed 's/^    //' > blk.sh
bash blk.sh
-1 09903694fbaa1b5a231b0b321e51667bf7687836d400f0ac2b8b9a9ee9a36905
-6 3d51fd9a68f94a9603cfa8a004e3464ab988787d0107f5bc80a073df74501428
-9 f280bc92eaee1e091fa32c29d3e44eeedba7981c647859abc7637778a8f6203d

Run 2026-08-29.

No test was skipped. Nothing here needed a display or elevation.

The means

Markdown prose in docs/, which is what the artefact already is, and the change
adds no language, no runtime and no dependency. It carries no rule a machine can
refuse and none is claimed: nothing in this tree holds this document to the
output it describes, which the document's own last section says, and this change
does not alter that. What it does buy is that the figure removed was the one
figure here that no re-take could keep true, so the surface that can go stale is
smaller than it was rather than merely freshly taken. Every claim above carries
the command that produced it, run at the commit being pushed in a clone outside
the working tree.

Who read it

Nobody but me. This change carries no second reader, and the ruleset on this
branch requires no approving review, so the merge is not evidence of one. The
commands above stand in place of a reader: every figure in the diff was run back
out of the file after it was written, and the readings that found the defect are
reproducible from the four commits they name.

The bundle document pasted one digest twice as the evidence that packing a
checkout twice produces the same archive. That paste no longer reproduces, and
re-taking it would not help, which is what makes it different from the five
figures repaired beside it yesterday.

Found by re-running every command in the document at the mainline. Packing
fa8c04f by the three commands the document quotes gives
3d51fd9a68f94a9603cfa8a004e3464ab988787d0107f5bc80a073df74501428, and the
document carries c0c27bcd42ef373f774f0d907bd4a1787c192624ac5ead66dc770efba831442b.
The bytes are not what moved: the same build output and the same archive digest
come out at fa8c04f, 2a1e214, 21bc843 and 3db5bc8, and the built tree is
identical to the one the working checkout produces.

What decides the rest of the value is the compressor. One tar stream under three
gzip levels gives three digests, and the default is a level rather than the
absence of one, so a digest pasted in a document is a fact about the machine that
packed it as well as about the bundle. No re-take makes that reproduce for a
reader whose gzip differs.

So the section that told a reader to compare against the pasted value now hands
over the comparison itself, one digest across the two archives, and the section
of bounds carries the measurement that says why. The failure this prevents is a
reader reading a mismatch against a stale paste as a corrupted or substituted
download.

Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
@iderex iderex added the documentation Improvements or additions to documentation label Aug 29, 2026
@iderex iderex self-assigned this Aug 29, 2026
@iderex iderex added this to the First release milestone Aug 29, 2026
@iderex
iderex merged commit 80942fa into main Aug 29, 2026
17 checks passed
@iderex
iderex deleted the documentation/the-archive-digest-is-a-property-rather-than-a-value branch August 29, 2026 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant