Classify serialized and runtime schema records
This commit is contained in:
parent
b34421efa1
commit
f106a9f636
1 changed files with 697 additions and 110 deletions
|
|
@ -63,9 +63,10 @@ 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.
|
||||
The trusted-host configuration refinement below owns strict parsing,
|
||||
canonicalization, path authority, and configuration fingerprinting. Successful
|
||||
loading is the physical meaning of the model's `ConfigSafe`; configuration bytes
|
||||
never enter a sandbox mount specification.
|
||||
|
||||
## 2. Glossary
|
||||
|
||||
|
|
@ -178,7 +179,154 @@ 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
|
||||
### 3.2 Trusted Host Configuration Refinement
|
||||
|
||||
The trusted-host configuration has the closed v1 shape in the
|
||||
[design schemas](schema.md). Lazaret chooses its configuration file from an
|
||||
explicit host CLI option or, when absent, from
|
||||
`$XDG_CONFIG_HOME/lazaret/config.toml`, with
|
||||
`$HOME/.config/lazaret/config.toml` as the XDG fallback. It derives the Storage
|
||||
Root from `storage.data_root` when present, otherwise from
|
||||
`$XDG_DATA_HOME/lazaret`, with `$HOME/.local/share/lazaret` as the fallback. The
|
||||
Runtime Root is `$XDG_RUNTIME_DIR/lazaret`; v1 has no configuration field that
|
||||
can redirect runtime control state elsewhere. Required XDG and home inputs must
|
||||
be NUL-free host paths. An unset, empty, or relative XDG config or data value is
|
||||
treated as unset and uses its home fallback; the home path and XDG runtime path
|
||||
must be present and absolute. An invalid fallback or runtime value refuses
|
||||
loading.
|
||||
|
||||
The caller supplies one profile name explicitly. Lazaret never selects the
|
||||
first profile, infers a profile from an image or executable, or falls back to a
|
||||
different profile. The canonical Agent Workspace is the existing directory
|
||||
selected by the caller, normally the current working directory. Lazaret opens
|
||||
it as a directory, obtains its canonical raw pathname and filesystem identity,
|
||||
and retains the descriptor. The selected profile name and canonical workspace
|
||||
bytes produce `DomainIdV1` exactly as defined by the schema.
|
||||
|
||||
The explicit configuration path follows the schema's strict host-path grammar.
|
||||
The loader resolves any declared symlink once to a canonical target and builds
|
||||
a no-symlink confined plan to that target. The source is limited to 1,048,576
|
||||
bytes, must be a regular file owned by root or the invoking user with exactly
|
||||
one hard link, and must not grant group or other write permission. Lazaret first
|
||||
opens it
|
||||
with an O_PATH-style descriptor so validating the file type cannot activate a
|
||||
special file, reopens that exact descriptor for nonblocking read, and compares
|
||||
their identities. It records size and nanosecond change time, reads exactly the
|
||||
recorded size into owned bytes, refuses trailing growth or a short read, reads
|
||||
the same range a second time, and requires equal bytes and unchanged identity,
|
||||
size, and change time before and after both reads. The loader never retries a
|
||||
changed source. It then performs recursive strict TOML decoding and v1 dispatch.
|
||||
No parser default or permissive flattening may make an unknown, duplicate,
|
||||
aliased, or unknown-version field meaningful. Every profile is structurally
|
||||
decoded, but filesystem and environment resolution applies only to the
|
||||
explicitly selected profile.
|
||||
|
||||
Path resolution produces a `ConfinedPathPlan`, not an ambient absolute path.
|
||||
Each plan retains a validated ancestor directory descriptor and a normalized
|
||||
relative suffix, records the ancestor's device, inode, and mount identity, and
|
||||
keeps canonical raw pathname bytes only as a diagnostic label or digest input.
|
||||
Every consumer uses descriptor-relative opens with beneath, no-magic-link,
|
||||
no-symlink, and no-mount-crossing resolution and revalidates the expected type.
|
||||
The consumer refuses a replaced ancestor, mount transition, symlink, special
|
||||
file, type mismatch, or any source that cannot be revalidated; it does not
|
||||
recover by opening the canonical label as an absolute pathname.
|
||||
|
||||
Lazaret creates a missing Storage, Runtime, profile, or Domain root one path
|
||||
component at a time beneath its retained existing ancestor. Every created
|
||||
component has mode `0700`. Creation refuses symlinks, magic links, and child
|
||||
mounts, and reopens each new component before proceeding. The selected root, if
|
||||
it already exists, and every component Lazaret creates beneath the closest
|
||||
existing ambient ancestor are Lazaret-owned: each must be a directory owned by
|
||||
the invoking user with mode exactly `0700`. Ambient ancestors above that
|
||||
ownership boundary use the same descriptor-relative confinement but need not
|
||||
use Lazaret's ownership or mode; an ordinary `0755` home-directory ancestor
|
||||
therefore does not by itself refuse loading. A creation or validation failure is
|
||||
final for that load and never authorizes a partially resolved root.
|
||||
|
||||
The profile directory is the `profiles/<profile-name>` child of the Storage
|
||||
Root. Persistent and runtime Domain roots use the lowercase hexadecimal Domain
|
||||
ID beneath separate `domains` children of the Storage and Runtime Roots. Those
|
||||
fixed layouts are constructed only from validated root handles; a path string
|
||||
or matching digest alone is not authority over a root.
|
||||
|
||||
Configuration confinement compares canonical component ancestry and retained
|
||||
filesystem identities after every source has been opened. The configuration
|
||||
file, Agent Workspace, Storage Root, Runtime Root, and their Domain/control
|
||||
trees may not overlap in either ancestor direction. Volume sources may be
|
||||
strict descendants of the profile directory, but they may not overlap the
|
||||
configuration source, Agent Workspace, runtime or Domain control trees, or one
|
||||
another. Other volume sources must be disjoint from all Lazaret data and control
|
||||
trees as well. All paths are reopened through their plans after the comparisons;
|
||||
any identity or mount change refuses the complete load. Volume creation is
|
||||
limited to a declared directory strictly beneath the profile directory and uses
|
||||
the same component-wise `0700` creation rules.
|
||||
|
||||
Configuration resolution also requires an internal `SandboxLayoutV1`. Its
|
||||
closed protected-destination set contains `/workspace` and every product-owned
|
||||
sandbox mount destination selected by production layout construction. Each
|
||||
persistent or volume destination is compared with every member in both ancestry
|
||||
directions. The configuration loader does not guess paths for control,
|
||||
credential, mailbox, proc, sys, dev, runtime, or later product mounts, and a
|
||||
layout cannot be constructed without `/workspace`. Production layout
|
||||
construction, rather than trusted-host configuration syntax, owns the remaining
|
||||
exact destination choices.
|
||||
|
||||
The loader resolves environment references only after structural, path, and
|
||||
network validation. A missing, non-UTF-8, or NUL-containing host value refuses
|
||||
the selected profile. Resolved values live only in the move-owned
|
||||
`ResolvedDomainConfiguration`; its representation is not serializable and its
|
||||
diagnostics redact values. Only reference names enter the configuration
|
||||
fingerprint. Configuration bytes, nonselected profiles, and unreferenced host
|
||||
environment values are not retained as runtime authority or copied into the
|
||||
Agent Sandbox.
|
||||
|
||||
The Host Coordinator derives the selected profile's effective IPv4 policy and
|
||||
`ConfigurationFingerprintV1` using the schema's exact normalization and
|
||||
canonical framing. IPv6 is disabled for a v1 sandbox. Joining a running Domain
|
||||
requires the same Domain ID and configuration fingerprint; the modeled
|
||||
configuration-mismatch path refuses every other value.
|
||||
|
||||
For auto-approval, the configured executable resolves to one canonical path
|
||||
outside every sandbox-writable or Lazaret control tree. That path, rather than a
|
||||
`PATH` lookup or basename, is fingerprinted and matched. On every approved
|
||||
execution the Host Coordinator reopens the current object through its confined
|
||||
plan, requires a regular file with exactly one hard link, root or invoking-user
|
||||
ownership, no group or other write permission, and an executable mode for the
|
||||
invoking user, and passes that open descriptor into the causal launch wrapper.
|
||||
The same checks apply when configuration is loaded. The wrapper
|
||||
executes `/proc/self/fd/<inherited-descriptor>` while retaining that descriptor,
|
||||
so pathname replacement after validation cannot select another object. There is
|
||||
no shell, numeric descriptor supplied by the requester, ambient-path reopen, or
|
||||
fallback execution path. Scripts are subject to the kernel's ordinary shebang
|
||||
handling; the rule authorizes the exact opened script object, not an arbitrary
|
||||
requester-selected interpreter.
|
||||
|
||||
`MailboxRequest.command_argv` is nonempty. Every element is UTF-8 and NUL-free;
|
||||
element zero is an absolute path byte-equal to the rule's canonical executable,
|
||||
and elements one onward are matched against the rule arguments. Lazaret performs
|
||||
no `PATH` lookup. The v1 structured request language accepts no command-string
|
||||
or shell-expansion form; an unsupported form has the physical
|
||||
`CommandRequiresShell` classification and cannot auto-approve. The launcher
|
||||
never inserts or interprets a shell. An explicitly configured `/bin/sh -c ...`
|
||||
vector can match only its exact configured rule. A directly configured script
|
||||
continues to use ordinary kernel shebang handling for the same opened script
|
||||
object.
|
||||
|
||||
Any shell-requiring request form, invalid executable, post-load path conflict,
|
||||
or argument mismatch follows the modeled developer approval path or is refused;
|
||||
it is never widened into automatic approval. Requiring one hard link rejects
|
||||
hardlinked package layouts, including affected Nix-style binaries, in v1. This
|
||||
is a deliberate conservative compatibility boundary. Relaxing it requires a
|
||||
new executable-alias authority policy in a later version; v1 has no exception or
|
||||
fallback.
|
||||
|
||||
`ResolvedDomainConfiguration` is created before a generation, durable intent,
|
||||
or external runtime resource. Every production configuration consumer receives
|
||||
that same owned resolved value or a capability-bounded borrow from it; consumers
|
||||
do not reparse the TOML document or independently repeat default, path, network,
|
||||
environment, fingerprint, or approval decisions.
|
||||
|
||||
### 3.3 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
|
||||
|
|
@ -375,7 +523,7 @@ withdraws publication before dropping keys and credential artifacts. HC loss
|
|||
destroys the in-memory package; bootstrap never restores it into another
|
||||
generation.
|
||||
|
||||
### 3.3 Session Terminals
|
||||
### 3.4 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
|
||||
|
|
@ -491,7 +639,7 @@ after that runtime-absence check. A process, container, PTY, or generation
|
|||
mismatch fails closed and retains the record; it is never adopted or signaled as
|
||||
the recorded session.
|
||||
|
||||
### 3.4 Filesystem and Git Model
|
||||
### 3.5 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,
|
||||
|
|
@ -523,7 +671,7 @@ 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
|
||||
### 3.6 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
|
||||
|
|
@ -654,7 +802,7 @@ 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
|
||||
### 3.7 Network Isolation
|
||||
|
||||
The Network Sidecar role is realized on the Runtime Supervisor-owned install
|
||||
path. The Runtime Supervisor holds network-administration capability while it
|
||||
|
|
@ -712,7 +860,7 @@ 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
|
||||
### 3.8 Host Escalation
|
||||
|
||||
The Escalation Client exchanges request and result records through the
|
||||
Escalation Mailbox: regular files written by atomic rename beneath host-private,
|
||||
|
|
@ -748,7 +896,7 @@ Escalation authentication, correlation, approval, execution, cancellation, resul
|
|||
delivery, and terminal routing are defined by the
|
||||
[TLA+ application protocol model](protocol/Lazaret.tla).
|
||||
|
||||
### 3.8 State Inspection and Reset
|
||||
### 3.9 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue