93 lines
6.0 KiB
Markdown
93 lines
6.0 KiB
Markdown
# @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`.
|
|
|
|
<!-- begin:auto-docs -->
|
|
## Documentation tree
|
|
|
|
- [error-codes](./src/error-codes/error-codes.md) — This module owns the stable `SAND_VM.*` error-code registry used by every public failure path inside the `@suaveplan/ap…
|
|
- [error-codes](./src/error-codes/error-codes.md) — This module owns the stable `SAND_VM.*` error-code registry used by every public failure path inside the `@suaveplan/ap…
|
|
- [frozen-globals](./src/globals/frozen-globals/frozen-globals.md) — This module assembles the curated global allowlist visible inside the `vm.Context` sandbox. Every binding installed her…
|
|
- [frozen-globals](./src/globals/frozen-globals/frozen-globals.md) — This module assembles the curated global allowlist visible inside the `vm.Context` sandbox. Every binding installed her…
|
|
- [otel](./src/otel/instruments.md) — This module owns the OpenTelemetry instrument bundle emitted by the `vm.Context` sandbox host. Instruments are bound la…
|
|
- [instruments](./src/otel/instruments.md) — This module owns the OpenTelemetry instrument bundle emitted by the `vm.Context` sandbox host. Instruments are bound la…
|
|
- [permissions](./src/permissions/checker.md) — `createPermissionChecker` compiles a `PermissionsManifest` (from `@suaveplan/api-types`) into a structural `PermissionC…
|
|
- [checker](./src/permissions/checker.md) — `createPermissionChecker` compiles a `PermissionsManifest` (from `@suaveplan/api-types`) into a structural `PermissionC…
|
|
- [fetch-proxy](./src/proxies/fetch-proxy/fetch-proxy.md) — `installFetchProxy` returns the outbound-HTTP surface visible inside the sandbox. Every request gates through the suppl…
|
|
- [fetch-proxy](./src/proxies/fetch-proxy/fetch-proxy.md) — `installFetchProxy` returns the outbound-HTTP surface visible inside the sandbox. Every request gates through the suppl…
|
|
- [fs-proxy](./src/proxies/fs-proxy/fs-proxy.md) — `installFsProxy` returns the sandbox-side filesystem surface that plugins consume. Every method gates the call through…
|
|
- [fs-proxy](./src/proxies/fs-proxy/fs-proxy.md) — `installFsProxy` returns the sandbox-side filesystem surface that plugins consume. Every method gates the call through…
|
|
- [install-capability-proxies](./src/proxies/install-capability-proxies/install-capability-proxies.md) — `installCapabilityProxies` wires the host-supplied capability bags into the sandbox's `vm.Context`. The sandbox sees on…
|
|
- [install-capability-proxies](./src/proxies/install-capability-proxies/install-capability-proxies.md) — `installCapabilityProxies` wires the host-supplied capability bags into the sandbox's `vm.Context`. The sandbox sees on…
|
|
- [sandbox](./src/sandbox/sandbox.md) — `createVmSandbox` is the keystone entry point of the package. It materialises a `vm.Context` whose `globalThis` is seal…
|
|
- [sandbox](./src/sandbox/sandbox.md) — `createVmSandbox` is the keystone entry point of the package. It materialises a `vm.Context` whose `globalThis` is seal…
|
|
- [testing](./src/testing/run-vm-conformance.md) — `runVmSandboxConformance(label, makeSandbox)` is the public conformance suite every `vm.Context`-based sandbox host mus…
|
|
- [run-vm-conformance](./src/testing/run-vm-conformance.md) — `runVmSandboxConformance(label, makeSandbox)` is the public conformance suite every `vm.Context`-based sandbox host mus…
|
|
<!-- end:auto-docs -->
|
|
|
|
## 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
|
|
|
|
```ts
|
|
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:
|
|
|
|
```ts
|
|
import { runVmSandboxConformance } from "@suaveplan/api-sandbox-vm/testing";
|
|
|
|
runVmSandboxConformance("my-host", makeMyHandle);
|
|
```
|
|
|