From c36d8b6ddf2b7d18354a541c0fa3f122c46538af Mon Sep 17 00:00:00 2001 From: clawbot Date: Sun, 23 Aug 2026 15:33:58 +0200 Subject: [PATCH] docs: state the enforced dist/ verification scope precisely (closes #331) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit README, the script synopsis, its header paragraph and the check_dist_tree comment now all say the same thing: regular files and symlinks under dist/ are covered; fifos, sockets, device nodes and empty directories are not, and why. No behaviour change — the walk is untouched. --- README.md | 33 +++++++++++++++++++-------------- TODO.md | 13 ++++++++++++- script/verify-build | 32 ++++++++++++++++++++------------ 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index c7cfe85..8335d58 100644 --- a/README.md +++ b/README.md @@ -81,17 +81,21 @@ lives. one of the bundles containing `src/shared/constants.js` — into a build receipt, and `script/verify-build` checks `dist/` against that receipt: every recorded file present with exactly the recorded bytes, every audited bundle carrying the -requested `DEBUG` marker, and nothing under `dist/` that the build did not -write. The `Makefile` creates the receipt path with `mktemp` per invocation, -outside the repo, and deletes it afterwards. +requested `DEBUG` marker, and no regular file or symlink under `dist/` that the +build did not write. The `Makefile` creates the receipt path with `mktemp` per +invocation, outside the repo, and deletes it afterwards. That is what ties the check to a build rather than to a directory. What it establishes is narrow and worth stating exactly: `dist/` is byte for byte the -output of the `build.js` run that just finished, with nothing added, removed or -altered in between. It establishes nothing about whether the source tree or -`build.js` were honest, and it offers nothing to someone handed a `dist/` from -elsewhere — without the receipt from its own build there is no input to the -check. Verifiable provenance for a third party is signing, which this is not. +output of the `build.js` run that just finished, with no regular file or symlink +added, removed or altered in between. Regular files and symlinks are the whole +of what the tree walk covers; fifos, sockets, device nodes and empty directories +under `dist/` are not checked, because a build emits none of them, none can +carry a shippable payload, and `grep` on a fifo would hang rather than fail. It +establishes nothing about whether the source tree or `build.js` were honest, and +it offers nothing to someone handed a `dist/` from elsewhere — without the +receipt from its own build there is no input to the check. Verifiable provenance +for a third party is signing, which this is not. There is deliberately no target that re-verifies an existing `dist/` on its own. The list of files to check has to come from the build that produced them; read @@ -143,12 +147,13 @@ provide: serves. Run deliberately, never as part of a build: the output is committed and there is no runtime fetch, so the shipped list is as fresh as the last vendoring run that was released -- `script/verify-build --expect release|debug --receipt PATH` — assert that - `dist/` is exactly what the build that just ran emitted, and that the compiled - `DEBUG` state of the bundles in it is the one that was asked for. Both - arguments are required and neither has a default: the expected mode is stated - by the caller rather than read from `AUTISTMASK_DEBUG`, and the file list - comes from the build's receipt rather than from `dist/` (see +- `script/verify-build --expect release|debug --receipt PATH` — assert that the + regular files and symlinks under `dist/` are exactly what the build that just + ran emitted (other file types are out of scope), and that the compiled `DEBUG` + state of the bundles in it is the one that was asked for. Both arguments are + required and neither has a default: the expected mode is stated by the caller + rather than read from `AUTISTMASK_DEBUG`, and the file list comes from the + build's receipt rather than from `dist/` (see [Build Receipts](#build-receipts)). Run automatically at the end of `make build` and `make build-debug`; fails loudly rather than passing whenever it cannot determine something. Not part of `make check`, which does not depend diff --git a/TODO.md b/TODO.md index 5398877..f0a0cbf 100644 --- a/TODO.md +++ b/TODO.md @@ -26,7 +26,8 @@ milestone is in flight on `next`; its `next` -> `main` PR is [#190](https://git.eeqj.de/sneak/AutistMask/pulls/190). `make check` verified green on `next` at `e9fa8be` on 2026-08-10, and `make build` produces `dist/chrome/` and `dist/firefox/`, verified against the build's own receipt to -be exactly what that build emitted with `DEBUG` compiled off. +hold exactly the regular files and symlinks that build emitted, with `DEBUG` +compiled off. The backlog lives on the [Gitea tracker](https://git.eeqj.de/sneak/AutistMask/issues), which is @@ -44,6 +45,16 @@ but the review is broader than any of them. # Completed Steps +- 2026-08-23: `README.md` and `script/verify-build`'s own comments now state the + emitted-tree guarantee at the width the code actually enforces + ([#331](https://git.eeqj.de/sneak/AutistMask/issues/331)). The tree walk is + `-type f -o -type l`, so the guarantee covers regular files and symlinks under + `dist/`; fifos, sockets, device nodes and empty directories are not checked, + because a build emits none of them, none can carry a shippable payload, and + `grep` on a fifo would hang rather than fail. The exclusion is deliberate and + unchanged — the README said "nothing under `dist/` that the build did not + write", which was broader than that. Documentation only; no executable line + changed. - 2026-08-20: A second extension page can no longer silently delete a wallet ([#304](https://git.eeqj.de/sneak/AutistMask/issues/304)). `saveState()` wrote the entire state blob, and every extension page — the toolbar popup, a dApp diff --git a/script/verify-build b/script/verify-build index e2e360e..eed1a45 100755 --- a/script/verify-build +++ b/script/verify-build @@ -1,8 +1,10 @@ #!/bin/sh -# script/verify-build: assert that dist/ holds exactly what the build that just -# ran emitted, and that the compiled DEBUG state of that output is the one the -# caller asked for. Our own extension to scripts-to-rule-them-all, run at the -# end of make build / make build-debug. +# script/verify-build: assert that the regular files and symlinks under dist/ +# are exactly what the build that just ran emitted (other file types are out of +# scope; see "What that does and does not establish" below), and that the +# compiled DEBUG state of that output is the one the caller asked for. Our own +# extension to scripts-to-rule-them-all, run at the end of make build / +# make build-debug. # # Why the DEBUG half exists: DEBUG makes the publicly committed test recovery # phrase the output of wallet creation, so a release artifact built with it live @@ -29,12 +31,16 @@ # path fresh per invocation, outside the repo, and deletes it afterwards. # # What that does and does not establish. It establishes that dist/ is byte for -# byte the output of the build.js run that just finished, with nothing added, -# nothing missing and nothing altered in between, and that the audited bundles -# in it compiled to the requested mode. It does NOT establish that the source -# tree or build.js were honest, and it says nothing at all to someone handed a -# dist/ from elsewhere: without the receipt from its own build they have no -# input to this check. That is signing, and it is not this control. +# byte the output of the build.js run that just finished, with no regular file +# or symlink added, missing or altered in between, and that the audited bundles +# in it compiled to the requested mode. Regular files and symlinks are the whole +# of what the tree walk covers; fifos, sockets, device nodes and empty +# directories under dist/ are not checked, because a build emits none of them, +# none can carry a shippable payload, and grep on a fifo would hang rather than +# fail. It does NOT establish that the source tree or build.js were honest, and +# it says nothing at all to someone handed a dist/ from elsewhere: without the +# receipt from its own build they have no input to this check. That is signing, +# and it is not this control. # # It fails rather than passes whenever it cannot determine something. Minified # output is not a stable contract, so "matched neither marker" is not evidence @@ -392,8 +398,10 @@ check_receipt_entries() { # its own command line, so a linked dist/ collapses this walk to one entry # and cross-checks nothing. # -# Types other than regular files and symlinks are left out on purpose: a build -# emits none of them, and grep on a fifo would hang rather than fail. +# Types other than regular files and symlinks — fifos, sockets, device nodes and +# empty directories — are left out on purpose, and the guarantee is bounded to +# what is walked: a build emits none of them, none can carry a shippable +# payload, and grep on a fifo would hang rather than fail. check_dist_tree() { LISTING="$(mktemp "${TMPDIR:-/tmp}/verify-build-dist.XXXXXX")" || fail "could not create a temporary file for the dist/ listing, so the