Skip to main content

strop_containers/
lib.rs

1//! strop-containers: attach to an *existing* container on the local Docker
2//! engine and browse/read its filesystem (0037 DC1a — browse/read).
3//!
4//! # Capability boundary (read-only by construction)
5//!
6//! This crate exposes exactly four engine conversations: probe (`docker
7//! info`), discovery (`docker ps` + `docker inspect`), and filesystem reads
8//! (`docker cp … -` tar streams). There is deliberately **no** write, delete,
9//! exec-of-arbitrary-argv, LSP or Git surface: those are DC1b policy
10//! decisions, not accidental omissions. Unsupported operations are refused
11//! with typed errors ([`ContainerError::CapabilityRefused`]), never silently
12//! approximated.
13//!
14//! # Ownership and identity
15//!
16//! - Attaching never transfers lifecycle ownership: nothing here creates,
17//!   stops, restarts or removes a container, and no local path is ever
18//!   touched — a container path is not aliased to an analogous host path.
19//! - The engine is the **local** Docker CLI only (argv arrays, never shell
20//!   strings). Remote engines are DC5; no SSH daemon inside the container
21//!   is required or used.
22//! - Identity is the canonical 64-hex inspect id plus the incarnation
23//!   (`State.StartedAt`), never a container name alone. A name that
24//!   re-resolves to a different id is a stale-identity refusal; a container
25//!   that restarts between inspect and read is detected by a cheap
26//!   `started_at` re-check before every read.
27//!
28//! # Process policy
29//!
30//! Every `docker` invocation runs through `strop_core::process`
31//! supervision: an [`OwnedProcess`](strop_core::process::OwnedProcess)
32//! process group, the caller's [`CancelToken`], a wall-clock deadline and
33//! bounded pipe retention. Directory listings stream the tar archive
34//! through an incremental parser that retains only direct-child metadata,
35//! so a subtree's bulk bounds the transfer, never the memory; a listing
36//! whose retained metadata overflows its bound is refused, and file reads
37//! truncate by explicit `max` semantics — nothing partial is ever
38//! presented as complete.
39
40mod engine;
41mod error;
42mod exec;
43mod identity;
44mod read;
45mod tar;
46
47pub use engine::{engine, inspect, list_running, revalidate, EngineRef};
48pub use error::ContainerError;
49pub use exec::{exec_capture, exec_command};
50pub use identity::{ContainerIdentity, ContainerRef};
51pub use read::{list_dir, read_file, DirEntry, DirEntryKind};