Skip to main content

agent_bridle_tool_shell/
lib.rs

1//! `agent-bridle-tool-shell` — capability-confined shell tool (argv + safe-subset engine).
2//!
3//! Per **ADR 0005** the object-capability *boundary* is L3 (kernel) and this
4//! crate is the L2 *convenience* engine: `agent-bridle` is the **exec funnel**,
5//! parsing each request itself ([`crate::parse`]) and running only what it can
6//! confine. [`ShellTool`] accepts either argv form (`program` + `args`) or a
7//! free-form `cmd` string, checks the `exec`/`fs` leash, spawns the program
8//! directly, and **refuses the dynamic constructs by design** (`$(...)`,
9//! backticks, subshells — the undecidable interiors of ADR 0001). The L3
10//! backstop is wired (agent-bridle#35): when it will actually confine the run —
11//! today the Landlock `fs_write` axis on a capable Linux build with `fs_write`
12//! restricted — children spawn inside a kernel-enforced ruleset and
13//! `sandbox_kind` reports [`agent_bridle_core::SandboxKind::Landlock`]; else the
14//! run is honestly *advisory* with [`agent_bridle_core::SandboxKind::None`]
15//! (I9, never overclaiming). Read/exec/net axes + macOS/Windows backends are
16//! follow-ups (ADR 0006).
17//!
18//! The engine (agent-bridle#34 Track A + #45): a sequence of pipelines joined by
19//! `&&`/`||`/`;` (short-circuit semantics), each pipeline simple commands with
20//! quoted arguments, **redirections** (`> out`, `>> out`, `< in`, `2> err`,
21//! `2>&1`), **filename globbing** (`*`/`?`/`[…]`) and **allowlisted `$VAR`
22//! expansion** — every filesystem/env touch bridle performs (redirect opens,
23//! glob directory listings, variable allowlist) is leash-/policy-checked before
24//! any spawn. The dynamic constructs (`$(…)`, backticks, subshells) stay refused
25//! by design. The process spawning is behind a `Spawner` seam (mocked in unit
26//! tests; real path in `tests/real_spawn.rs`). `brush-bridle-core` remains the
27//! deferred, reversible
28//! full-bash alternative engine behind the same registry seam (ADR 0005 D4 —
29//! tracked on agent-bridle#20).
30
31#![forbid(unsafe_code)]
32#![warn(missing_docs)]
33
34#[cfg(feature = "brush")]
35mod brush_shell;
36#[cfg(feature = "brush")]
37mod caveat_interceptor;
38#[cfg(feature = "carried-coreutils")]
39mod coreutils_dispatch;
40#[cfg(feature = "host-shell")]
41mod host_shell;
42#[cfg(feature = "shell")]
43mod net_proxy;
44#[cfg(feature = "shell")]
45mod parse;
46#[cfg(feature = "shell")]
47mod shell_tool;
48
49#[cfg(feature = "shell")]
50pub use shell_tool::ShellTool;
51
52/// The sandboxed-host engine (ADR 0019 / #194): full-shell semantics with the
53/// guarantee entirely on L3. Opt-in via the `host-shell` feature; a
54/// construction-time alternative to [`ShellTool`] behind the ADR 0005 D2 seam.
55#[cfg(feature = "host-shell")]
56pub use host_shell::HostShellTool;
57
58/// The carried **brush** engine (agent-bridle#20 / Track 2): a bash-in-Rust
59/// shell run in-process, confined by the `CommandInterceptor` L2 leash — the
60/// only engine that also confines a *restricted* `exec`/`net` grant, on any
61/// platform. Opt-in via the `brush` feature; a construction-time alternative to
62/// [`ShellTool`] behind the ADR 0005 D2 seam, using the temporary `brush-ocap-*`
63/// fork (reubeno/brush#1184).
64#[cfg(feature = "brush")]
65pub use brush_shell::BrushShellTool;
66
67/// Carried-coreutils dispatch (agent-bridle#20 / issue #206). An embedder's
68/// binary calls [`maybe_dispatch`] at the top of `main` to become
69/// dispatch-capable, so the brush engine's carried `ls`/`cat`/… shims (which
70/// re-exec `<self> --invoke-bundled <name>`) resolve in-process against the host
71/// binary — carried coreutils with no host tools. [`register_shims`] /
72/// [`install_default_providers`] are used by the engine internally.
73#[cfg(feature = "carried-coreutils")]
74pub use coreutils_dispatch::{install_default_providers, maybe_dispatch, register_shims};
75
76/// Network egress audit surface (#124, ADR 0016): the loopback proxy records
77/// every proxy-visible connection as a [`NetAuditEvent`] through an [`AuditSink`]
78/// (default off; enable via the `BRIDLE_NET_AUDIT` setting). The `bridle-netmon`
79/// binary renders the JSON-lines stream as a live monitor.
80#[cfg(feature = "shell")]
81pub use net_proxy::{AuditSink, JsonlSink, NetAuditEvent, NetDecision, NetKind, NullSink};