sand-boxer/workplans/SAND-WP-0014-owner-mediated-execution.md
tegwick d69827aaa2 feat: pin bwrap rein runtimes and isolate private state
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0726e-5232-73f2-aaca-2c05ceb62efb
2026-09-05 20:36:11 +02:00

5.6 KiB

id type title domain repo status owner topic_slug created updated state_hub_workstream_id
SAND-WP-0014 workplan Owner-mediated governed bwrap execution infotech sand-boxer active codex owner-mediated-execution 2026-09-04 2026-09-05 b616d1cd-208f-5ecf-a4a0-a028396422c4

Owner-mediated governed bwrap execution

Promote intake GLAS-IN-0002 into sand-boxer ownership. Replace the unusable consumer-side nsenter hint with an owner-executed command boundary that remains bound to the sandbox and its governed consumer identity. A refused execution must never fall back to a host checkout or another extension.

Define the governed execution contract

id: SAND-WP-0014-T01
status: done
priority: high
state_hub_task_id: "1b4349de-7027-5f01-8deb-122772e1404d"

Define request/result schemas and evidence for exact actor/project/session/run binding, ready/active lifecycle, workspace confinement, declared network posture, value-free credential route references, bounded command duration, and bounded output.

Implement owner-mediated bwrap execution

id: SAND-WP-0014-T02
status: done
priority: high
state_hub_task_id: "59f9af7c-7cd7-5e86-849f-5dfc7a3a06ee"

Add manager, extension, CLI, and authenticated HTTP surfaces. Only ext.bwrap may execute in this slice. The extension launches an owner broker inside bwrap, uses the sandbox workspace as its working directory, starts commands with a sanitized environment, and fails closed if the recorded workspace is not the exact owner-managed sandbox directory.

Remove direct namespace-entry guidance

id: SAND-WP-0014-T03
status: done
priority: high
state_hub_task_id: "4fc7d747-13d5-58e7-b89e-b72e845515aa"

Stop publishing raw consumer-side nsenter commands. Reachability describes owner-mediated execution without exposing a misleading direct-attach route.

Verify unit and local namespace behavior

id: SAND-WP-0014-T04
status: done
priority: high
state_hub_task_id: "c7ada937-4430-59d7-b3a6-9f3f36e9a907"

Cover identity/state/TTL refusal, unsupported-extension refusal, exact workspace validation, sanitized environment, credential route references, timeout/output bounds, API authentication, lifecycle restoration, and teardown. Run the full repository check and, when host user namespaces permit it, a non-secret live bwrap command proof.

Implemented and verified 2026-09-04. make check passes with 119 tests. The first live attempt proved that even the bwrap owner cannot reliably setns from the host on this kernel (IPC: Operation not permitted), so execution was moved to a small read-only broker launched inside the namespace and reached via an owner-only Unix socket. make smoke-bwrap-exec then passed: actor agt, project/session/run binding reached the command; cwd was the copied sandbox; the host-source sentinel was absent; the command created an artifact; the net namespace exposed only lo under declared default: deny, egress: []; no credential routes or values were present; and teardown reported destroyed with the workspace removed.

The authenticated HTTP smoke subsequently exposed and fixed a lifecycle defect: --die-with-parent tied bwrap to the process handling create, so the namespace could disappear before a later API exec. Owner sandboxes now persist across requests and remain bounded by explicit destroy, TTL expiry, and stale reaping.

The consumer-contract audit also found that Glas needs to create a private task file without writing through the host mirror or putting prompt content in argv. Owner exec now supports bounded stdin_text (1,000,000 UTF-8 bytes), delivers it only to the child process, and excludes it from results and lifecycle evidence.

Prove one governed rein and coordinate consumers

id: SAND-WP-0014-T05
status: wait
priority: high
state_hub_task_id: "c6812fd4-bb7b-5be0-8344-a122496fe5bc"

With Glas and rein-aharness, run one real selected rein command through the owner API using an explicitly declared egress profile and catalog credential route. Prove that the source checkout is absent, retain value-free evidence, destroy the workspace, then update Glas readiness and Activity Core ACTIVITY-WP-0032-T05. Do not trigger the production pilot before readiness changes.

This task depends on a reviewed Glas profile revision and its matching credential/egress/runtime contract. Glas selected the Claude route first in GLAS-WP-0012; the earlier OpenRouter AppRole dependency applies only to the separate open-weight profile and does not establish Claude authentication.

2026-09-05: SAND-WP-0015 implements pinned Python runtime mounts and private namespace state, with a real rein CLI startup proof. Claude workload credential routing, enforced provider egress, pinning/deploying the Claude executable, and the real-model acceptance remain open in SAND-WP-0015-T04. No credential value belongs in this workplan or State Hub.

Acceptance criteria

  • Execution requires the recorded actor, project, session, and run identity.
  • Only a live, unexpired, ready sandbox can start a command; concurrent commands are refused.
  • Command execution is argument-vector based, starts inside the copied sandbox workspace, and has no host/source-checkout fallback.
  • ext.bwrap supplies its declared read-only runtime paths and enforces the profile's network namespace. Evidence reports default policy and egress list.
  • Credential inputs are non-secret catalog route references only.
  • Duration and captured output are bounded, lifecycle state is restored, and teardown remains idempotent.
  • Consumer-facing reachability no longer recommends direct nsenter.