open-standards/wai/wai-web/demo/verify_measure.sh
Transaction Science 8cf9c53a03 wai-web: staged measurement and the session claim in the browser (W5-4)
wai-web binds wai::stage_measure, the code wai_stage_measure runs, compiled to
wasm32 (src/measure.rs): evaluateTitle gives the text `eval --json` prints for a
title, simulate and simulateModel the text `sim` prints, countObject one
envelope's counted bytes or the code it is not countable with, qualityRgb8 one
picture pair's integers (sums of squares as decimal strings), outputRoot the
output tree's root. A title is read from a map of files; titleMissing names the
next file it needs, so a page fetches them one at a time.

receipt_claims builds and runs for wasm32 with stage_measure, so signing is
exposed: sessionBegin records a session at its entry object
(SessionRecorder), decoderFor/presented/received record what the page did,
finish seals the reconstruct-session claim with a page-supplied seed (energy
null), and verifyClaim runs the claim-conformance runner against the outputs
and the objects. CI builds receipt_claims,stage_measure for wasm32 beside the
stage_measure guard.

demo/verify_measure_wasm.mjs requires, from the wasm32 build, every golden,
refusal title, counted object, quality pair and simulator result of
staged-measure-conformance/ byte for byte, and a page-recorded session per
fixture equal to the native tool's claim byte for byte. demo/verify_measure.sh
adds the native `eval --json` of every fixture (cmp against the wasm32 text)
and the native and Python claim verifiers' verdicts on every browser-sealed
session. wai-web-wasm.yml runs it (the W17 line).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-06 16:59:27 -04:00

73 lines
3.9 KiB
Shell
Executable file

#!/usr/bin/env bash
# The wasm32 measurement binding gives the native figures byte for byte, over the corpus
# wai/staged-measure-conformance/:
#
# 1. demo/verify_measure_wasm.mjs runs the wasm32 build under Node: every fixture's
# evaluation against goldens.json, the refusal titles, counting.json, quality.json,
# sim/results.json, the output tree, and the session claim the browser seals;
# 2. the native tool's `wai_stage_measure eval --json` for every fixture must equal the
# wasm32 evaluation byte for byte (cmp);
# 3. every session the wasm32 build sealed, and its altered variants, are verified by
# the native claim verifier (`wai_claim_vectors verdicts`) and by the independent
# Python verifier (`claim-conformance/claim_verify.py verdicts`), and each verdict list
# must equal the one the wasm32 build gave, line for line.
#
# from wai-web/: bash demo/verify_measure.sh [path/to/pkg-node/wai_web.js]
#
# With no argument the nodejs package is built here (cargo, then the wasm-bindgen CLI at
# the version Cargo.lock pins); with one, that package is used, as CI does after building
# it. The native binaries are built in debug under their own target directory, so a
# CARGO_TARGET_DIR shared with other feature sets is not disturbed. claim_verify.py needs
# the `cryptography` package. Any missing artifact fails the run.
set -euo pipefail
cd "$(dirname "$0")/.." # wai-web/
WEB="$(pwd)"
WAI="$(cd .. && pwd)"
for tool in cargo node python3; do
command -v "$tool" >/dev/null || { echo "verify_measure: needs $tool"; exit 1; }
done
OUT="$(mktemp -d)"
trap 'rm -rf "$OUT"' EXIT
PKG="${1:-}"
if [ -z "$PKG" ]; then
command -v wasm-bindgen >/dev/null || { echo "verify_measure: needs the wasm-bindgen CLI"; exit 1; }
# Build output is not discarded: a failed build must show why.
cargo build --locked --release --target wasm32-unknown-unknown
wasm-bindgen --target nodejs --out-dir demo/pkg-node --out-name wai_web \
"${CARGO_TARGET_DIR:-target}/wasm32-unknown-unknown/release/wai_web.wasm"
PKG="$WEB/demo/pkg-node/wai_web.js"
fi
PKG="$(cd "$(dirname "$PKG")" && pwd)/$(basename "$PKG")"
[ -f "$PKG" ] || { echo "verify_measure: missing artifact $PKG"; exit 1; }
echo "== 1. the wasm32 binding over the corpus"
node demo/verify_measure_wasm.mjs "$PKG" "$WAI/staged-measure-conformance" --out "$OUT"
echo "== 2. the native evaluation equals the wasm32 evaluation, byte for byte"
NATIVE_TARGET="${CARGO_TARGET_DIR:-$WAI/wai-rs/target}/verify-measure-native"
( cd "$WAI/wai-rs" && cargo build --locked --no-default-features --features stage_measure,receipt_claims \
--target-dir "$NATIVE_TARGET" --bin wai_stage_measure --bin wai_claim_vectors )
BIN="$NATIVE_TARGET/debug"
for b in wai_stage_measure wai_claim_vectors; do
[ -x "$BIN/$b" ] || { echo "verify_measure: missing artifact $BIN/$b"; exit 1; }
done
n=0
for dir in "$WAI"/staged-measure-conformance/fixtures/*/; do
name="$(basename "$dir")"
[ -f "$OUT/eval-$name.json" ] || { echo "verify_measure: no wasm32 evaluation of $name"; exit 1; }
"$BIN/wai_stage_measure" eval "$dir" --json > "$OUT/native-$name.json"
cmp "$OUT/native-$name.json" "$OUT/eval-$name.json"
echo " $name: identical ($(wc -c < "$OUT/native-$name.json" | tr -d ' ') bytes)"
n=$((n + 1))
done
[ "$n" -ge 4 ] || { echo "verify_measure: only $n fixtures"; exit 1; }
echo "== 3. the browser-sealed sessions, verified natively and independently"
[ -s "$OUT/sessions.json" ] && [ -s "$OUT/verdicts-wasm.txt" ] || { echo "verify_measure: no sessions written"; exit 1; }
"$BIN/wai_claim_vectors" verdicts "$OUT/sessions.json" > "$OUT/verdicts-native.txt"
diff "$OUT/verdicts-wasm.txt" "$OUT/verdicts-native.txt"
python3 "$WAI/claim-conformance/claim_verify.py" verdicts "$OUT/sessions.json" > "$OUT/verdicts-python.txt"
diff "$OUT/verdicts-wasm.txt" "$OUT/verdicts-python.txt"
echo " $(wc -l < "$OUT/verdicts-wasm.txt" | tr -d ' ') verdicts: wasm32, native and Python agree"
echo "verify_measure: OK"