first commit
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
# run-wasm-conformance
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Exports `runWasmSandboxConformance(label, makeSandbox)` — the
|
||||
conformance harness every WASM-tier sandbox host (this package's own,
|
||||
or any future implementation) MUST pass. The harness pins the
|
||||
observable contract: preopens reflect `policy.fs[]`, the outbound
|
||||
allowlist reflects `policy.fetch[]`, the `rw:` prefix turns a preopen
|
||||
read-write, `dispose()` is idempotent, and the instrument registry
|
||||
exposes the canonical `plugin.permission_denied_total` counter.
|
||||
|
||||
The harness is exported from the `./testing` subpath so adapters
|
||||
consume it as a normal import. The in-package fixture sandbox passes
|
||||
every scenario; the harness is self-tested via
|
||||
`run-wasm-conformance.test.ts`.
|
||||
|
||||
## Features
|
||||
|
||||
- Six pinned scenarios covering the spec delta's observable behaviour.
|
||||
- Uses the host's `describe`/`it` from `@suaveplan/testing/runner` so
|
||||
adapter test reports show nested suites under the host's tree.
|
||||
- `WasmSandboxFactory` signature lets adapters pass a minimal builder
|
||||
rather than re-implementing the full `createWasmSandbox` surface.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
// In an adapter package's test file:
|
||||
import { runWasmSandboxConformance } from "@suaveplan/api-sandbox-wasm/testing";
|
||||
import { makeMyAdapterSandbox } from "./my-adapter.js";
|
||||
|
||||
runWasmSandboxConformance("my-adapter", makeMyAdapterSandbox);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
runWasmSandboxConformance("with-cache", async (input) => {
|
||||
const cached = sandboxCache.get(JSON.stringify(input));
|
||||
if (cached !== undefined) return cached;
|
||||
const handle = await createWasmSandbox({ /* ... */ });
|
||||
sandboxCache.set(JSON.stringify(input), handle);
|
||||
return handle;
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `runWasmSandboxConformance(label: string, makeSandbox: WasmSandboxFactory): void`
|
||||
- `WasmSandboxFactory = (input) => Promise<WasmSandboxHandle>` where
|
||||
`input` is `{ fsRules, fetchRules, denyCapability }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The harness consumes the adapter's `WasmSandboxHandle` via its public
|
||||
surface only — `preopens`, `outbound`, `instruments`, and `dispose()`.
|
||||
Adapters that wrap or proxy the handle must preserve those properties
|
||||
identically.
|
||||
|
||||
The harness deliberately uses `dispose()` after every scenario rather
|
||||
than letting GC handle it, because a WASM-runtime under load can pin
|
||||
memory longer than the test budget allows. Adapters that hold open OS
|
||||
resources MUST close them in `dispose()` for the harness to pass on
|
||||
constrained CI runners.
|
||||
Reference in New Issue
Block a user