Skip to content

Decide sandbox granularity: Forge wrapper is one fence per daemon, but scout-cannot-write needs a per-session fence #277

Description

@saucam

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:

  1. 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.
  2. 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

  • Which granularity does Forge actually provide today (per user? per workspace? per session)?
  • If per-session is wanted, does codeoid dispatch into Forge sandboxes, and what does that do to the dispatch queue's claim/lease model in dispatch.ts?
  • Does a scout get a genuinely read-only mount, or does shape stay a scope claim + prompt contract?
  • What is the posture statement for unattended routines specifically?
  • Whatever we land, keep it a wrapper — reject any if (sandboxed) branch inside an enforcement site, same review rule as local mode

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions