# @coda/sandbox

Isolated V8 code execution engine built on [`isolated-vm`](https://github.com/nicolo-ribaudo/isolated-vm). Provides secure, memory-limited sandboxes for running user-defined datasource scripts within the runner service.

## Installation

```jsonc
// package.json
{ "dependencies": { "@coda/sandbox": "workspace:*" } }
```

## Usage

```ts
import {
  SandboxEngine,
  type SandboxEngineConfig,
  DEFAULT_ISOLATE_LIMITS,
  DEFAULT_BRIDGE_LIMITS,
} from "@coda/sandbox";

const config: SandboxEngineConfig = {
  memoryMb: 128,
  maxConcurrentIsolates: 4,
  warmPoolSize: 2,
  wasmModules: [],
  defaultIsolateLimits: DEFAULT_ISOLATE_LIMITS,
  defaultBridgeLimits: DEFAULT_BRIDGE_LIMITS,
};

const engine = new SandboxEngine(config);
await engine.init();

// Submit an execution request (non-blocking)
const session = engine.submit({
  requestId: "req_123",
  code: "return data.accounts.length;",
  // ... isolateLimits, bridgeLimits, toolPolicy
});

// Consume events from the session
for await (const event of session) {
  switch (event.type) {
    case "status":
      console.log("Status:", event.message);
      break;
    case "dataRequest":
      /* supply data back to the isolate */ break;
    case "result":
      console.log("Result:", event.data);
      break;
    case "error":
      console.error("Error:", event.message);
      break;
  }
}

await engine.shutdown();
```

## API Reference

### SandboxEngine

| Method        | Description                                           |
| ------------- | ----------------------------------------------------- |
| `init()`      | Load WASM modules and warm the isolate pool           |
| `submit(req)` | Submit an execution request, returns `SandboxSession` |
| `shutdown()`  | Drain all isolates and shut down                      |

Constructor accepts `SandboxEngineConfig` and optional `Partial<SandboxEngineDeps>` for dependency injection in tests.

### Configuration

```ts
interface SandboxEngineConfig {
  memoryMb: number; // Memory per isolate
  maxConcurrentIsolates: number; // Max parallel isolates
  warmPoolSize: number; // Pre-warmed isolates ready for use
  wasmModules: WasmModuleConfig[];
  defaultIsolateLimits: IsolateLimits;
  defaultBridgeLimits: BridgeLimits;
}
```

### Error Classes

All errors extend `SandboxError`:

| Error                    | Description                              |
| ------------------------ | ---------------------------------------- |
| `SandboxError`           | Base error class                         |
| `SandboxTimeoutError`    | Execution exceeded time limit            |
| `SandboxOOMError`        | Isolate exceeded memory limit            |
| `SandboxRuntimeError`    | Script threw during execution            |
| `SandboxValidationError` | Invalid input (bad code, missing fields) |
| `SandboxAbortedError`    | Execution was aborted by the caller      |

### Message Types

The host↔isolate bridge uses typed messages:

**Inbound (host → isolate):**

| Type                  | Description                            |
| --------------------- | -------------------------------------- |
| `ExecuteMessage`      | Initial execution request with code    |
| `DataResponseMessage` | Data supplied in response to a request |

**Outbound (isolate → host):**

| Type                 | Description                           |
| -------------------- | ------------------------------------- |
| `StatusMessage`      | Execution progress update             |
| `DataRequestMessage` | Isolate requesting data from the host |
| `ResultMessage`      | Final execution result                |
| `ErrorMessage`       | Execution error                       |

### Other Exports

| Export                   | Description                                     |
| ------------------------ | ----------------------------------------------- |
| `DEFAULT_MEMORY_MB`      | Default memory per isolate (128 MB)             |
| `DEFAULT_ISOLATE_LIMITS` | Default isolate resource limits                 |
| `DEFAULT_BRIDGE_LIMITS`  | Default bridge message limits                   |
| `IsolateLimits`          | CPU/memory/wall-clock limits for an isolate     |
| `BridgeLimits`           | Message size and count limits for the bridge    |
| `ToolPolicy`             | Permissions for tool access within the sandbox  |
| `ExecutionStats`         | CPU, memory, and wall-clock statistics          |
| `SandboxSession`         | Async iterable of outbound events               |
| `SandboxEngineConfig`    | Engine configuration                            |
| `SandboxEngineDeps`      | Injectable dependencies (isolate manager, etc.) |
| `SessionFactory`         | Factory function for creating sessions          |
| `WasmModuleConfig`       | WASM module loading configuration               |
| `IsolateStats`           | Per-isolate resource usage statistics           |

## Architecture

See the detailed docs:

- [Architecture](../../docs/architecture/sandbox.md) — design overview and isolate lifecycle
- [API Reference](../../docs/api/sandbox.md) — full endpoint and message documentation
- [Security](../../docs/compliance/sandbox-security.md) — isolation guarantees and threat model

## Key files

| Path             | Description                                               |
| ---------------- | --------------------------------------------------------- |
| `src/index.ts`   | Public exports                                            |
| `src/engine.ts`  | Engine lifecycle: warm pool, isolate allocation, sessions |
| `src/bridge/`    | Host↔isolate messaging protocol and type definitions      |
| `src/execution/` | Isolate creation, WASM loading, execution loop            |

## Building

```bash
pnpm --filter @coda/sandbox build
```
