Skip to content

Enforce sandbox prerequisites before launching Podman tools - #25

Merged
jasonsmithio merged 1 commit into
mainfrom
feat/sandbox-prereqs-enforcement
May 15, 2026
Merged

Enforce sandbox prerequisites before launching Podman tools#25
jasonsmithio merged 1 commit into
mainfrom
feat/sandbox-prereqs-enforcement

Conversation

@jasonsmithio

Copy link
Copy Markdown
Collaborator

Summary

Closes the loop on the sandbox-prereqs feature. PR #23 added detection, PR #24 added the status-bar indicator and install modal — those were visibility only. This PR is the enforcement half that decides what happens when Podman / gVisor are missing at tool-launch time.

  • Two new crates. paddleboard_sandbox_prereqs_state extracts the SandboxPrereqs GPUI global out of the UI crate so non-UI callers (agent, project) can read cached probe status without a workspace cycle. paddleboard_sandbox_settings owns the policy: OnMissingRuntime (Block / FallBackToHost / WarnOnce), SandboxSettings, a pure decide_gate(prereqs, settings) -> SandboxGateDecision, and a claim_warn_once_slot() AtomicBool so warn_once is genuinely once-per-session. 7 unit tests cover the decision matrix.
  • Three gated call sites. sandbox_tool.rs, sandbox_service_tool.rs (host fallback registers a Forwarded Ports entry with host_port == container_port), and the Sandboxed arm in project/src/context_server_store.rs. The upstream-shaped sandboxed_stdio_transport.rs is intentionally untouched — gating at the caller keeps the fork-divergence surface minimal.
  • New setting paddleboard_sandbox.on_missing_runtime defaulting to block, plus paddleboard_sandbox.prereq_check_enabled to disable the probe entirely. Schema lives in crates/settings_content/src/paddleboard_sandbox.rs (net-new file); the three required additions to settings_content.rs and the vscode_import.rs initializer are tagged // PaddleBoard: per fork hygiene.
  • Docs updated in lockstep: WELCOME.md Sandbox section describes the policy and shield UX, README.md's "Secure agent sandbox" bullet picks up the same note, and crates/workspace/src/tour.md section 2 mirrors it.

Test plan

  • cargo build -p paddleboard clean
  • cargo clippy --no-deps -p paddleboard_sandbox_settings -p paddleboard_sandbox_prereqs -p paddleboard_sandbox_prereqs_state -p paddleboard_sandbox_prereqs_ui -p settings_content -p settings -p agent -p project --tests clean (pre-existing llm_picker clippy failure on main is unrelated)
  • Unit tests pass: 7 in paddleboard_sandbox_settings, 3 in sandbox_tool, 7 in sandbox_service_tool, 6 in sandboxed_stdio_transport
  • Manual smoke: with Podman stopped, run a sandboxed tool call and verify the agent gets a clear "sandbox prerequisites missing" error and the install modal is one click away
  • Manual smoke: flip paddleboard_sandbox.on_missing_runtime to fall_back_to_host and verify sandbox_tool runs on the host shell, sandbox_service_tool registers a Forwarded Ports row, and a sandboxed_stdio MCP server falls through to plain stdio
  • Manual smoke: flip to warn_once and verify the log warning fires exactly once per session

Notes

  • Existing users won't pick up the in-app tour changes until the materialization gate at workspace.rs:785 / paddleboard/src/main.rs:1494 is loosened. Out of scope here.
  • The duplicate "Sandboxed MCP Servers" block at the bottom of tour.md is a pre-existing bug, left alone to keep this PR scoped.

Release Notes:

  • Added paddleboard_sandbox.on_missing_runtime policy that decides whether sandboxed tools block, fall back to the host, or warn once when Podman / gVisor prerequisites are missing.

🤖 Generated with Claude Code

Closes the loop on the sandbox-prereqs feature: PR-A added detection,
PR-B added the status indicator and install modal, and this is the
enforcement half that decides what happens when prereqs are missing at
tool-launch time.

Two new crates:

- paddleboard_sandbox_prereqs_state extracts the `SandboxPrereqs` GPUI
  global out of the UI crate so non-UI callers (`agent`, `project`) can
  read the cached probe status without a `workspace` cycle.
- paddleboard_sandbox_settings owns the policy model: `OnMissingRuntime`
  (Block / FallBackToHost / WarnOnce), `SandboxSettings`, a pure
  `decide_gate(prereqs, settings) -> SandboxGateDecision`, and a
  `claim_warn_once_slot()` AtomicBool so `warn_once` is genuinely
  once-per-session.

Three call sites consult the gate before spawning podman:
sandbox_tool.rs, sandbox_service_tool.rs (host fallback registers a
Forwarded Ports entry with host_port == container_port), and the
`Sandboxed` arm in project/context_server_store.rs (keeping the
upstream-shaped sandboxed_stdio_transport.rs untouched, per fork
hygiene).

The new `paddleboard_sandbox.on_missing_runtime` setting drives the
policy, with `block` as the default so the sandbox guarantee stays
honest. WELCOME.md, README.md, and the in-app tour are updated to
match.

Release Notes:

- Added `paddleboard_sandbox.on_missing_runtime` policy that decides whether sandboxed tools block, fall back to the host, or warn once when Podman / gVisor prerequisites are missing.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jasonsmithio
jasonsmithio merged commit 1b60414 into main May 15, 2026
@jasonsmithio
jasonsmithio deleted the feat/sandbox-prereqs-enforcement branch May 16, 2026 23:26
jasonsmithio added a commit that referenced this pull request May 31, 2026
…ment

Enforce sandbox prerequisites before launching Podman tools
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.

1 participant