first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View File

@@ -0,0 +1,50 @@
# `validateAbi` — post-Javy module reflection
## Purpose
`validateAbi` is step 5 of the TS->WASM compilation pipeline: it runs `WebAssembly.compile(bytes)` against Javy's output and reflects the resulting module to assert the WASI-stdio variant's surface contract. The contract has two halves: required *exports* (`memory` + `_start`) and required *imports* (`wasi_snapshot_preview1.{fd_read, fd_write, environ_get, environ_sizes_get, proc_exit}`).
Mirroring the host bridge's `REQUIRED_WASI_STDIO_IMPORTS` list intentionally: the bridge instantiates the module against its own snapshot of those imports, and any future divergence between the lists would cause one half of the system to ship validations the other cannot satisfy. Single-sourcing the list in spec ensures the bridge and compiler stay in lock-step; this module hard-codes its own copy because cycling the import via `@suaveplan/api-sandbox-wasm-host-bridge` would pull a 30+ file graph into the compiler's static surface.
## Features
- One-shot `WebAssembly.compile` returns both the validation verdict AND a reusable `Module` — the orchestrator threads the same `Module` into the route-extract step so we never compile twice.
- Failure mode `compile_failed` (`WebAssembly.compile` threw) is separated from `ABI_VALIDATION_FAILED` (compile succeeded, exports/imports incomplete) via `context.reason`.
- Per-missing-item `recordAbiFailure` increments thread through the optional `instruments` so dashboards can split the failure rate by which symbol vanished — useful when a Javy upgrade silently drops `clock_time_get` or similar.
- Missing list is sorted for diagnostic stability.
## Usage: Basic
```ts
import { validateAbi } from "@suaveplan/wasm-compiler-javy";
import { readFile } from "node:fs/promises";
const bytes = await readFile("/tmp/plugin.wasm");
const { module } = await validateAbi({ wasmBytes: bytes });
```
## Usage: Advanced
```ts
import { validateAbi, createWasmCompilerInstruments } from "@suaveplan/wasm-compiler-javy";
const instr = createWasmCompilerInstruments();
try {
const { module } = await validateAbi({ wasmBytes, instruments: instr });
// forward `module` to route-extract
} catch (err) {
// `recordAbiFailure` has already counted the missing exports for the dashboard.
throw err;
}
```
## API Reference
- `validateAbi(options: ValidateAbiOptions): Promise<ValidateAbiResult>` — entrypoint.
- `ValidateAbiOptions: { wasmBytes: Uint8Array; instruments?: WasmCompilerInstruments }`.
- `ValidateAbiResult: { module: WebAssembly.Module }`.
- `REQUIRED_WASI_IMPORTS` / `REQUIRED_EXPORTS` — frozen string-array registries.
## Implementation Notes
`WebAssembly.compile` is the only piece of the validator that crosses the JS/WASM boundary. The reflection methods `WebAssembly.Module.imports(module)` and `WebAssembly.Module.exports(module)` are pure JS — they walk parsed metadata without touching memory or invoking the runtime. The compiled `Module` is opaque to the validator but the orchestrator hands it to the route-extract step, which instantiates it against a host-built WASI snapshot to fish the routes out. The implementation deliberately does NOT cycle through `@suaveplan/api-sandbox-wasm-host-bridge` so the compiler's static graph stays compact; the bridge re-validates anyway when its `buildWasiStdioInstall` runs, so a one-pass divergence cannot leak past the host's installPlugin call.