Skip to content

feat(worker): container execution backend with resource limits and hosted gate (#5)#59

Merged
BunsDev merged 1 commit into
mainfrom
feat/issue-5-worker-isolation
Jul 7, 2026
Merged

feat(worker): container execution backend with resource limits and hosted gate (#5)#59
BunsDev merged 1 commit into
mainfrom
feat/issue-5-worker-isolation

Conversation

@BunsDev

@BunsDev BunsDev commented Jul 7, 2026

Copy link
Copy Markdown
Member

Closes #5 — the largest infra item in the wave; unblocks #12.

What lands

crates/worker/src/backend.rs — a backend seam behind the session launch:

  • Host backend: today's direct execution, unchanged (dev / trusted self-hosting)
  • Container backend (worker.backend = "container"): one fresh, uniquely-named container per task attempt through any docker-compatible CLI (docker / podman / nerdctl)

The isolation profile (pinned by a pure-argv test):
--read-only rootfs · --cap-drop ALL · no-new-privileges · bounded /tmp tmpfs · only the task workspace bind-mounted · --cpus / --memory / --pids-limit / --network limits

Security details:

  • Git authority forwarded by env-var name (-e COVEN_GIT_TOKEN) — the token never enters argv, docker inspect, or shell history (asserted end-to-end)
  • Timeout kills the CLI and the container by name; --rm + explicit kill guarantee teardown
  • Exit 137 surfaces as a probable memory-limit kill in the failure detail (resource limits visible in failure states)
  • The session brief references /workspace — the sandbox's view — never host paths

Hosted gate: [[installations]] configured + backend = "host" → doctor error unless allow_host_backend = true is set deliberately. Container mode validates the CLI binary and image.

Acceptance criteria → proof

Criterion Test
Hosted mode refuses host backend by default hosted_posture_refuses_the_host_backend_without_explicit_opt_in
Fresh isolated workspace/container per attempt unique-name test + --rm in pinned argv
Resource limits enforced & visible argv pin + exit-137 explanation + timeout kill-by-name e2e
Cleanup tested success + failure success asserted in the publication harness; workspace_is_destroyed_when_the_session_fails
Logs filtered for secrets unchanged redact pipeline covers all copied-out surfaces; token-not-in-argv asserted
Docs: backends + operator config docs/container-isolation.md operator section, example.toml, README row

Verification

219 tests green · clippy -D warnings clean · python gates green · demo 21/21 (host backend default — proves back-compat)

…sted gate (#5)

Closes #5.

New crates/worker/src/backend.rs: a WorkerBackend seam behind the session
launch. The host backend keeps today's direct execution for development and
trusted self-hosting; worker.backend = "container" runs each task attempt
in a fresh, uniquely named container via any docker-compatible CLI:

- hardened profile: --read-only rootfs, --cap-drop ALL, no-new-privileges,
  bounded /tmp tmpfs, only the task workspace bind-mounted
- resource limits: --cpus / --memory / --pids-limit / --network, all
  operator-configurable under [worker.container]
- git authority forwarded by env var NAME (-e COVEN_GIT_TOKEN): the token
  never enters argv, docker inspect, or shell history
- wall-clock enforcement kills the CLI and then the container by name;
  --rm plus explicit kill guarantee teardown; exit 137 is surfaced as a
  probable memory-limit kill in the failure detail
- the session brief references the workspace as the sandbox sees it
  (/workspace), not the host path

Hosted gate: once [[installations]] exist (hosted posture), doctor refuses
worker.backend = "host" unless allow_host_backend = true is set
deliberately. Container mode validates the runtime CLI and image.

Workspace teardown is now tested on both paths (success in the publication
gate harness, failure via an exit-2 session), and a fake docker CLI proves
the isolation argv, env-only token, result copy-out from the bind mount,
and kill-by-name on timeout.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Copilot AI review requested due to automatic review settings July 7, 2026 06:52
@BunsDev
BunsDev merged commit fd2ea35 into main Jul 7, 2026
2 checks passed
@BunsDev
BunsDev deleted the feat/issue-5-worker-isolation branch July 7, 2026 06:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a worker execution backend abstraction to support running each coven-code --headless attempt inside a hardened, resource-limited container for hosted deployments, while preserving the existing host-execution path for development/self-hosting and gating host execution in “hosted posture” via config diagnostics.

Changes:

  • Introduces a Backend abstraction with Host and Container backends, plus a pinned container isolation argv profile and timeout teardown behavior.
  • Extends worker configuration (worker.backend, worker.container.*, worker.allow_host_backend) and updates doctor checks to refuse host execution by default when [[installations]] are configured.
  • Updates documentation and examples to describe the new backends and operator configuration; adds tests asserting isolation argv, token forwarding channel, timeout kill-by-name, and workspace cleanup.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Adds a capability row documenting container isolation support and hosted posture behavior.
docs/container-isolation.md Documents operator-facing config for selecting the container backend and its isolation properties.
crates/worker/src/lib.rs Routes session launches through the new backend seam; adds container backend and cleanup assertions in tests.
crates/worker/src/backend.rs Implements host/container execution backends, docker argv construction, and timeout teardown mechanics.
crates/webhook/src/routes.rs Updates test configs to include new worker backend fields.
crates/config/src/lib.rs Adds new worker backend/container config types and doctor validation for hosted posture gating.
config/example.toml Documents the new worker backend/container settings in the sample config.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +9 to +11
//! Git authority is injected by environment variable *name* (`-e NAME`
//! inherits the value from the docker CLI's own environment), so the token
//! never appears in any argv, container inspect output, or shell history.
Comment on lines +202 to +211
if let Some(kill) = kill {
match Command::new(&kill.docker_bin)
.args(["kill", &kill.name])
.output()
.await
{
Ok(_) => {}
Err(e) => warn!(container = %kill.name, "docker kill failed: {e}"),
}
}
Comment on lines +87 to +90
bounded `/tmp` tmpfs, and only the task workspace bind-mounted. Git
authority is forwarded by environment variable *name* (`-e COVEN_GIT_TOKEN`)
so the token never appears in argv or `docker inspect`. On timeout the
adapter kills both the CLI process and the container by name; `--rm` tears
BunsDev added a commit that referenced this pull request Jul 7, 2026
* feat(github): branch listing, compare, head-PR lookup, ref deletion, labels (#14)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

* feat(gardener): branch classifier, policy planner, and schedule parsing (#14)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

* feat(config): per-repo gardener policy with validation (#14)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

* feat(webhook): garden command and GardenRun task kind (#14)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

* feat(worker): execute gardener plans — scan, prune with SHA guard, surface draft PRs (#14)

Replace the GardenRun stub with a real execution path: scan branches
against the resolved per-repo policy, classify and plan, prune dead and
merged branches (re-checking the SHA before every delete), surface
PR-less human branches as labeled draft PRs, and post the run report on
the report issue. Bot-only PR-less branches are skipped, and the whole
runner stays behind the write-permission command gate.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

* chore(tests): carry WorkerConfig and Config struct drift across the rebase

Main added backend/container/allow_host_backend to WorkerConfig (#59)
while this branch added the gardener section to Config; fill both sides
in the test literals that construct the structs directly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

* feat: schedule Branch Gardener runs (#14)

Wire configured gardener schedules into the server, support /coven garden, and update shipped docs/status.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Val Alexander <bunsthedev@gmail.com>

---------

Signed-off-by: Val Alexander <bunsthedev@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add hosted worker container isolation and resource limits

2 participants