516 lines
36 KiB
Markdown
516 lines
36 KiB
Markdown
# Lazaret Specification
|
|
|
|
This document is the normative product specification for Lazaret.
|
|
|
|
### Document authority
|
|
|
|
| Document | Authoritative for |
|
|
| :--- | :--- |
|
|
| This specification | Product north star, trust model, stable vocabulary and identifiers, below-abstraction architecture, and product requirements |
|
|
| [TLA+ application protocol model](protocol/Lazaret.tla) and [TLC config](protocol/Lazaret.cfg) | Protocol lifecycle, communication semantics, publication, registration, escalation, recovery, and checked invariants |
|
|
| [Prepared-lower TLA+ model](protocol/PreparedLower.tla) and [TLC config](protocol/PreparedLower.cfg) | Prepared-artifact publication, generation leases, mounts, reclamation, stage recovery, and checked invariants |
|
|
| [Design schemas](schema.md) | Logical durable records, network-policy documents, readiness evidence, and their relationships |
|
|
|
|
This specification does **not** restate modeled actions or invariants. The TLA+
|
|
models are authoritative above their abstraction boundaries. This specification
|
|
owns physical refinements below those boundaries. A new above-abstraction rule
|
|
belongs in the applicable model before a product refinement relies on it.
|
|
|
|
## 1. Problem Statement
|
|
|
|
AI coding agents need broad local capabilities: they run arbitrary tools, modify a
|
|
project, use Git, install dependencies, and access selected network services. Code
|
|
produced or invoked by an agent is not trusted to run directly on the developer's
|
|
host. A conventional container reduces risk, but poor terminal behavior, transient
|
|
tool state, restricted Git access, and manual setup can make the safe path too
|
|
inconvenient for routine work.
|
|
|
|
Lazaret's north star is:
|
|
|
|
> Make isolated agent execution the easiest way to work, while ensuring that every
|
|
> transition from the sandbox to host authority is explicit, attributable, and
|
|
> controlled by the developer.
|
|
|
|
Lazaret therefore provides a rootless gVisor sandbox with a bidirectionally shared
|
|
workspace, persistent sandbox-local tooling, controlled network egress, and a
|
|
human-in-the-loop host escalation path.
|
|
|
|
### 1.1 Trust Model
|
|
|
|
The following components are trusted:
|
|
|
|
- The developer and host operating system.
|
|
- The Lazaret CLI and the domain's Session Coordinator (Host Coordinator, Runtime
|
|
Supervisor, and attached runsc client).
|
|
- Host configuration selected by the developer.
|
|
- Domain network-policy installation and connectivity helpers under Runtime
|
|
Supervisor ownership, and the policy Lazaret installs for the Domain.
|
|
|
|
The following components are untrusted:
|
|
|
|
- The agent and every process it launches.
|
|
- Code, tools, and package installation scripts executed inside the Agent Sandbox.
|
|
- Data received from the network by sandboxed processes.
|
|
|
|
All Client Sessions in the same Domain intentionally share an Agent Sandbox and
|
|
are one sandbox trust domain. Session identity distinguishes ownership and routes
|
|
terminal interactions; it is not an isolation boundary between processes in that
|
|
sandbox.
|
|
|
|
The Agent Workspace is intentionally writable. Lazaret protects the host outside
|
|
the explicitly mounted workspace and volumes. Tracked and ordinary untracked
|
|
workspace paths remain writable, while Git-ignored paths are isolated into
|
|
Domain-scoped sandbox state by default. The developer may explicitly disable that
|
|
isolation in trusted host configuration.
|
|
|
|
The physical refinement of model configuration confinement canonicalizes the
|
|
configuration file and every bind-mount source, compares their resolved ancestry,
|
|
and omits configuration bytes from the sandbox mount specification.
|
|
|
|
## 2. Glossary
|
|
|
|
These terms and identifiers are stable across the specification, protocol model,
|
|
implementation, logs, and user interfaces.
|
|
|
|
| Term | Definition |
|
|
| :--- | :--- |
|
|
| **Agent Profile** | A developer-selected host configuration describing an agent image and its granted storage, network, environment, and escalation capabilities. |
|
|
| **Agent Workspace** | The canonical host project directory mounted read-write at `/workspace` in the Agent Sandbox. |
|
|
| **Agent Sandbox** | The rootless gVisor container in which an agent and its child processes execute. One sandbox is shared by all Client Sessions in a Domain. gVisor sentry, gofer, and guest processes are the sandbox, not the Session Coordinator. |
|
|
| **Agent Sandbox ID** | A runtime-unique identifier assigned to one Agent Sandbox instance and bound to its Domain protocol identity. |
|
|
| **Client CLI ID** | A runtime-unique identifier assigned to one host Lazaret CLI process. It is authenticated as a protocol identity and bound to one Client Session. |
|
|
| **Client Session** | One active host Lazaret CLI process and the interactive or non-interactive command it attaches to the Agent Sandbox. |
|
|
| **Session ID** | A cryptographically random identifier unique to one Client Session. |
|
|
| **Session Anchor** | Ephemeral session credentials that bind protocol messages to a registered Session ID and route them to the owning host CLI. |
|
|
| **Session Coordinator** | The logical Domain role defined by the protocol model. The selected physical refinement maps it to Host Coordinator, Runtime Supervisor, and attached runsc processes. |
|
|
| **Session Coordinator ID** | A runtime-unique identifier for the logical Session Coordinator as a protocol peer, authenticated on the Host Coordinator face. Generation scoping and stale-credential refuse follow the protocol model. |
|
|
| **Host Coordinator** | The constitutive Session Coordinator process that runs in the host user and mount namespaces. It is the protocol face: Domain lock, durable state store, Session PTY masters, escalation mailbox and routing, publication and session admission, and lifetime authority over the Runtime Supervisor. |
|
|
| **Runtime Supervisor** | The constitutive Session Coordinator process that runs in the Domain generation's user, mount, and network namespaces under a Host Coordinator lifetime lease. It owns supervised filesystem and network resources for the generation, arms the parent-death edge to attached runsc, and launches the attached runsc client. |
|
|
| **Attached runsc** | The constitutive Session Coordinator process that is the non-detached `runsc` client child of the Runtime Supervisor. It supplies the causal coupling edge to the complete Agent Sandbox. |
|
|
| **Domain** | The shared runtime and persistent-state scope for one `(Agent Profile, canonical Agent Workspace)` pair. |
|
|
| **Domain ID** | A deterministic identifier derived from the Agent Profile name and canonical Agent Workspace path. It namespaces Domain resources but is not an authentication credential. |
|
|
| **Domain generation** | One attempt to prepare, publish, operate, and tear down or recover a Domain's transient runtime resources under a single Session Coordinator instance and durable generation identity. |
|
|
| **Domain Root** | The host-only directory containing persistent state and metadata for one Domain. |
|
|
| **Network Sidecar** | The logical Domain network-policy role for one Domain generation: derived-policy application, enforcement network-namespace preparation, connectivity-helper supervision, and network readiness attestation. Under the selected architecture this role is realized on the Runtime Supervisor-owned install path (with a supervised connectivity helper). It is not a constitutive Session Coordinator process and need not be a separate OS process. The Agent Sandbox never holds network-administration capability. |
|
|
| **Network Sidecar ID** | Protocol component identifier for the Domain generation's Network Sidecar role instance (not a Runtime Supervisor or connectivity-helper process id, and not a filesystem path). Generation scoping follows the protocol model. |
|
|
| **Connectivity helper** | The supervised process that provides user-space connectivity for the Domain enforcement network namespace. Production uses `slirp4netns`. Ownership and lease coupling follow the protocol model; process identity is product recovery material, not the Network Sidecar ID. |
|
|
| **Derived network policy** | The generation-bound policy document Lazaret derives from trusted host configuration (default and profile allow/deny prefixes, DNS reachability, address-family disposition). Only derived policy is installed; the Agent Sandbox never supplies policy. |
|
|
| **Network readiness fingerprint** | Product encoding of protocol network readiness: a cryptographic digest over Domain ID, generation, configuration fingerprint, Network Sidecar ID, derived-policy digest, and enforcement network-namespace identity material. |
|
|
| **Prepared lower** | A Lazaret-owned immutable root filesystem tree materialised from the selected base image. Content is identified by a prepared-artifact identity. |
|
|
| **Prepared-artifact ID** | A Lazaret-assigned identity for one immutable prepared-lower tree (content-addressed or otherwise unique among prepared lowers under the Storage Root). |
|
|
| **Prepared-lower lease** | Product binding of a Domain generation to a prepared-artifact ID for State Anchor use (not a container-engine mount refcount). Lease lifecycle follows the protocol model. |
|
|
| **Durable intent** | Protocol durable intent that Lazaret intends to create or has created a named external resource for a Domain generation (see protocol model). |
|
|
| **Publication** | Protocol publication of a Domain generation for Client Session registration and service (see protocol model). |
|
|
| **Git Sentry** | The protective mount layout that preserves bidirectional workspace and Git access while preventing writes to the host's default Git hooks and repository configuration. |
|
|
| **Ignored Workspace State** | Domain-scoped sandbox-local storage presented at Git-ignored Agent Workspace paths instead of exposing the corresponding host content. |
|
|
| **State Anchor** | The Domain-scoped persistent writable filesystem layer merged over selected paths from the sandbox base image prepared lower. |
|
|
| **Trust Anchor** | The ephemeral Domain-scoped certificate authority used to authenticate role-bound Lazaret protocol identities. |
|
|
| **Protocol Identity** | An authenticated binding of a component role, Agent Profile, Domain ID, and runtime component ID. Identifiers name components but do not authenticate them by themselves. |
|
|
| **Escalation Client** | The Lazaret-provided executable through which a sandboxed process requests a host action. |
|
|
| **Escalation Mailbox** | Host-private, Domain-scoped regular-file message paths mounted into the Agent Sandbox for signed escalation requests and correlated results. |
|
|
| **Escalation Request ID** | A cryptographically random identifier used to correlate one host escalation request and response. |
|
|
| **Escalation Result** | The terminal response to an accepted Host Escalation, correlated by Escalation Request ID and carrying its outcome plus command exit status and output when execution occurred. |
|
|
| **Host Escalation** | A request by a sandboxed process for Lazaret to execute a developer-approved or auto-approved action with host authority. |
|
|
| **Configuration Fingerprint** | A cryptographic digest of the validated host configuration that created or joined a running Domain. |
|
|
| **Storage Root** | The trusted host directory beneath which Lazaret stores Domain Roots and profile-scoped state. |
|
|
| **Storage Catalog** | The versioned redb store for prepared artifacts, preparation operations, and cross-Domain generation leases. Domain coordinators serialize short catalog transactions with the Storage Catalog lock; no process keeps the catalog open as global runtime authority. |
|
|
|
|
## 3. Architecture
|
|
|
|
### 3.1 System Boundaries
|
|
|
|
```mermaid
|
|
flowchart TB
|
|
subgraph Host[Trusted host]
|
|
CLI[Client CLI]
|
|
Config[Host configuration]
|
|
HostWorkspace[Agent Workspace]
|
|
HC[Host Coordinator]
|
|
RS[Runtime Supervisor]
|
|
Runsc[Attached runsc]
|
|
State[State Anchor / FUSE]
|
|
Net[Network policy + connectivity helper]
|
|
Mailbox[Escalation Mailbox]
|
|
HostExec[Approved host process]
|
|
end
|
|
|
|
subgraph Sandbox[Untrusted Agent Sandbox - rootless gVisor]
|
|
Agent[Agent and child processes]
|
|
Workspace[/workspace mount]
|
|
Escalate[Escalation Client]
|
|
end
|
|
|
|
Config --> CLI
|
|
HostWorkspace <--> Workspace
|
|
CLI <--> HC
|
|
HC --> RS
|
|
RS --> Runsc
|
|
Runsc --> Sandbox
|
|
RS --> State
|
|
RS --> Net
|
|
HC <--> Mailbox
|
|
Agent <--> Workspace
|
|
Agent --> Escalate
|
|
Escalate <--> Mailbox
|
|
HC --> HostExec
|
|
Agent --> Net
|
|
Net --> Network[Permitted destinations]
|
|
```
|
|
|
|
The physical Session Coordinator refinement uses an HC→RS parent/child edge and
|
|
lifetime pipe. The RS creates the generation namespaces, arms the parent-death
|
|
edge, and launches a non-detached runsc client. Client CLI protocol descriptors
|
|
terminate in the HC process.
|
|
|
|
The Agent Sandbox uses gVisor's application-kernel isolation under rootless
|
|
operation. The product launches runsc directly through the HC→RS→runsc process
|
|
chain; an external container engine does not own the Domain's Agent Sandbox.
|
|
Rootless operation limits the host authority of runtime helpers, while gVisor
|
|
interposes a separate userspace kernel between untrusted processes and the host
|
|
kernel. Network policy installation and connectivity helpers are trusted and are
|
|
not part of the untrusted agent environment.
|
|
|
|
Lazaret is daemonless: it does not require a persistent global Unix service or
|
|
cross-Domain runtime authority that survives independently of Domain generations.
|
|
Runtime paths and durable rows carry Domain ID, generation, configuration
|
|
fingerprint, role identity, and physical ownership fields. Bootstrap recovery is
|
|
initiated by a host Lazaret CLI invocation, not by a resident scheduler.
|
|
|
|
### 3.2 Domain and Session Lifecycle Refinement
|
|
|
|
The Host Coordinator implements Domain ownership with a non-blocking host
|
|
`flock`, Domain-scoped runtime paths, an exclusive Domain Store handle, and
|
|
generation identity records. Client CLIs reach the Host Coordinator through its
|
|
host-private protocol face rather than a global control plane.
|
|
|
|
Protocol lifecycle—startup, registration, cancellation, recovery, teardown,
|
|
publication, escalation, generation-scoped identities, durable intent, network
|
|
readiness, prepared-lower lease, and connectivity-helper ownership—is defined by
|
|
the [TLA+ application protocol model](protocol/Lazaret.tla). Product
|
|
implementation refines that model with physical resources (prepared-lower trees,
|
|
mounts, `slirp4netns`, PTYs, runsc clients, durable store encoding, and exact
|
|
ownership records). Physical recovery enumerates and inspects those resources
|
|
independently of process liveness.
|
|
|
|
### 3.3 Session Terminals
|
|
|
|
The Host Coordinator owns one host PTY master per interactive Client Session. The
|
|
PTY slave is attached to non-detached `runsc exec` standard streams with a guest
|
|
TTY. The root attached `runsc run` client remains terminal-neutral and is not the
|
|
Session PTY attachment path. Production must not depend on `runsc exec
|
|
-console-socket`.
|
|
|
|
Session terminal ownership is the Host Coordinator; a Client CLI never inherits
|
|
the sandbox Session PTY. For each Client Session the coordinator maintains the
|
|
session identity needed for routing and cleanup, including Session ID, PTY master,
|
|
`runsc exec` client process identity, and guest process or process-group identity.
|
|
|
|
Interactive terminal control requires:
|
|
|
|
- Window resize applied to the host PTY master and guest `SIGWINCH` delivered to
|
|
the exact session process or process group through runsc.
|
|
- Client control events (for example interrupt) translated into runsc signal
|
|
operations for that exact session process or process group; raw host PTY
|
|
control characters alone are not a sufficient contract.
|
|
- Per-session exit status collected from the non-detached `runsc exec` client as
|
|
the primary source.
|
|
- On session close, PTY master loss, or exec-client loss: apply the modeled
|
|
session-close transition, stop the exact guest session process or process
|
|
group through runsc, reap the exec client, and close the PTY.
|
|
|
|
Disconnected Client Sessions close rather than reattach to an unbounded scrollback
|
|
owned by the coordinator.
|
|
|
|
### 3.4 Filesystem and Git Model
|
|
|
|
The Agent Workspace is mounted read-write. Tracked paths and untracked paths that
|
|
are not ignored propagate in both directions. The Git index, `HEAD`, references,
|
|
and objects are shared with the host in real time. Lazaret does not create a
|
|
separate worktree or branch and does not promise that the host working tree
|
|
remains unchanged.
|
|
|
|
By default, paths matched by the repository's effective Git ignore rules are
|
|
redirected to Ignored Workspace State. Existing host content at those paths is not
|
|
exposed to the Agent Sandbox, and sandbox writes remain Domain-scoped and persist
|
|
across restarts. This prevents agent-modified dependency trees, virtual
|
|
environments, generated executables, caches, and other ignored artifacts from
|
|
later being executed by host tools. Trusted host configuration may disable this
|
|
behavior when fully bidirectional ignored paths are required.
|
|
|
|
Ignored-path isolation is defense in depth and does not replace the mandatory Git
|
|
Sentry protections below.
|
|
|
|
Lazaret applies narrow protective mounts over host integration files that must not
|
|
be modified by the agent:
|
|
|
|
- The host repository's `.git/config` is exposed read-only.
|
|
- The host repository's `.git/hooks` is hidden behind sandbox-local transient
|
|
storage.
|
|
- Supported host editor configuration directories may be hidden behind
|
|
sandbox-local transient storage.
|
|
|
|
These protections do not make the workspace immutable. Their purpose is to stop
|
|
the sandbox from writing the protected host Git configuration and default hook
|
|
directory while preserving normal Git operations and bidirectional source edits.
|
|
|
|
### 3.5 Persistent Sandbox State
|
|
|
|
The State Anchor preserves developer tooling and selected sandbox system paths for
|
|
one Domain. It combines a Lazaret-owned prepared lower from the selected base
|
|
image with a Domain-scoped writable upper directory.
|
|
|
|
#### Prepared lower
|
|
|
|
Preparation resolves the selected base image, applies layers with a supported
|
|
OCI-aware preparer, and materialises an immutable Lazaret-owned root filesystem
|
|
tree under the Storage Root. The tree carries a prepared-artifact ID and a source
|
|
image identity. Live container-engine image mounts are not a production State
|
|
Anchor lower. Archive export alone is not a complete preparation boundary;
|
|
container tooling may participate only as transport into Lazaret-owned
|
|
preparation. Ad hoc unsupported tar extractors are not a production preparer.
|
|
|
|
Prepared-artifact identity is independent of its storage pathname. The Domain
|
|
Store and Storage Catalog encode the model's generation-to-artifact lease with
|
|
separate Domain and generation fields; an engine mount refcount is not its
|
|
physical representation. Preparation uses descriptor-relative staging,
|
|
publication, quarantine, and deletion beneath validated Storage Root handles.
|
|
|
|
The prepared rootfs preserves OCI modes and is exposed only as a read-only State
|
|
Anchor lower. Lazaret enforces immutability through artifact ownership and
|
|
lifecycle rather than by rewriting image permission bits.
|
|
|
|
#### Durable generation document refinement
|
|
|
|
Durable Domain state is an embedded store opened exclusively by the Host
|
|
Coordinator process that holds the Domain's exclusive lifecycle lock for write.
|
|
No other process opens the store for read or write: Client CLIs, the Runtime
|
|
Supervisor, recovery observers, and status tools obtain state only through Host
|
|
Coordinator IPC or by becoming the lock-holding Host Coordinator. Domain flock
|
|
serializes which process may be that exclusive opener. Store mutations use
|
|
atomic transactions; an interrupted write leaves the last successfully committed
|
|
document, never a half-applied generation decision.
|
|
|
|
Protocol durable decision vocabulary, multi-role intent, and mismatch refuse are
|
|
defined by the protocol model. The product store encodes that generation document
|
|
in typed tables under a schema/db version (unknown newer versions fail closed
|
|
until an explicit Host Coordinator migration), including generation identity,
|
|
minted runtime component IDs, and participant ownership material (for example
|
|
prepared-artifact ID, pid/start, mount identity, network readiness fingerprint).
|
|
Participant roles are `prepared_lower`, `state_anchor`, `git_routing`, `network`,
|
|
`helper`, `sandbox`, and `publication`. The `helper` participant independently
|
|
records durable intent and exact connectivity-helper pid/start identity before
|
|
the `network` participant records readiness. Sessions and the generation mailbox
|
|
are separate generation records. Deterministic paths are lookup hints for
|
|
physical recovery, not ownership proofs.
|
|
|
|
The normative logical records and relationships are defined in the
|
|
[design schemas](schema.md). Their implementation representation must preserve
|
|
the distinct Domain Store and Storage Catalog boundaries. Opaque generation
|
|
documents are not a product storage format.
|
|
|
|
Each catalog operation acquires host-wide `storage-catalog.lock`, opens the
|
|
catalog, performs one redb transaction, closes it, and releases the lock. The
|
|
lock covers lease changes, prepare publication, and transition to `Reclaiming`.
|
|
This permits concurrent Domain coordinators without a persistent global daemon
|
|
or concurrent redb opens.
|
|
|
|
The physical lease-acquisition refinement is:
|
|
|
|
1. Commit `prepared_lower = Intent` in the Domain Store with the intended
|
|
prepared-artifact identity.
|
|
2. Under `storage-catalog.lock`, insert the exact `(prepared-artifact ID, Domain
|
|
ID, generation)` lease in one catalog transaction.
|
|
3. Commit `prepared_lower = LeaseHeld` in the Domain Store.
|
|
4. Commit `state_anchor = Intent`, create the exact mount, and then commit
|
|
`state_anchor = Prepared` with its mount identity.
|
|
|
|
The physical unmount and lease-release refinement is:
|
|
|
|
1. Commit `state_anchor = ReleaseIntent` while retaining its exact mount and
|
|
prepared-artifact identity.
|
|
2. Verify the recorded mount identity and unmount it. A mismatched mount refuses
|
|
release and remains untouched.
|
|
3. After independently observing that the exact mount is absent, atomically
|
|
commit `state_anchor = Clean` and `prepared_lower = ReleaseIntent` in the
|
|
Domain Store.
|
|
4. Under `storage-catalog.lock`, recheck the matching Domain release intent and
|
|
absence of the exact mount, then remove only the exact generation lease in one
|
|
catalog transaction.
|
|
5. Commit `prepared_lower = Clean` in the Domain Store.
|
|
|
|
Recovery resumes only from matching durable identity. `state_anchor =
|
|
ReleaseIntent` retains the catalog lease while recovery verifies and completes
|
|
the unmount. `prepared_lower = ReleaseIntent` permits removal of a still-present
|
|
exact catalog lease only after the exact mount is absent; an already-absent lease
|
|
permits the Domain participant to become `Clean`. A catalog lease with missing,
|
|
unreadable, non-release, or mismatched Domain evidence is retained and reported.
|
|
A Domain `LeaseHeld` record whose exact catalog lease is absent is inconsistent
|
|
and fails closed; recovery neither recreates the lease nor mounts the State
|
|
Anchor. These rules make every interrupted release conservative and prevent a
|
|
mounted State Anchor from becoming unleased.
|
|
|
|
Store version acceptance occurs before physical resource inspection. The first
|
|
product version has no product predecessor. Future migration steps create and
|
|
validate destination rows in one redb transaction and update the version last.
|
|
|
|
Files not represented in the upper layer follow the selected base image. Files,
|
|
directories, and whiteouts recorded in the upper layer remain authoritative when
|
|
the lower image changes. This permits installed tools to survive restarts while
|
|
allowing unmodified base-image content to follow the selected image.
|
|
|
|
Persistent state is sandbox state, not host configuration. It must not contain or
|
|
override Lazaret's host control plane.
|
|
|
|
### 3.6 Network Isolation
|
|
|
|
The Network Sidecar role is realized on the Runtime Supervisor-owned install
|
|
path: the Runtime Supervisor (or a packaging-equivalent installer still bound to
|
|
the same Network Sidecar ID) holds network-administration capability only for
|
|
install and attestation in the Domain enforcement network namespace. The Agent
|
|
Sandbox does not receive that capability and may join only that prepared
|
|
enforcement namespace, not the host network namespace. Production connectivity uses
|
|
`slirp4netns`. Installing policy by driving nftables through runsc into the guest
|
|
is not a production path. Protocol helper ownership, network readiness, and
|
|
publication gates follow the protocol model.
|
|
|
|
#### Derived policy and readiness encoding
|
|
|
|
The policy, attestation, readiness-identity projection, and fingerprint inputs
|
|
are defined by the normative [design schemas](schema.md).
|
|
|
|
The Host Coordinator passes canonical policy bytes through a write-sealed
|
|
inherited memfd. The Runtime Supervisor verifies the seals and digest, installs
|
|
the policy, and returns observed route, helper, process, and namespace evidence
|
|
over an inherited Host Coordinator-created private `SOCK_SEQPACKET` channel.
|
|
Before helper launch, the Host Coordinator commits the independent `helper`
|
|
participant as `Intent`. After launch it verifies and commits the exact helper
|
|
and supervising Runtime Supervisor pid/start identities before accepting network
|
|
readiness evidence and advancing the `network` participant.
|
|
The Host Coordinator independently reads the Runtime Supervisor's namespace
|
|
identity and persists the attestation, fingerprint, and generation-bound
|
|
deny/permit/DNS probe result. Persisted readiness files are evidence after this
|
|
exchange, not its transport.
|
|
|
|
#### Default policy and deny representation
|
|
|
|
IPv4 destinations are permitted by default except for the RFC 1918 private
|
|
address ranges (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`), which are denied
|
|
by default. Explicit, more-specific allow rules may grant access within those
|
|
ranges. Lazaret also installs the reachability needed for the Domain's selected
|
|
DNS resolvers. Other permitted and denied destination prefixes come from trusted
|
|
host configuration.
|
|
|
|
Default and configured deny prefixes are enforced with **loopback-unicast deny
|
|
routes** in the Domain enforcement network namespace (routes that direct matching
|
|
destinations to a loopback unicast address so packets are not forwarded). Linux
|
|
`blackhole` routes are not the production deny representation for this path.
|
|
Equal-prefix allow/deny conflicts must be rejected or resolved in favor of denial.
|
|
|
|
Normal Linux longest-prefix routing determines the most specific matching route.
|
|
IPv4 and IPv6 must either receive equivalent policy or an address family must be
|
|
disabled.
|
|
|
|
The OCI configuration joins only the Domain enforcement network namespace, and
|
|
`slirp4netns` attached to that namespace is the sole external egress mechanism.
|
|
Dynamic policy changes are outside the current physical refinement.
|
|
|
|
### 3.7 Host Escalation
|
|
|
|
The Escalation Client exchanges request and result records through the
|
|
Escalation Mailbox: regular files written by atomic rename beneath host-private,
|
|
Domain-scoped paths. Request and result paths may use different mount modes. The
|
|
mailbox is not an authentication boundary. Its paths include Domain and
|
|
generation identity and are opened through Host Coordinator-owned directory
|
|
handles. Host-only CLI/coordinator control may use host-private Unix sockets that
|
|
are never mounted into the Agent Sandbox.
|
|
|
|
The physical host-process launcher invokes an executable with an argument vector
|
|
and contains no shell-expansion path.
|
|
|
|
Escalation authentication, correlation, approval, execution, cancellation, result
|
|
delivery, and terminal routing are defined by the
|
|
[TLA+ application protocol model](protocol/Lazaret.tla).
|
|
|
|
### 3.8 State Inspection and Reset
|
|
|
|
The host CLI provides read-only discovery, inspection, structural verification,
|
|
and explicit reset operations for Domain State Anchors. These operations resolve
|
|
a Domain through trusted host metadata and never accept an arbitrary host
|
|
filesystem path as an upper-layer target.
|
|
|
|
Inspection reports metadata and overlay changes without printing file contents by
|
|
default. Structural verification requires an inactive Domain and exclusive
|
|
lifecycle ownership so its result is not invalidated by concurrent writes. A
|
|
reset may target one configured persistent container path or all State Anchors in
|
|
the Domain. It discards the selected upper-layer state so the next launch follows
|
|
the current prepared lower; it does not modify the prepared lower artifact, Agent
|
|
Workspace, Ignored Workspace State, or unselected State Anchors.
|
|
|
|
Reset is permitted only after Lazaret holds the Domain's exclusive lifecycle lock
|
|
and has established that no Client Session, Session Coordinator constitutive
|
|
process, sandbox, network helper, host process, or overlay mount is using the
|
|
selected state. Confirmation flags may suppress the human prompt but may not
|
|
bypass these safety conditions. Reset must be crash-consistent and must never
|
|
follow a symlink outside the Domain Root.
|
|
|
|
## 4. Requirements
|
|
|
|
These requirements cover physical mechanisms and encodings below the TLA+
|
|
abstraction boundaries. Modeled safety and liveness requirements are intentionally
|
|
not duplicated here.
|
|
|
|
### 4.1 Security Requirements
|
|
|
|
| ID | Requirement |
|
|
| :--- | :--- |
|
|
| **SR-1** | Agent processes shall execute in a rootless gVisor sandbox and shall not receive host root authority. |
|
|
| **SR-3** | Host paths outside the Agent Workspace, developer-configured volumes, and Lazaret-owned fixed control mounts shall not be accessible to the Agent Sandbox. |
|
|
| **SR-4** | The sandbox shall be unable to modify the host repository's `.git/config` or default `.git/hooks` directory through the workspace mount. |
|
|
| **SR-5** | Network-administration capability for policy installation shall be confined to the Runtime Supervisor-owned Network Sidecar install path; the Agent Sandbox process specification shall omit that capability. |
|
|
| **SR-6** | Network policy shall cover every enabled address family and shall deny equal-specificity policy conflicts. Default and configured deny prefixes shall be enforced with loopback-unicast deny routes in the Domain enforcement network namespace; Linux blackhole routes shall not be the production deny representation. |
|
|
| **SR-10** | Domain sockets, mailboxes, and coordination files shall reside in a host-private directory owned by the developer. |
|
|
| **SR-11** | Runtime and persistent path construction shall begin from validated Domain roots, include the Domain ID in resource identities, and verify stored Domain identity before reuse. |
|
|
| **SR-12** | The runsc OCI specification shall create private PID, IPC, UTS, mount, and user namespaces and set its network namespace path to the independently verified Runtime Supervisor namespace descriptor. It shall contain no host namespace path entry. |
|
|
| **SR-13** | Git-ignored Agent Workspace paths shall use Ignored Workspace State by default, preventing the sandbox from reading or modifying corresponding host content; only trusted host configuration may disable this behavior. |
|
|
| **SR-14** | State Anchor maintenance shall remain confined to the resolved Domain Root. Destructive maintenance shall require exclusive lifecycle ownership and an inactive, unmounted target. |
|
|
| **SR-15** | Lazaret shall not use a live container-engine image mount as the production State Anchor lower; the lower shall be a Lazaret-owned prepared lower. Archive export alone shall not be treated as a complete preparation boundary. |
|
|
|
|
### 4.2 Functional Requirements
|
|
|
|
| ID | Requirement |
|
|
| :--- | :--- |
|
|
| **FR-1** | Lazaret shall derive a stable Domain ID from the selected Agent Profile and canonical Agent Workspace. |
|
|
| **FR-3** | Tracked and non-ignored workspace edits and supported Git operations shall propagate bidirectionally between host and sandbox. |
|
|
| **FR-4** | Selected sandbox paths and Ignored Workspace State shall persist across Domain restarts without copying Lazaret host configuration into the sandbox. |
|
|
| **FR-7** | Product recovery shall inspect external runtime resources independently of owner-process liveness and compare typed pid/start, namespace, mount, artifact, path, and inode evidence before physical cleanup. |
|
|
| **FR-8** | Lazaret shall support interactive terminal sessions without degrading supported host terminal capabilities. |
|
|
| **FR-9** | Trusted host configuration shall allow the developer to disable Git-ignored path isolation for an Agent Profile. |
|
|
| **FR-11** | The host CLI shall list, inspect, structurally verify, and reset all or selected State Anchors without requiring direct manipulation of Lazaret's storage layout. |
|
|
| **FR-14** | The Host Coordinator shall own one host PTY master per interactive Client Session; the PTY slave shall attach through non-detached `runsc exec` standard streams. The root attached `runsc run` client shall remain terminal-neutral. Production Session PTYs shall not depend on `runsc exec -console-socket`. |
|
|
| **FR-15** | For each interactive Client Session, Lazaret shall apply window resize to the host PTY master and deliver guest `SIGWINCH` to the exact session process or process group through runsc; translate Client control events into runsc signal operations; collect exit status primarily from the non-detached `runsc exec` client; and after the modeled session-end transition stop the exact guest process or process group, reap the exec client, and close the PTY. |
|
|
| **FR-16** | Domain network connectivity shall use `slirp4netns` as the production connectivity helper. The Domain Store shall record independent `helper` intent before launch and exact helper and supervising Runtime Supervisor pid/start identities before network readiness. |
|
|
| **FR-17** | The Domain Store shall be opened only by the Host Coordinator process holding the Domain `flock`; mutations shall use whole redb transactions. Storage Catalog opens shall be bounded by `storage-catalog.lock` and one transaction. Cross-store lease release shall follow the durable release-intent, exact-unmount, catalog-delete, Domain-clean ordering defined by the durable generation refinement. |
|
|
| **FR-18** | Product network-readiness evidence shall conform to the normative design schema and include the readiness fingerprint plus the generation-bound deny/permit/DNS probe result. |
|
|
| **FR-19** | The Host Coordinator shall derive generation-bound network policy from trusted host configuration; the Runtime Supervisor shall install only that derived policy and attest readiness by observed namespace state. Durable network participant state shall record the network readiness fingerprint. |
|
|
| **FR-20** | The physical network probe shall execute in the Agent Sandbox network view or an equivalent generation-bound process using the same enforcement namespace and record configured deny, permitted reachability, and selected DNS resolver observations. |
|
|
| **FR-21** | The Domain Store and Storage Catalog shall preserve the records, ownership variants, identities, and relationships in the normative design schema. |
|
|
| **FR-22** | Preparation shall use a supported OCI-aware preparer that materialises a Lazaret-owned immutable rootfs with source identity and prepared-artifact ID. |
|
|
|
|
### 4.3 Developer-Experience Requirements
|
|
|
|
| ID | Requirement |
|
|
| :--- | :--- |
|
|
| **DX-1** | A developer shall be able to launch an Agent Profile in the current workspace with one command. |
|
|
| **DX-2** | Tools installed in configured persistent sandbox paths and dependencies stored in Ignored Workspace State shall remain available on later launches of the same Domain. |
|
|
| **DX-3** | Normal source editing, `git status`, staging, committing, and reference updates shall work from inside the Agent Sandbox. |
|
|
| **DX-4** | Escalation prompts shall identify the requesting profile, session, command, and justification without mixing terminal input or output between sessions. |
|
|
| **DX-5** | Failures shall report actionable diagnostics and shall not leave the developer's terminal in a corrupted mode. |
|
|
| **DX-6** | State inspection shall provide human-readable and machine-readable output without exposing persisted file contents by default, and reset shall show its resolved Domain and exact scope before confirmation. |
|
|
|
|
### 4.4 Operational Requirements
|
|
|
|
| ID | Requirement |
|
|
| :--- | :--- |
|
|
| **OR-4** | Security-sensitive behavior shall be covered by integration tests on supported runsc, filesystem, and network configurations. |
|
|
| **OR-5** | An interrupted State Anchor reset shall recover to either the prior generation or a new empty generation; it shall not leave a partially reset active upper layer. |
|
|
| **OR-6** | Lazaret shall not require a persistent global daemon or multi-Domain resident process. Shared Storage Catalog operations shall use bounded lock/open/transaction/close critical sections. |
|