Signed provenance#
/provenance.intoto.json is an in-toto Statement v1 with an SLSA provenance v1 predicate, in a DSSE envelope.
- Signature. ES256 over the DSSE pre-authentication encoding, as
r‖sin base64. - Key. Verify it with the release public key,
/release-key.jwk. - Subjects, by sha256:
- the bander bundle and the four native builds;
- the operator bundle;
- the verification kit;
- the conformance vectors, the OpenAPI document and the SBOM.
- Materials:
- the sha256 of every source file that went in, and of the lockfile that pins the build tools;
- the checksum-verified Node runtime archives the natives were built from;
- the exact release chain.
server/provenance.test.js checks on every build that:
- the envelope verifies;
- every subject digest is the artefact on disk;
- a changed digest breaks the signature;
- no private key exists anywhere in the deployed directory.
Build type local-release-v1#
The release chain runs on the maintainer's workstation, in the order listed in the statement's release_chain. The provenance is generated last.
- The builder.
builder.idnames the maintainer's workstation. There is no hosted build service. - The key. The release key is kept outside the deployed directory (
keys/) and never published.
What level this is#
SLSA Build Level 1: provenance exists, and it is signed. It is not Level 2 or 3. Those require a hosted build platform that generates and signs provenance itself. Here, the signature proves who published the statement, not that an isolated builder produced the bytes.
Reproducible builds#
One command checks a release against its signed provenance:
node server/reproduce.js
It does four things, in order:
- Verifies the envelope against the release public key.
- Checks the sources. Every source file the statement lists must be byte-identical to the file in the tree it runs in. If any differ, it stops: that tree is not the release.
- Rebuilds every subject in a disposable copy of the tree, at a different path, with the release chain's own build commands. The natives are built from the official Node runtime archives, each checked against the digest the statement pins (and against Node's published checksums when it fetches one).
- Compares each rebuilt artefact's sha256 with the signed subject.
Exit code 0 means every subject reproduced. --skip-natives rebuilds only the JavaScript artefacts, in seconds; --in-place rebuilds in a disposable checkout instead of a copy; --json prints a machine-readable report. The private release key is never copied.
| Artefact | Reproduced? | How it is checked |
|---|---|---|
Verification kit (mirror-kit.js) | Yes, byte for byte | reproduce.js; also server/provenance.test.js, which regenerates it and compares |
| Operator bundle | Yes, byte for byte | reproduce.js; also server/edge/bundle.test.js checks freshness |
Bander bundle (mirror-bander.bundle.js) | Yes, byte for byte | reproduce.js |
| Native binaries (Node single-executable), all four | Yes, byte for byte | reproduce.js, on two operating systems |
| Conformance vectors, OpenAPI document, SBOM | Yes, byte for byte | reproduce.js |
Result, 11 October 2026: 10 of 10 subjects, on Windows and on Ubuntu, checked against the provenance this release publishes (invocation release-2026-10-11T12-25-19-293Z), with all 194 listed source files identical on both. Every release before it reproduced the same way on both machines, on 29 and 30 September and on 5, 6 and 9 October.
| Where | Result |
|---|---|
| Windows 11, Node 24.16.0, in a scratch copy at a different path | 10 of 10 reproduced, in under a minute |
Ubuntu 24.04 (x86-64), Node 24.16.0, packages from npm ci --offline against the lockfile, natives built from the runtime archives already on disk — the run fetches nothing | 10 of 10 reproduced, from provenance signed on Windows, in about a minute and a quarter |
The four native binaries (SHA-256, first 16 characters): win-x64 db7f720876631c4f, darwin-arm64 897a0595b79404e0, darwin-x64 e1a416cad856bfcf, linux-x64 3c12d9a7f41a379d. The full digests are the subjects of /provenance.intoto.json.
What the second machine found#
The first native builds embedded the build machine's absolute folder path, and with it the maintainer's user name, in every binary. Node writes the path of the bundled script into the executable, so the bytes depended on where the repository was checked out: reproducible on one machine only. It was found by trying to reproduce on a second operating system. The build now runs from the repository root with relative paths. The binaries published before 29 September carry that path and are replaced by these.
What is not shown#
- A rebuild by anyone but the maintainer. Both machines are the maintainer's: the Linux run was an Ubuntu install on the same computer. Independent reproduction is the point of publishing the command, and it has not happened yet.
- Public source. The tree is not public. A reviewer receives it in diligence and can confirm it is the release's tree from the digests above, which is what step 2 does. Publishing it is the maintainer's decision.
- Node's own build. The natives embed the official Node runtime. The rebuild reproduces the packaging, starting from the same archives, not Node's compilation.
- The compressed copies the site hosts for download. Those are packaging of the natives, not rebuilt here. Verify the native's sha256, which is its identity.
What is still missing#
- No public source repository with protected history. The provenance lists every source file by digest, but you cannot yet fetch the tree from a repository.
- No hosted builder.
- The native binaries are not code-signed. Operating systems will warn; verify the sha256 instead.