# Fixed Wasm guest: locked reproducible build and pin (updated 2026-11-02) The fixed Javy/QuickJS guest `qqq_javy_runtime.wasm` is pinned in `PINNED-WASM.json` (sha256, length, the exact source inputs and their hash, Cargo.lock hash, Rust commit, WASI SDK identity). `deploy/snapshot_execution.py` (`WASM_SHA`), the license inventory, import inventory and review doc all carry the same hash, and `deploy/test_deploy.py` (`PinnedWasmTest`) fails if any of them, the Wasm source inputs or Cargo.lock drift apart. Change the guest source only together with a reviewed re-pin. ## Reproduce (operator, offline, no network) ```text pwsh -File wasm-runtime/Build-Wasm.ps1 -SdkRoot -OutputDir ``` `Build-Wasm.ps1` refuses an existing output directory, verifies the source-input hash and Cargo.lock against the pin, the Rust 1.97.1 compiler commit, and the SDK's clang version line plus `clang.exe`, `libclang.dll` and WASI libc hashes; sets `WASI_SDK`, `LIBCLANG_PATH` and `BINDGEN_EXTRA_CLANG_ARGS` (forward slashes; the rquickjs-sys build script must never download an SDK); runs `cargo +1.97.1 build --release --target wasm32-wasip1 --offline --locked`; then FAILS unless the artifact equals the pinned sha256 and length. It writes `provenance.json` next to the artifact. Inputs: WASI SDK 33.0 archive sha256 `df14ca2a2127c2d6b6be07e6f5549b3af9c1b3c0112430c200a4749970c59f06` (extracted copy used here: root's `qqq-javy-wasi-tools-20261031/sdk-extracted`), Rust 1.97.1 with the `wasm32-wasip1` target. ## Current pin `4b247288d6cdff6783f8087a2a9039935f50af9099451cc841a3639c9625a18c`, 1,567,189 bytes, source inputs `ec834dc9d9d10e360c7abcb10c811e6dd892ce744bb40974a068e01908530cb7`. Reproduced twice from clean copies in different directories and different output directories with identical hash (`repro-A`, `repro-B` logs). A one-byte source change is refused before any build. ## Why the pin changed (finding) The earlier pin `ca72ac7d72a0876a2c602fe6b73c9ded7ead35fbba6f4034ee544345a38557af` was built before a standards pass added a 3-line license header to each `src/*.rs` on 2026-11-01. Rebuilding the CURRENT inputs with those 3 lines removed, using this same recipe and toolchain, reproduces `ca72...` exactly, so the original recipe is recovered. The two artifacts differ in exactly 9 bytes, all Rust panic-location line numbers (each +3); the type, import, function, export, code and custom Wasm sections are byte-identical (only the data section differs). Reverting the headers would violate the repository's header standard, so the owned source is re-pinned to the artifact built from current source. The old artifact is still the one inside the existing image `qqq-script-execution:qualification-20261031-1` and the root's old context; they were not modified, and `snapshot_execution.py --verify` of that old context now refuses under the new pin by design. ## Evidence (trusted local only; `productionQualified=false`) 12 native tests and clippy `-D warnings` pass from the clean checkout; the native fixed-Wasm + Extism supervisor corpus passes with the new artifact in the existing image (private evidence, not carried in this tree).