Files
suaveplan/packages/api-stack/api/api-sandbox-vm/src/testing/run-vm-conformance.md
2026-05-27 23:29:53 +01:00

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: 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

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 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.