Files
clawmates/crates/cm-sandbox/src/lib.rs
T
Omar SobhandClaude Opus 4.8 ce7a5d9aed
ci / gates (push) Successful in 7s
ci / rust (push) Failing after 20s
ci / frontend (push) Successful in 24s
ci / e2e (push) Has been skipped
Remove orphaned k8s artifacts (Docker-only now)
CI no longer references k8s; delete the dead k8s surface:
- deploy/helm/ (the chart), ci/check-helm.sh, scripts/netpol-cluster.sh
- cm-sandbox: the feature-gated K8sDriver (src/k8s.rs) + k8s_security test +
  the `k8s`/`k8s-tests` features + the optional kube/k8s-openapi/rustls deps
  (Cargo.lock drops the kube-rs tree). Nothing outside cm-sandbox referenced it.

Docker (bollard) DockerDriver is the sole sandbox driver. cm-sandbox + cm-runtime
compile, fmt + clippy clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-06-26 18:55:17 -07:00

65 lines
2.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! Per-agent sandbox orchestration (spec §15): containers with no root, no
//! capabilities, a seccomp deny profile, read-only rootfs, and no network.
//! One `SandboxDriver` trait; the Docker implementation serves dev and the
//! air-gapped compose target.
mod docker;
mod spec;
pub use docker::DockerDriver;
pub use spec::{
DriveMount, ExecResult, ManagedSandbox, PtySession, SandboxHandle, SandboxKind, SandboxSpec,
};
/// Label every Clawmates sandbox carries, so orphans can be found + reaped
/// after a crash/restart. Value is the kind: `agent` (no egress) or `browser`.
pub const SANDBOX_LABEL: &str = "clawmates.sandbox";
/// The label value for a sandbox of the given kind.
pub fn sandbox_kind(egress: bool) -> &'static str {
if egress {
"browser"
} else {
"agent"
}
}
#[derive(Debug, thiserror::Error)]
pub enum SandboxError {
#[error("container engine error: {0}")]
Engine(String),
#[error("sandbox not found")]
NotFound,
}
#[async_trait::async_trait]
pub trait SandboxDriver: Send + Sync {
/// Creates and starts a hardened sandbox container.
async fn provision(&self, spec: &SandboxSpec) -> Result<SandboxHandle, SandboxError>;
/// Runs a command inside the sandbox (orchestrator-initiated only; the
/// sandbox can initiate nothing outbound).
async fn exec(&self, handle: &SandboxHandle, cmd: &[&str]) -> Result<ExecResult, SandboxError>;
/// Starts an interactive PTY (`exec -it`) inside the sandbox: a TTY-backed
/// `cmd` (e.g. `["zsh","-l"]`) whose combined output streams back and whose
/// stdin accepts keystrokes. `env` adds `KEY=VALUE` vars to the session (e.g.
/// a MOTD greeting). Used by the Terminal app, not agent tools.
async fn attach_pty(
&self,
handle: &SandboxHandle,
cmd: &[&str],
cols: u16,
rows: u16,
env: &[String],
) -> Result<crate::PtySession, SandboxError>;
/// Resizes a running PTY exec's window (cols × rows).
async fn resize_pty(&self, exec_id: &str, cols: u16, rows: u16) -> Result<(), SandboxError>;
/// Stops and removes the sandbox.
async fn destroy(&self, handle: &SandboxHandle) -> Result<(), SandboxError>;
/// Whether the sandbox container is currently running.
async fn health(&self, handle: &SandboxHandle) -> Result<bool, SandboxError>;
/// List sandboxes the engine currently holds for this kind
/// (`agent`/`browser`), so the manager can reap orphans whose owning
/// process died. Filtered by the [`SANDBOX_LABEL`] label.
async fn list_managed(&self, kind: &str) -> Result<Vec<ManagedSandbox>, SandboxError>;
}