# Vm sandbox conformance harness _(no submodules)_ ## Purpose `runVmSandboxConformance(label, makeSandbox)` is the public conformance suite every `vm.Context`-based sandbox host must pass. The suite encodes the package's spec ADDED requirements as runnable assertions so any future host implementation (an alternative isolate library, a hardened wrapper, a worker-thread variant) plugs in against the same contract by exporting a single factory function. This module is the reusable bridge between the OpenSpec capability spec and the implementation; checking that a sandbox passes the harness is sufficient to verify it satisfies the public requirements. ## Features - Six assertions covering: `process` global absence, frozen `globalThis`, direct dynamic-code rejection, indirect dynamic-code rejection, node-built-in import refusal, dispose idempotency. - Adapter-driven: the harness calls `makeSandbox(source)` to obtain a fresh handle for every assertion so adapters with non-trivial setup cost can amortise it through closure capture. - Permissive eval-code expectation: the indirect-dynamic case accepts either `EVAL_REJECTED` or `INDIRECT_EVAL_REJECTED` so adapters that implement only the broad trap still pass. ## Usage: Basic ```ts import { runVmSandboxConformance } from "@suaveplan/api-sandbox-vm/testing"; import { createVmSandbox } from "@suaveplan/api-sandbox-vm/sandbox/sandbox"; import { createPermissionChecker } from "@suaveplan/api-sandbox-vm/permissions/checker"; runVmSandboxConformance("self", async (source) => createVmSandbox({ pluginId: "self", logger: console as never, checker: createPermissionChecker({ policy: {} }), pluginModule: { kind: "source", identifier: "x", source }, proxies: { fs: { readFile: async () => "", writeFile: async () => undefined }, fetch: { request: async () => ({ status: 204, headers: {}, body: "" }), }, capabilities: {}, }, }) ); ``` ## Usage: Advanced Compose with a stricter checker and a pre-baked capability bag so the harness also exercises the host's `__suaveplan` receiver: ```ts import { runVmSandboxConformance } from "@suaveplan/api-sandbox-vm/testing"; import { createVmSandbox } from "@suaveplan/api-sandbox-vm/sandbox/sandbox"; runVmSandboxConformance("strict", async (source) => createVmSandbox({ pluginId: "strict", logger, checker: strictChecker, pluginModule: { kind: "source", identifier: "strict.mjs", source }, proxies: { fs: realFs, fetch: realFetch, capabilities: { db: { query: async (sql) => realQuery(String(sql)) }, }, }, }) ); ``` ## API Reference - `runVmSandboxConformance(label, makeSandbox)` — register the suite under `runVmSandboxConformance — ${label}`. - `type MakeVmSandbox` — factory accepting plugin source text and returning a `VmSandboxHandle` (synchronously or via Promise). ## Implementation Notes The harness uses `@suaveplan/testing/runner` so it remains runner- agnostic — Bun-mode and Vitest-mode test runs see identical descriptions and assertion semantics. Sandbox source strings are constructed by concatenation rather than tagged templates so the emitted code never references a host-side binding. The `EVAL_TOK` token-split is a defence against static analysers that would otherwise flag the harness as containing direct `eval` usage — the harness exercises the trap, not the function. Disposal happens inside every assertion so the harness never leaks contexts; the adapter is responsible for tearing the handle down promptly.