3.7 KiB
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:
processglobal absence, frozenglobalThis, 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_REJECTEDorINDIRECT_EVAL_REJECTEDso adapters that implement only the broad trap still pass.
Usage: Basic
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:
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 underrunVmSandboxConformance — ${label}.type MakeVmSandbox— factory accepting plugin source text and returning aVmSandboxHandle(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.