4.7 KiB
4.7 KiB
Tasks: enterprise-server-sandbox
Change ID: enterprise-server-sandbox
Package: @suaveplan/sandbox
Target path: server/infra/sandbox
Prerequisites on Verdaccio: @suaveplan/error, @suaveplan/types, @suaveplan/logger
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree per
proposal.md. package.jsonat0.1.0,"sideEffects": false, exports"."+worker+processsubpaths.- Deps:
@suaveplan/error workspace:^,@suaveplan/types workspace:^,@suaveplan/logger workspace:^,zod catalog:forms,@opentelemetry/api catalog:observability,tslib catalog:build. - DevDeps:
vitest catalog:testing,@vitest/coverage-istanbul catalog:testing,@suaveplan/testing workspace:^. tsconfig.jsonextendinglibrary-node.json;vitest.config.tswithpool: 'forks',setupFiles: ['@suaveplan/testing/polyfills'].- Scripts:
lint,typecheck,test,test:coverage,build,docs:check.
2. Types and errors
- Define all interfaces and Zod schemas (
SandboxOptionsSchema,RunOptionsSchema) insrc/types/sandbox.types.ts. - Write
sandbox.types.md(≥200 words, both examples, API reference). src/error-codes.ts: five codes;registerSandboxErrorCodes(); eager call.
3. Worker sandbox
- Write
src/worker/sandbox-worker-script.ts: minimal worker entry that receives{ code, context }viaself.onmessage, evaluates code in aFunction('context', code)(context)with captured stdout/stderr, posts result back, handles errors. - Implement
WorkerSandboxinsrc/worker/worker-sandbox/worker-sandbox.ts:- Creates a new
Worker(sandboxWorkerScript)perrun()call (for isolation reset). - Posts
{ code, context }to worker; sets a timeout viaAbortController; on timeout terminate worker and throwSANDBOX_TIMEOUT. - Captures postMessage response as
SandboxResult. dispose(): no-op (workers are per-run).- OTel: span
sandbox.run, countersandbox.runs_total, histogramsandbox.duration_ms.
- Creates a new
- Write
worker-sandbox.test.ts(≤500 lines): simple return value; console.log captured; context injection; timeout; syntax error (ok: false, error set); abort signal;{ timeout: 15000 }. - Write
worker-sandbox.md(≥200 words).
4. Process sandbox
- Implement
ProcessSandboxinsrc/process/process-sandbox/process-sandbox.ts:run(code, context, options): write a temp JS file; spawnbun run <tempFile>withstdin: JSON.stringify(context); capture stdout/stderr; enforce timeout by killing process; returnSandboxResult.- Propagate exit code; on non-zero, set
ok: false. dispose(): clean up temp files.- OTel: same instrumentation as worker sandbox.
- Write
process-sandbox.test.ts(≤500 lines): same scenarios as worker sandbox, plus process exit code handling. - Write
process-sandbox.md(≥200 words).
5. Security tests
- Write
tests/security.test.ts(≤500 lines,{ timeout: 15000 }):- Code attempting
process.exit()is caught and sandbox returns error. - Code attempting
require('fs').readFileSync('/etc/passwd')is blocked (process sandbox withallowFs: false). - Infinite loop hits timeout correctly.
- Code throwing large strings does not OOM the test runner.
- Context values are not accessible outside the sandbox (no prototype pollution).
- Code attempting
6. Integration tests
tests/integration.test.ts: worker + process sandbox run same set of test snippets; verify identical results;{ timeout: 30000 }.
7. Docs + verify + publish
- Root
README.md: security model explanation, worker vs process trade-offs, quick-start examples, API table. bunx turbo lint --filter=@suaveplan/sandbox— zero errors.bunx turbo typecheck --filter=@suaveplan/sandbox— zero errors.bunx turbo test --filter=@suaveplan/sandbox— all pass.bunx turbo test:coverage --filter=@suaveplan/sandbox— 100%.bun scripts/publish.ts --package @suaveplan/sandbox.- Update
CLAUDE.md; archive toopenspec/archive/2026-04-24-enterprise-server-sandbox/.