# Copyright (C) 2026 Kingsrook, LLC. # SPDX-License-Identifier: Apache-2.0 <# .SYNOPSIS Reproduce the fixed Javy/QuickJS Wasm guest from locked inputs and verify it against PINNED-WASM.json. .DESCRIPTION Offline only. Never downloads an SDK or crate. Refuses an existing output directory. Verifies, before building: Cargo.lock/source-input hashes, the Rust compiler commit, and the already-extracted WASI SDK's clang version line plus clang.exe, libclang.dll and wasi libc hashes. After building: the artifact must match the pinned sha256 and length, otherwise the script fails. Run it twice with different -OutputDir values (and, ideally, from different checkouts) to prove reproducibility. Writes provenance.json next to the artifact. .EXAMPLE pwsh -File Build-Wasm.ps1 -SdkRoot C:/tools/wasi-sdk-33.0-x86_64-windows -OutputDir C:/new/output-1 #> param( [Parameter(Mandatory)][string]$SdkRoot, [Parameter(Mandatory)][string]$OutputDir ) $ErrorActionPreference = 'Stop' $root = $PSScriptRoot $pin = Get-Content -Raw (Join-Path $root 'PINNED-WASM.json') | ConvertFrom-Json function Sha256Of([string]$path) { (Get-FileHash -Algorithm SHA256 -LiteralPath $path).Hash.ToLowerInvariant() } function Require([bool]$condition, [string]$message) { if (-not $condition) { throw "Build-Wasm refused: $message" } } Require ([IO.Path]::IsPathRooted($OutputDir)) 'OutputDir must be absolute' Require (-not (Test-Path -LiteralPath $OutputDir)) 'OutputDir must not already exist' Require (Test-Path -LiteralPath $SdkRoot) 'SdkRoot not found' # 1. locked source inputs $combined = New-Object System.Text.StringBuilder foreach ($name in $pin.sourceInputs) { [void]$combined.Append($name + "`n" + (Sha256Of (Join-Path $root $name)) + "`n") } $sha = [Security.Cryptography.SHA256]::Create() $inputsHash = ([BitConverter]::ToString($sha.ComputeHash([Text.Encoding]::UTF8.GetBytes($combined.ToString()))) -replace '-', '').ToLowerInvariant() Require ($inputsHash -eq $pin.sourceInputsSha256) "source inputs differ from PINNED-WASM.json (have $inputsHash); re-pin only after a reviewed source change" Require ((Sha256Of (Join-Path $root 'Cargo.lock')) -eq $pin.cargoLockSha256) 'Cargo.lock differs from the pin' # 2. toolchain $rustc = (& rustc "+$($pin.toolchain.rust)" -vV) -join "`n" Require ($rustc -match "commit-hash: $($pin.toolchain.rustcCommitHash)") 'rustc commit differs from the pin' $sdkInfo = $pin.toolchain.wasiSdk $clang = Join-Path $SdkRoot 'bin/clang.exe' Require ((Sha256Of $clang) -eq $sdkInfo.clangExeSha256) 'SDK clang.exe differs from the pin' Require ((Sha256Of (Join-Path $SdkRoot 'bin/libclang.dll')) -eq $sdkInfo.libclangDllSha256) 'SDK libclang.dll differs from the pin' Require ((Sha256Of (Join-Path $SdkRoot 'share/wasi-sysroot/lib/wasm32-wasip1/libc.a')) -eq $sdkInfo.wasiLibcSha256) 'SDK wasi libc differs from the pin' Require (((& $clang --version) | Select-Object -First 1) -eq $sdkInfo.clangVersionLine) 'SDK clang version line differs from the pin' $clangInclude = Get-ChildItem (Join-Path $SdkRoot 'lib/clang') -Directory | Select-Object -First 1 Require ($null -ne $clangInclude) 'SDK has no clang resource directory' # 3. build (new output directory; offline; locked) New-Item -ItemType Directory -Path $OutputDir | Out-Null $saved = @{} foreach ($key in 'CARGO_TARGET_DIR', 'WASI_SDK', 'LIBCLANG_PATH', 'BINDGEN_EXTRA_CLANG_ARGS') { $saved[$key] = [Environment]::GetEnvironmentVariable($key) } try { $env:CARGO_TARGET_DIR = (Join-Path $OutputDir 'cargo-target') $env:WASI_SDK = $SdkRoot $env:LIBCLANG_PATH = (Join-Path $SdkRoot 'bin') # forward slashes: the clang-args parser treats backslashes as escapes $env:BINDGEN_EXTRA_CLANG_ARGS = '-isystem ' + ((Join-Path $clangInclude.FullName 'include') -replace '\\', '/') Push-Location $root try { & cargo "+$($pin.toolchain.rust)" build --release --target $pin.toolchain.target --offline --locked if ($LASTEXITCODE -ne 0) { throw "cargo build failed ($LASTEXITCODE)" } } finally { Pop-Location } } finally { foreach ($key in $saved.Keys) { [Environment]::SetEnvironmentVariable($key, $saved[$key]) } } # 4. verify against the pin and record provenance $built = Join-Path $OutputDir "cargo-target/$($pin.toolchain.target)/release/qqq_javy_runtime.wasm" $artifact = Join-Path $OutputDir $pin.artifact Copy-Item -LiteralPath $built -Destination $artifact $actual = Sha256Of $artifact $length = (Get-Item -LiteralPath $artifact).Length $result = [ordered]@{ artifact = $pin.artifact; sha256 = $actual; bytes = $length; pinnedSha256 = $pin.sha256; matchesPin = ($actual -eq $pin.sha256 -and $length -eq $pin.bytes) sourceInputsSha256 = $inputsHash; cargoLockSha256 = $pin.cargoLockSha256 rustc = ($rustc -split "`n" | Select-Object -First 1); wasiSdkClang = $sdkInfo.clangVersionLine builtAtUtc = [DateTime]::UtcNow.ToString('o') } ($result | ConvertTo-Json) | Set-Content -LiteralPath (Join-Path $OutputDir 'provenance.json') -Encoding utf8 Require $result.matchesPin "built artifact $actual ($length bytes) does not match the pin $($pin.sha256)" Write-Output ($result | ConvertTo-Json -Compress)