Oregami
Repositories/oxedyne/daimond

oxedyne/daimond/dev/build-wasm.sh

7.1 KiB, 1 run

created by r2519314175:13, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1#!/bin/bash
2# build-wasm.sh -- build the browser bundle so that the bytes are the same
3# wherever it is built.
4#
5# This is THE build command for Daimond's wasm. Use it rather than calling
6# wasm-pack directly, and use it for a rebuild you intend to compare against the
7# published bundle: a plain `wasm-pack build` does NOT produce the sealed bytes.
8#
9# Why it exists. Rust bakes the path of every source file into the binary --
10# `file!()` is expanded by the `err!` and panic macros throughout fe2o3, and the
11# expansion is the path as rustc saw it. Built plainly, the wasm therefore
12# carries the absolute paths of the machine that built it, somewhere under
13# `/home/<whoever>/.cargo/git/checkouts/...`. Two people building byte-identical
14# source get different wasm, and the difference is only their home directory.
15#
16# That quietly voided the whole verifiability claim. "Rebuild it and compare the
17# hash" is addressed to a stranger, and no stranger could ever have matched it;
18# it only ever succeeded for someone rebuilding on the machine that sealed it,
19# which is not evidence of anything. It also meant every visitor was served the
20# author's directory layout inside the wasm.
21#
22# The fix is to remap those prefixes to fixed stand-ins before they are baked
23# in. Cargo's own `trim-paths` profile option would do this, but it is still
24# nightly-only in Cargo 1.90 (the pinned toolchain), so the equivalent is done
25# here with the stable `--remap-path-prefix` flag. Each builder maps THEIR
26# paths to the SAME stand-ins, so the output stops depending on where they keep
27# their files.
28#
29# bash dev/build-wasm.sh # the sealed build
30# bash dev/build-wasm.sh --dev # anything else is passed to wasm-pack
31set -e
32cd "$(dirname "$0")/.."
33ROOT=$(pwd -P)
34
35# Where cargo unpacks dependency sources. Everything under it becomes /cargo.
36CARGO_DIR=$(cd "${CARGO_HOME:-$HOME/.cargo}" && pwd -P)
37
38# The two prefixes that vary from machine to machine. rustc already remaps its
39# own standard library to /rustc/<hash>, so those two are the whole story.
40export RUSTFLAGS="--remap-path-prefix=$CARGO_DIR=/cargo --remap-path-prefix=$ROOT=/build ${RUSTFLAGS:-}"
41
42wasm-pack build --target web --out-dir www/pkg "$@"
43
44# ── Say what it was built from ──────────────────────────────────────────
45#
46# `dev/staleguard.mjs` is what decides whether a verifier is measuring THIS
47# tree's engine, and with nothing to go on it can only compare clocks. An mtime
48# answers a different question from the one being asked -- "was the bundle
49# written after the source was?" rather than "was it built FROM this source?" --
50# and the two part company whenever files are rewritten without being changed. A
51# `git stash` and its `pop` restore byte-identical sources with new timestamps,
52# and every wasm-guarded verifier then refuses a bundle that is in fact this
53# source's. That cost a lane a rebuild it did not need on 2026-08-12.
54#
55# So the bundle now carries `www/pkg/source.json`: a SHA-256 per engine source
56# file, plus one over the wasm itself. Two properties keep it from becoming a
57# second thing to go stale. The guard REHASHES the tree in front of it rather
58# than believing the note, so an edit made afterwards is caught exactly as it
59# always was; and the note names the bundle it is about, so a bundle rebuilt by
60# any other means stops matching and the clock takes over. It can only ever
61# prevent a false refusal. It can never launder a stale bundle.
62#
63# It does NOT make rebuilds rare. A comment added to a Rust file moves that
64# file's hash just as a changed fence does, and nothing short of compiling can
65# tell those apart. What stops costing a build is source that never changed.
66#
67# The other half of this lives in `verify/lib.mjs`: `pkg/source.json` is in
68# EXCLUDE, so the note never enters a sealed manifest. It records where and when
69# a build happened, both of which differ for every honest rebuild, and sealing it
70# would make "clone it, build it, compare the hash" false for every reader.
71# Neither half is any use alone. `dev/repro-check.sh` proves the pair.
72#
73# Not fatal when it cannot be written -- an older mirror has no staleguard to
74# call, and the bundle above is built and good either way. What is lost is a
75# shortcut. Said out loud rather than swallowed, because a build that quietly
76# stopped certifying would look exactly like one that never started.
77#
78# `2>&1 >/dev/null` keeps the REASON: the hash on stdout is noise here, and the
79# reason is on stderr, and a failure reported without one is a second thing to
80# go and find out.
81if WHY=$(node dev/staleguard.mjs certify www/pkg "$ROOT" dev/build-wasm.sh 2>&1 >/dev/null); then
82 echo
83 echo "build-wasm: certified — www/pkg/source.json records the source this was built from,"
84 echo " so a verifier compares content rather than timestamps."
85else
86 echo
87 echo "build-wasm: NOT CERTIFIED — no source record could be written beside the bundle, so"
88 echo " verifiers fall back to comparing mtimes. The bundle itself is built and fine."
89 echo "${WHY:- (no reason given)}" | sed 's/^/ /'
90fi
91
92# ── Say which kind of bundle this is ────────────────────────────────────
93#
94# The two prefixes above are the whole story ONLY in the mirror, where
95# `Cargo.toml` pins fe2o3 by git revision so its sources come from under
96# $CARGO_DIR. The DEV tree links fe2o3 by path, at ~/usr/code/rust/fe2o3, which is
97# outside both remapped prefixes -- so every `err!` and every panic in fe2o3
98# bakes this machine's home directory into the bundle, and a build made here can
99# never be reproduced by a stranger.
100#
101# That is fine for testing and fatal for sealing, and the difference is invisible
102# unless somebody thinks to look. It was NOT looked at for two releases: seq 66
103# and 67 were sealed from a dev build, so for three days the transparency log
104# named a bundle nobody outside this machine could produce. The check costs
105# nothing, so it runs every time rather than being remembered.
106#
107# It greps for THIS BUILDER'S home directory, not for `/home/` generally. The
108# broader pattern also matches `/home/you/project/src/main.rs`, which is a
109# deliberate literal in `src/tools.rs` -- the file tools' own description, telling
110# a model that an absolute path is refused rather than followed. A correct,
111# reproducible mirror build therefore reported "DEV BUILD - 1 line" and would have
112# been withheld from a release for a documentation example. A check that cries
113# wolf on a good build gets ignored on a bad one, which is the failure this check
114# exists to prevent.
115BAKED=$(grep -ac "$HOME" www/pkg/oxedyne_daimond_bg.wasm || true)
116echo
117if [ "$BAKED" -eq 0 ]; then
118 echo "build-wasm: REPRODUCIBLE — no home directory in the bundle. Safe to seal."
119else
120 echo "build-wasm: DEV BUILD — $BAKED line(s) of this machine's home directory are in"
121 echo " the bundle, because fe2o3 is linked by PATH here and only the mirror pins it"
122 echo " by revision. Fine to test with. DO NOT SEAL IT: build in the mirror instead,"
123 echo " per \"Deploying\" in ~/usr/SYSTEM.md, and let repro-check.sh confirm it."
124fi