Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
6.0 KiB
6.0 KiB
@suaveplan/api-sandbox-vm - vm.Context-based sandbox host for Suaveplan API plugins running in the sandboxed tier. Builds a frozen-globals vm.Context, loads the plugin via vm.SourceTextModule, rejects dynamic-code constructors and node built-in imports, and routes every fs/fetch/capability call through a host-installed permission-gated proxy surface. Server-tier.
vm.Context-based sandbox host for Suaveplan API plugins running in
the sandboxed tier. The package owns the vm.Context+frozen-globals
half of the design doc §2.2 sandboxed tier; the worker-thread bulkhead
is owned by @suaveplan/api-worker-host and the permission policy is
owned by @suaveplan/api-sandbox-permissions.
Documentation tree
- error-codes — This module owns the stable
SAND_VM.*error-code registry used by every public failure path inside the `@suaveplan/ap…- error-codes — This module owns the stable
SAND_VM.*error-code registry used by every public failure path inside the `@suaveplan/ap…
- error-codes — This module owns the stable
- frozen-globals — This module assembles the curated global allowlist visible inside the
vm.Contextsandbox. Every binding installed her…- frozen-globals — This module assembles the curated global allowlist visible inside the
vm.Contextsandbox. Every binding installed her…
- frozen-globals — This module assembles the curated global allowlist visible inside the
- otel — This module owns the OpenTelemetry instrument bundle emitted by the
vm.Contextsandbox host. Instruments are bound la…- instruments — This module owns the OpenTelemetry instrument bundle emitted by the
vm.Contextsandbox host. Instruments are bound la…
- instruments — This module owns the OpenTelemetry instrument bundle emitted by the
- permissions —
createPermissionCheckercompiles aPermissionsManifest(from@suaveplan/api-types) into a structural `PermissionC…- checker —
createPermissionCheckercompiles aPermissionsManifest(from@suaveplan/api-types) into a structural `PermissionC…
- checker —
- fetch-proxy —
installFetchProxyreturns the outbound-HTTP surface visible inside the sandbox. Every request gates through the suppl…- fetch-proxy —
installFetchProxyreturns the outbound-HTTP surface visible inside the sandbox. Every request gates through the suppl…
- fetch-proxy —
- fs-proxy —
installFsProxyreturns the sandbox-side filesystem surface that plugins consume. Every method gates the call through…- fs-proxy —
installFsProxyreturns the sandbox-side filesystem surface that plugins consume. Every method gates the call through…
- fs-proxy —
- install-capability-proxies —
installCapabilityProxieswires the host-supplied capability bags into the sandbox'svm.Context. The sandbox sees on…- install-capability-proxies —
installCapabilityProxieswires the host-supplied capability bags into the sandbox'svm.Context. The sandbox sees on…
- install-capability-proxies —
- sandbox —
createVmSandboxis the keystone entry point of the package. It materialises avm.ContextwhoseglobalThisis seal…- sandbox —
createVmSandboxis the keystone entry point of the package. It materialises avm.ContextwhoseglobalThisis seal…
- sandbox —
- testing —
runVmSandboxConformance(label, makeSandbox)is the public conformance suite everyvm.Context-based sandbox host mus…- run-vm-conformance —
runVmSandboxConformance(label, makeSandbox)is the public conformance suite everyvm.Context-based sandbox host mus…
- run-vm-conformance —
Modules
| Subpath | Purpose |
|---|---|
./sandbox/sandbox |
createVmSandbox, VmSandboxHandle — builds the frozen vm.Context and drives the plugin lifecycle. |
./globals/frozen-globals/frozen-globals |
Curated allowlist of globals visible inside the sandbox. |
./proxies/fs-proxy/fs-proxy |
Host-proxied filesystem with permission-gated readFile/writeFile. |
./proxies/fetch-proxy/fetch-proxy |
Host-proxied outbound HTTP with permission gating. |
./proxies/install-capability-proxies/install-capability-proxies |
Wires the consolidated __suaveplan receiver into the context. |
./permissions/checker |
In-package default PermissionChecker built from a PermissionsManifest. |
./error-codes/error-codes |
SAND_VM.* registry + SandboxVmError. |
./otel/instruments |
OTel histogram + three counters (boot duration, eval rejection, module-import rejection, permission denial). |
./testing |
runVmSandboxConformance(label, makeSandbox) — the conformance harness every vm sandbox host must pass. |
Quick start
import {
createVmSandbox,
createPermissionChecker,
} from "@suaveplan/api-sandbox-vm";
const checker = createPermissionChecker({
policy: { fs: ["/srv/data/**"], fetch: ["api.example.com"] },
});
const handle = createVmSandbox({
pluginId: "demo",
logger,
checker,
pluginModule: { kind: "path", path: "/srv/plugins/demo.mjs" },
proxies: {
fs: realFsAdapter,
fetch: realFetchAdapter,
capabilities: {},
},
});
await handle.start();
// ... later
handle.dispose();
Runtime requirement
Node ≥ 20 with --experimental-vm-modules enabled at process start.
vm.SourceTextModule is gated behind that flag; the sandbox raises
SAND_VM.SOURCE_TEXT_MODULE_FAILED with a clear hint when the flag is
missing.
Conformance
Pass the package's testing harness against any custom vm-based
sandbox host:
import { runVmSandboxConformance } from "@suaveplan/api-sandbox-vm/testing";
runVmSandboxConformance("my-host", makeMyHandle);