Sandbox worker + supervisor runbook
Production hostile-code sandbox capability execution is disabled until the cutover gate is GO. Current default is NO_GO because ADR-022 cosign and eligible-host smoke artifacts are not recorded.
Native/systemd deploymentโ
- Provision a dedicated Linux host. Do not colocate general app workloads.
- Install pinned
bubblewrapat/usr/bin/bwrap; record the package version and hash in the cutover evidence. - Create the service identity:
- user/group:
humanwork-sandbox - runtime socket dir:
/run/humanwork-sandbox - workspace root:
/var/lib/humanwork-sandbox
- user/group:
- Enable project quotas for
/var/lib/humanwork-sandbox(prjquotafor ext4 or XFS project quota). Missing quota support isNO_GO. - Enable cgroup v2 delegation for the supervisor service.
humanwork-sandbox-supervisor.serviceusesDelegate=yesand setsHUMANWORK_SANDBOX_CGROUP_ROOT=/sys/fs/cgroup/system.slice/humanwork-sandbox-supervisor.service; that delegated subtree must allow pids/memory/cpu/io writes andcgroup.kill. - Install:
/opt/humanwork/sandbox-supervisor/bin/humanwork-sandbox-supervisor/opt/humanwork/sandbox-supervisor/bin/capability-shell/opt/humanwork/sandbox-supervisor/bin/sandbox-init/opt/humanwork/sandbox-supervisor/bin/browser-action-adapter/opt/humanwork/sandbox-supervisor/bin/true(bound as/sandbox/bin/truefor smoke and canonical exec allowlist checks)- Chromium runtime at
/usr/lib/chromium/chromium(bound read-only as/sandbox/bin/chromium; the supervisor also binds Chromium's read-only/usr/lib*runtime directories whenbrowser_actionis dispatched) /opt/humanwork/sandbox-supervisor/policy/*/opt/humanwork/sandbox-worker/worker.py,supervisor_client.py,supervisor_protocol.py
- Install
deploy/systemd/humanwork-sandbox-supervisor.serviceanddeploy/systemd/humanwork-sandbox-worker.service. The supervisor unit must keepSANDBOX_INIT_BIN=/opt/humanwork/sandbox-supervisor/bin/sandbox-init,HUMANWORK_BROWSER_RUNTIME_BIN=/usr/lib/chromium/chromium,HUMANWORK_BROWSER_ADAPTER_BIN=/opt/humanwork/sandbox-supervisor/bin/browser-action-adapter,HUMANWORK_SANDBOX_EXECUTABLE_DIR=/opt/humanwork/sandbox-supervisor/bin, and the delegatedHUMANWORK_SANDBOX_CGROUP_ROOTabove. - Put only
SANDBOX_WORKER_TOKENand non-secret primitive config in/etc/humanwork/sandbox-worker.env. Do not pass caller env into sandbox dispatch. - Start services:
systemctl enable --now humanwork-sandbox-supervisor.servicesystemctl enable --now humanwork-sandbox-worker.service
- Run smoke from the host or a controlled ops box:
SANDBOX_WORKER_URL=http://127.0.0.1:8080 SANDBOX_WORKER_TOKEN=... bun api/scripts/smoke-sandbox-supervisor.ts
Supervisor socket permissions must remain owner-only (0600) under /run/humanwork-sandbox/supervisor.sock; the worker runs as the same service identity.
Dedicated K8s node deploymentโ
Use infra/k8s/sandbox-worker.yaml only on a labelled dedicated node that satisfies infra/k8s/sandbox-worker-node-requirements.md.
- The default ConfigMap keeps project quota/proxy facts false, so readiness is
NO_GOuntil host smoke proves the node. - Pin the worker image by digest for production; do not deploy
latestas the final cutover artifact. - The manifest must not mount the Docker socket, host home,
.ssh, host credentials, broad/etc, broad/run, or host root. /var/lib/humanwork-sandboxis the only host workspace bind and must have hard project quota enforcement./sys/fs/cgroupaccess is allowed only for the delegated cgroup v2 subtree on the dedicated node.- Enable CAP_NET_ADMIN only for proxy-only mode after smoke proves veth/nftables/proxy behavior.
GO / NO_GO checksโ
GET /health from the worker must report:
status="GO"andproductionReady=true.checks.adrCosign.status="GO".checks.hostPrimitives.status="GO"with bwrap/runtime/seccomp hashes.checks.productionCutoverGate.status="GO".- no
noGoReasons.
api/scripts/smoke-sandbox-supervisor.ts must then pass:
- worker health and primitive readiness with bwrap, namespace, cgroup, seccomp, quota, Landlock, proxy, process/cancel, Chromium, and adapter evidence;
- artifact write/read;
exec_argvwith a canonical/sandbox/...executable;browser_actionthroughproxy-only, returning adapter-produced action evidence rather than a denied/error success substitute;- full supervisor evidence schema validation;
- hostile-deny subset and the full eligible-host hostile battery artifact;
- release/cutover evidence hash binding.
On GitHub-hosted or otherwise ineligible hosts, smoke may be run with ALLOW_NO_GO=1 to publish a NO_GO/skipped artifact. That artifact is not production readiness.
Proxy-only specificsโ
network=proxy-only requires supervised netns/veth, host proxy config, nftables allow-only-proxy rules, and CAP_NET_ADMIN. If any primitive is absent, dispatch must return proxy_only_unavailable. It must not downgrade to host networking or report network=off as proxy-only success.
Landlock evidenceโ
Every supervisor result includes landlock. If the kernel ABI is available, sandbox-init must apply Landlock and report enabled=true, rulesetApplied=true. If unavailable, evidence must say available=false, reason="kernel_unsupported"; this is allowed only because bwrap mount policy, cgroups, quotas, and seccomp remain load-bearing.
Rollbackโ
Rollback routes traffic away from sandbox capability execution or deploys a previous supervisor/worker build that still satisfies the same evidence contract.
Rollback must never route to backend=none, sandbox=off, direct spawn, raw bwrap success, degraded success, or worker success without linux-bwrap-supervisor evidence. If no eligible worker exists, disable the sandbox capability path and fail closed rather than running unsandboxed code.