# @smithers-orchestrator/sandbox — src

What lives here:

- `execute.js` — `executeSandbox()`, the full sandbox lifecycle: DB rows,
  SmithersEvents, heartbeats, concurrency limit, and the diff-review gate.
  Runs through either a registered `SandboxProvider` (provider path) or a
  local `SandboxTransport` runtime (transport path).
- `bundle.js` — write/validate result bundles with size, symlink, and
  path-escape enforcement (`README.md` manifest + `patches/`, `artifacts/`,
  `logs/`).
- `egress.js` — network egress config: normalize, env projection, redaction,
  and CA cert materialization into the request bundle.
- `transport.js` — the `SandboxTransport` Effect service tag and
  runtime → layer selection (bubblewrap/docker/codeplane; see `effect/`).
- `sandboxPath.js` — root-confinement path resolution used by bundle
  validation and by packages/smithers tools.
- Type-only `.ts` sidecars (`SandboxHandle`, `SandboxProvider`,
  `ExecuteSandboxOptions`, ...) — never convert to/from `.js`.

Entry points: the package export `.` is `index.js` (bundle + egress +
execute + transport re-exports), and every src file is individually
importable via the `./*` subpath export — treat all exports here as public.

## Provider kit

`provider-kit/` is the shared foundation every command-backed sandbox provider
package (cloudflare, and the four downstream providers) builds on. Import it
from the package root or `./provider-kit`.

- `createCommandSandboxProvider(options)` returns a `SandboxProvider`
  (`{ id, run, cleanup }`). It handles the whole remote lifecycle: ship the
  request JSON, materialize the egress CA, inject env, exec the command, read
  and parse the result, scrub secrets from errors, and destroy the session on
  cleanup. Providers supply only a `createSession(request)` factory plus
  `id`/`command`/`workdir`/`env`/`cleanup` overrides.
- `SandboxSession` is the seam each provider implements over its vendor SDK:
  `{ remoteId, writeFile, readFile, exec(command, { cwd, env, timeoutMs, signal }), destroy? }`.
  The kit talks only to this interface, so a provider never re-implements request
  shipping or result parsing.
- The command entry reads the request JSON and writes the result JSON at
  `SMITHERS_SANDBOX_REQUEST_PATH` / `SMITHERS_SANDBOX_RESULT_PATH`
  (`SANDBOX_PROVIDER_REQUEST_ENV` / `SANDBOX_PROVIDER_RESULT_ENV`), or prints the
  result JSON to stdout.
- `createSandboxProviderContractSuite({ name, expectedProviderId, createProvider })`
  defines a reusable `bun:test` suite so each provider package proves the happy
  path and SandboxProvider shape invariants against its own `createProvider`
  factory. `createProvider(handler, providerOptions?)` builds a provider whose
  remote exec runs `handler({ command, request, files, env })` and writes the
  returned value to the result file; `providerOptions` merge into construction.
  Exhaustive error, redaction, and timeout paths live in the kit's own unit test.
- Helpers `writeSandboxProviderRequestFile`, `parseSandboxProviderResult`,
  `uploadEgressCaToSession`, and `redactSandboxProviderValue` are exported for
  providers that need finer control.

Gotchas: `index.d.ts` is generated by `tsup --dts-only`, never hand-edit;
`transport.js` opens with a tool-managed `@smithers-type-exports` block that
must stay byte-for-byte; the `cloudflare` runtime deliberately has no local
layer (it requires a provider from `smithers-orchestrator/cloudflare`);
packages/engine re-exports the `effect/` modules, so renames there break it.
