Files
f0d695ec97
QRun-IO/ci-policy: ci / fork-guard (push) Skipped
QRun-IO/ci-policy: ci / head-profile (push) Skipped
QRun-IO/ci-policy: ci / application-template-0 (push) Skipped
QRun-IO/ci-policy: ci / gradle-1 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3 (push) Skipped
QRun-IO/ci-policy: ci / java-docker-4 (push) Skipped
QRun-IO/ci-policy: ci / java-frontend-browser-5 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6 (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7 (push) Skipped
QRun-IO/ci-policy: ci / node-8 (push) Skipped
QRun-IO/ci-policy: ci / node-9 (push) Skipped
QRun-IO/ci-policy: ci / node-10 (push) Skipped
QRun-IO/ci-policy: ci / node-playwright-11 (push) Skipped
QRun-IO/ci-policy: ci / repository-policy-12 (push) Skipped
QRun-IO/ci-policy: ci / source-config-13 (push) Skipped
QRun-IO/ci-policy: ci / source-config-14 (push) Skipped
QRun-IO/ci-policy: ci / android-0 (push) Skipped
QRun-IO/ci-policy: ci / original-business (push) Skipped
QRun-IO/ci-policy: ci / original-mcp (push) Skipped
QRun-IO/ci-policy: ci / original-voyage (push) Skipped
QRun-IO/ci-policy: ci / original-cli (push) Skipped
QRun-IO/ci-policy: ci / repository-policy (push) Skipped
QRun-IO/ci-policy: ci / java-core-2-head (push) Skipped
QRun-IO/ci-policy: ci / java-docker-3-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-6-head (push) Skipped
QRun-IO/ci-policy: ci / java-maven-7-head (push) Skipped
QRun-IO/ci-policy: ci / not-enrolled (push) Failing after 7s
QRun-IO/ci-policy: native / fork-deny (push) Skipped
QRun-IO/ci-policy: native / dotnet-0 (push) Skipped
QRun-IO/ci-policy: ci / ci-result (push) Failing after 6s
QRun-IO/ci-policy: native / native-result (push) Successful in 6s
chore: preserve paused QBit work and document remaining issues
Save the current implementation and README, status, and known-issue documentation at the user-requested stop. No completed release or deployment is claimed.

Co-Authored-By: Claude <noreply@anthropic.com>

Co-Authored-By: GPT-6 Codex <noreply@openai.com>
2026-11-04 10:45:28 -06:00

87 lines
5.0 KiB
PowerShell

# 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)