Records the open topology decision from conductor-design.md §9 (landed in #275). Blocking for unattended routines (#54).
The two fences
Sandboxing is provided as a wrapper: highflame-forge provisions the sandbox and starts codeoid inside it. That split is right — it keeps the daemon free of if (sandboxed) branches, the same discipline local-mode.md enforces for the verified auth path. But it solves one threat model, not both:
| Fence |
Protects |
Provided by |
| Outer |
the host from the fleet — filesystem outside the workspace, egress, credential exposure |
Forge sandbox (wrapper) |
| Inner |
a session's declared posture, and fleet members from each other |
R6 scoping + worktree check (daemon) |
Everything in the inner row happens inside the outer fence. sed -i on a repo file works as well sandboxed as not, and the fence cannot distinguish "the conductor wrote this" from "the session that owns this worktree wrote this" — same uid, same namespace. Adding a sandbox does not satisfy R6.
The decision
codeoid inside a Forge sandbox → one fence shared by every session on that daemon. Tenant- or workspace-granular.
codeoid spawning Forge sandboxes and dispatching into them → per-session isolation, but a different topology and a different dispatch path.
Why it can't stay undecided
Two things in the shipped design are currently claims rather than fences:
shape: "scout". The dispatch brief tells a scout it investigates and reports, and WORKER_SCOPE_PROFILES.scout withholds tools:write — but WRITE_TOOLS excludes Bash, so a scout can still sed -i. Under a shared fence there is nothing behind the scope claim.
- Untrusted packs. They share the fence with everything else, so pack trust is entirely a scope/approval question today.
Both get materially safer under per-session isolation and stay as-is under a shared one. That is a real posture difference to make knowingly, and it matters most for unattended dispatch — a routine firing ship workers with nobody watching is a different risk than an owner approving each one.
Questions to answer
Related
Records the open topology decision from conductor-design.md §9 (landed in #275). Blocking for unattended routines (#54).
The two fences
Sandboxing is provided as a wrapper:
highflame-forgeprovisions the sandbox and starts codeoid inside it. That split is right — it keeps the daemon free ofif (sandboxed)branches, the same discipline local-mode.md enforces for the verified auth path. But it solves one threat model, not both:Everything in the inner row happens inside the outer fence.
sed -ion a repo file works as well sandboxed as not, and the fence cannot distinguish "the conductor wrote this" from "the session that owns this worktree wrote this" — same uid, same namespace. Adding a sandbox does not satisfy R6.The decision
codeoid inside a Forge sandbox → one fence shared by every session on that daemon. Tenant- or workspace-granular.
codeoid spawning Forge sandboxes and dispatching into them → per-session isolation, but a different topology and a different dispatch path.
Why it can't stay undecided
Two things in the shipped design are currently claims rather than fences:
shape: "scout". The dispatch brief tells a scout it investigates and reports, andWORKER_SCOPE_PROFILES.scoutwithholdstools:write— butWRITE_TOOLSexcludesBash, so a scout can stillsed -i. Under a shared fence there is nothing behind the scope claim.Both get materially safer under per-session isolation and stay as-is under a shared one. That is a real posture difference to make knowingly, and it matters most for unattended dispatch — a routine firing
shipworkers with nobody watching is a different risk than an owner approving each one.Questions to answer
dispatch.ts?shapestay a scope claim + prompt contract?if (sandboxed)branch inside an enforcement site, same review rule as local modeRelated