This page describes the combined gate for lane D. The gate is the set of real-Docker tests that must pass before lanes F and G may run agents in production. It also states what those lanes must do when they call the isolation boundary.
The gate needs a running Docker daemon. Run the suites one file at a time, because they share one image tag and one daemon:
npx vitest run --no-file-parallelism test/agent-contract.test.ts test/agent-clone.test.ts test/agent-container.test.ts test/agent-network.test.ts test/agent-policy.test.ts test/agent-proxy.test.ts test/agent-adapter.test.ts test/agent-supervisor.test.ts test/agent-output.test.ts test/agent-gate.test.tsThe Agent isolation workflow runs the same command. The main CI workflow skips
the Docker suites so that they never run in parallel.
The live vendor probes need real credentials, so CI does not run them. To run them,
set CODEBOOST_RUN_AUTH_PROBES=1, CODEBOOST_CODEX_AUTH_FILE (a Codex auth.json
path) and CLAUDE_CODE_OAUTH_TOKEN. Do not put credentials in an issue, a pull
request or chat.
Each row is a T9 requirement for the Docker suite. The suite fails if any row fails.
| Requirement | Tests |
|---|---|
| Isolation holds: non-root, no capabilities, read-only root, no host paths or secrets, vendor-only egress | agent-container: read-only isolation, lockdown and mount validation; agent-network: egress and DNS |
A read-only phase cannot write /work |
agent-container: phase worktree for all five phases |
| Planning and questions cannot run a process | agent-policy: tool sets exclude the command tool, and command dispatch refuses these phases |
| Task and scratch byte and inode limits hold | agent-container: task capacity; scratch capacity for Codex and Claude (/tmp, HOME, CODEX_HOME, output directory) |
Hard links and alias writes from .git/config and objects fail, and metadata stays unchanged |
agent-container: metadata alias probe in planning, review and execute, with a digest of .git before and after |
| Mountpoint replacement fails | agent-container: metadata and metadata alias probes (mv and rm -rf of .git) |
| Both vendor startup probes read the schema and return bounded valid output through their documented channel | agent-supervisor live probes: Codex through its output file, Claude through its stdout envelope (credentials required) |
| Hostile input stays inside the boundary | agent-container: repositories with links that leave the checkout are refused, links inside the checkout still work, oversized repositories fail closed; agent-policy: option-like prompts; agent-proxy: hostile CONNECT traffic; agent-supervisor: hostile output |
A test that cannot fail proves nothing. agent-gate runs each negative probe from
production in a container that is missing one protection. It then checks that the
probe reports that exact breach. The cases include writable Git metadata, a writable
worktree in each read-only phase, task and scratch areas without a byte or an inode
limit, the Codex-only scratch areas, a writable control directory, and repository
links or secret content in the worktree.
A probe also discards the output of any forbidden command it tries. So a breach that succeeds, such as reading a file through a link, cannot copy data into the output.
Probe scripts must use the deny helper for actions that must fail. Do not write
! command in a probe: set -e ignores a negated command, so the probe would
continue and report success even when the forbidden action worked. Before D5, the
metadata, read-only isolation and capacity probes had this defect.
Use only these entry points to run an agent:
createTaskClonecreates a committed, standalone staging clone.prepareTaskFilesystemscopies that clone into bounded task storage. CallremoveTaskFilesystemswhen the task ends. It refuses a repository that has a symbolic link with an absolute target or a target outside the checkout, before it creates any storage. Report this to the user as a repository the agent cannot run on; do not retry it.captureInvocationfreezes the request. Capture each attempt ID once. A new attempt needs a new attempt ID.startCodexInvocationorstartClaudeInvocationruns the agent and returns a handle. Pass the vendor credential only as the function argument.
The boundary guarantees the following:
- The profile is immutable, and every launch revalidates it against Docker.
- Tools are limited by phase. Planning and questions can only read, list and search.
- Web search and MCP are off, stdin is closed, and network traffic reaches only the vendor hosts.
- Output is bounded and decoded as strict UTF-8. Invalid output fails as
capture-failure. - The invocation deadline bounds every launch. Cleanup still runs after the deadline.
The caller must do the following:
- Keep ownership until
settledresolves. It resolves only after the container has stopped and its cleanup has finished. The supervisor retries cleanup until then. - Call
cancelto stop an invocation. The first stop reason is kept. - Treat
stopReasonas the result of the invocation. A missingstopReasonmeans the agent finished normally.
- CI does not run the live vendor probes. Run them locally with credentials before a release that changes the image, the adapters or the prompts.
- T9 as a whole is complete only when lane F runs every suite in required CI (F6).