docs/craft/infra/sidecar-reimplementation.md
The sandbox pod uses one app container plus one native restartable init sidecar from the same image:
sandbox: untrusted agent/code execution.sidecar: signed control-plane filesystem API for bundle pushes and
snapshot tar/untar operations. It is rendered in initContainers with
restartPolicy: Always.The sidecar is not a durable-storage client. It does not receive S3 bucket names, AWS credentials, or workload identity. Snapshot bytes are streamed between the API server and sidecar over the signed sidecar HTTP API; the API server persists and restores those bytes through the normal Onyx FileStore.
Pod: sandbox-{id}
ServiceAccount: sandbox
shareProcessNamespace: false
initContainers:
sandbox-init
- firewall/proxy bootstrap
- must complete before user code
sidecar
- restartPolicy: Always
- daemon on :8731
- POST /push for bundle materialization
- POST /snapshot/create for gzip snapshot stream
- POST /snapshot/restore/{session_id} for gzip restore stream
- read/write /workspace/managed
- read/write /workspace/sessions
- no snapshot storage credentials
containers:
sandbox
- opencode agent
- Next.js dev server
- read-only /workspace/managed
- read/write /workspace/sessions
- no snapshot storage credentials
Create:
{"session_id": ...} to
/snapshot/create.outputs/ and attachments/, and
streams application/gzip back. Empty workspaces return 204. Opencode
history is sandbox-global and uses separate opencode-history endpoints.SnapshotManager.persist_snapshot_from_stream.SnapshotManager stores the archive in get_default_file_store() with
FileOrigin.SANDBOX_SNAPSHOT.Restore:
SnapshotManager.restore_snapshot_to_stream./snapshot/restore/{session_id} with X-Bundle-Sha256./workspace/sessions/{session_id}, and
reinstalls dependencies when needed.ServiceAccount/sandbox without storage annotations.craft.extraBoundServiceAccounts.>= 1.33 is required for native restartable init sidecar
containers.