# `@agy/sandbox-gateway` Housekeeping for the only sanctioned path for running untrusted code. ```bash pnpm --filter @agy/sandbox-gateway run # one pass, then exit pnpm --filter @agy/sandbox-gateway dev # poll every 10 minutes ``` ## What it does 1. **Reaps idle sessions.** A sandbox session nobody has touched for hours is still consuming CPU and disk on the provider. The worker stops it. 2. **Audits the stop.** It writes a `sandbox.reap` audit event, because "the platform killed my sandbox" must be answerable from the audit log. A session whose workspace has vanished is still stopped — just recorded without an organization. 3. **Reports the safety envelope** at startup: which provider is live, the command timeout, the output cap and the default egress policy. An operator should be able to see the limits without reading the source. ## What it deliberately does **not** do **It never executes a command.** The only command path is `SandboxService.run_command`, reachable from the API under a tenant check. This worker only *stops* things. ## Implementation `apps/api/app/workers/sandbox_gateway.py`; the state change itself lives in `SandboxService.reap_idle_sessions`, which is explicitly **not** tenant-scoped and therefore not reachable from any tenant-scoped route. Tests: `apps/api/tests/test_workers.py`. ## Extracting this into its own process ```bash DATABASE_URL=... python -m app.workers sandbox-gateway --loop --interval 600 ``` When a real provider (`SANDBOX_PROVIDER=daytona|e2b`) is configured, this is the process that should own provider-side teardown, so that a crash of the API does not leak sandboxes.