2026-07-11 23:33:04 +09:00
|
|
|
# Lazaret schemas
|
|
|
|
|
|
2026-07-14 23:34:56 +09:00
|
|
|
This document is a mutable coordination schema for Lazaret records and protocol
|
|
|
|
|
data shapes. The [specification](specification.md) defines their authoritative
|
|
|
|
|
physical use, while the TLA+ models define authoritative lifecycle and ordering
|
|
|
|
|
above the implementation abstraction. The diagrams coordinate logical fields,
|
|
|
|
|
variants, relationships, and serialization boundaries across implementation
|
|
|
|
|
work; they do not select a programming-language representation or override the
|
|
|
|
|
specification or models.
|
|
|
|
|
|
|
|
|
|
Every class carries exactly one serialization-category stereotype:
|
|
|
|
|
`<<serialized>>` identifies a record that may cross a configuration,
|
|
|
|
|
durable-storage, or protocol codec boundary, while `<<runtime>>` identifies an
|
|
|
|
|
in-memory authority or plan that must not implement Serde serialization or
|
|
|
|
|
deserialization. Shape stereotypes such as `<<enumeration>>` and `<<union>>` are
|
|
|
|
|
orthogonal and may coexist.
|
|
|
|
|
|
|
|
|
|
## Trusted host configuration
|
|
|
|
|
|
|
|
|
|
The trusted-host configuration dispatch identifier is exactly
|
|
|
|
|
`lazaret-trusted-host-config-v1`. The v1 TOML document has the following closed
|
|
|
|
|
shape; every table recursively rejects unknown fields, duplicate keys, duplicate
|
|
|
|
|
tables, field aliases, and unknown enumeration values.
|
|
|
|
|
|
|
|
|
|
| Table | Field | Presence and value |
|
|
|
|
|
| :--- | :--- | :--- |
|
|
|
|
|
| root | `schema` | required; exact dispatch identifier |
|
|
|
|
|
| root | `storage` | optional; defaults to an empty table |
|
|
|
|
|
| root | `network` | optional; defaults to an empty table |
|
|
|
|
|
| root | `profiles` | required; at least one dynamically named profile |
|
|
|
|
|
| `storage` | `data_root` | optional host path; defaults beneath the XDG data home |
|
|
|
|
|
| `network` | `default_allow` | optional list of IPv4 prefixes; defaults empty |
|
|
|
|
|
| `network` | `default_deny` | optional list of IPv4 prefixes; defaults empty |
|
|
|
|
|
| profile | `image` | required nonempty OCI image reference |
|
|
|
|
|
| profile | `isolate_gitignored` | optional Boolean; defaults `true` |
|
|
|
|
|
| profile | `persistent_dirs` | optional list of sandbox paths; defaults empty |
|
|
|
|
|
| profile | `allow_egress` | optional list of IPv4 prefixes; defaults empty |
|
|
|
|
|
| profile | `deny_egress` | optional list of IPv4 prefixes; defaults empty |
|
2026-07-16 20:41:13 +09:00
|
|
|
| profile | `readiness` | required at load for the selected profile; closed denied, permitted, and DNS target table |
|
2026-07-14 23:34:56 +09:00
|
|
|
| profile | `env` | optional map from sandbox environment name to `env:` reference; defaults empty |
|
|
|
|
|
| profile | `volumes` | optional list of volume tables; defaults empty |
|
|
|
|
|
| profile | `escalation` | optional table; defaults to disabled with no rules |
|
2026-07-16 20:41:13 +09:00
|
|
|
| `readiness` | `denied` | one to 32 unique `{ address = IPv4, port = nonzero }` targets denied by effective policy |
|
|
|
|
|
| `readiness` | `permitted` | one to 32 unique `{ address = IPv4, port = nonzero }` targets allowed by effective policy |
|
|
|
|
|
| `readiness` | `dns` | one to 32 unique `{ resolver = IPv4, query = strict DNS name }` targets |
|
2026-07-14 23:34:56 +09:00
|
|
|
| volume | `host` | required host path |
|
|
|
|
|
| volume | `container` | required sandbox path |
|
|
|
|
|
| volume | `kind` | required: `file` or `directory` |
|
|
|
|
|
| volume | `access` | optional: `read-only` or `read-write`; defaults `read-write` |
|
|
|
|
|
| volume | `create` | optional Boolean; defaults `false` |
|
|
|
|
|
| `escalation` | `enabled` | optional Boolean; defaults `false` |
|
|
|
|
|
| `escalation` | `auto_approve` | optional list of auto-approval rules; defaults empty |
|
|
|
|
|
| auto-approval rule | `executable` | required host executable path |
|
|
|
|
|
| auto-approval rule | `args` | optional ordered list of arguments; defaults empty |
|
|
|
|
|
| auto-approval rule | `allow_extra_args` | optional Boolean; defaults `false` |
|
|
|
|
|
|
|
|
|
|
Profile names are ASCII and match
|
|
|
|
|
`[A-Za-z0-9][A-Za-z0-9._-]{0,63}`, excluding `.` and `..`. The caller selects
|
|
|
|
|
one profile by its exact case-sensitive name; the document has no default
|
|
|
|
|
profile and declaration order never selects one. All configuration strings are
|
|
|
|
|
UTF-8 and NUL-free. Environment map keys and the names following `env:` match
|
|
|
|
|
`[A-Za-z_][A-Za-z0-9_]*`. An environment value is a reference only; literal
|
|
|
|
|
values and other reference schemes are invalid.
|
|
|
|
|
|
|
|
|
|
Host path declarations are absolute or begin with exactly `~/`; only a volume
|
|
|
|
|
`host` may instead begin with exactly `{profile_dir}/`. A declaration rejects an
|
|
|
|
|
empty suffix, an empty component, repeated or trailing separators, `.` or `..`,
|
|
|
|
|
and every other expansion, variable, glob, or shell form. In particular,
|
|
|
|
|
`~//etc` and `{profile_dir}//etc` are invalid. Sandbox paths are normalized
|
|
|
|
|
absolute UTF-8 paths with the same component restrictions; the root path is
|
|
|
|
|
invalid.
|
|
|
|
|
|
|
|
|
|
Persistent paths are pairwise distinct and neither equal nor ancestral in
|
|
|
|
|
either direction. Volume container paths are pairwise distinct and
|
|
|
|
|
non-ancestral. Each volume container path is a strict descendant of exactly one
|
|
|
|
|
persistent path; equality with that path is invalid. Resolution requires an
|
|
|
|
|
internal `SandboxLayoutV1`, whose closed protected-destination set contains
|
|
|
|
|
`/workspace` and every control, credential, mailbox, proc, sys, dev, runtime,
|
|
|
|
|
and other product-owned sandbox mount destination selected by the production
|
|
|
|
|
layout. Persistent and volume paths must not intersect any protected
|
|
|
|
|
destination in either ancestry direction. Configuration semantics do not assign
|
|
|
|
|
destinations other than the specification-fixed `/workspace`; the production
|
|
|
|
|
sandbox-layout constructor owns that complete set and cannot construct a layout
|
|
|
|
|
that omits `/workspace`. A volume source has the declared kind. `create=true` is
|
|
|
|
|
valid only for a directory source anchored strictly beneath `{profile_dir}`; a
|
|
|
|
|
file source is never created. Symlinks, magic links, mount crossings, sockets,
|
|
|
|
|
devices, FIFOs, and other special files cannot satisfy a source.
|
|
|
|
|
|
|
|
|
|
The v1 network language is IPv4-only. Each prefix is parsed, has host bits
|
|
|
|
|
cleared, and is deduplicated. Effective allow prefixes are the union of global
|
|
|
|
|
and selected-profile allows. Effective deny prefixes are the union of global,
|
|
|
|
|
selected-profile, and the three RFC 1918 prefixes. An exact normalized prefix
|
|
|
|
|
present in both sets is invalid; overlaps at different prefix lengths are valid
|
|
|
|
|
and use longest-prefix routing. The Agent Sandbox disables IPv6 for v1.
|
|
|
|
|
|
|
|
|
|
An auto-approval rule is valid only while its profile escalation table is
|
|
|
|
|
enabled. Its executable resolves to a canonical regular executable outside the
|
|
|
|
|
Agent Workspace, every configured volume source, the profile directory, and
|
|
|
|
|
every Lazaret data, runtime, Domain, and control tree. At load and before every
|
|
|
|
|
execution, the object must have exactly one hard link, be owned by root or the
|
|
|
|
|
invoking user, grant no group or other write permission, and be executable by
|
|
|
|
|
the invoking user. Rule arguments are UTF-8, NUL-free strings.
|
|
|
|
|
`allow_extra_args=false` matches only the exact ordered argument list.
|
|
|
|
|
`allow_extra_args=true` requires at least one configured argument and matches
|
|
|
|
|
that nonempty ordered prefix followed by zero or more arguments. Exact duplicate
|
|
|
|
|
normalized rules are invalid.
|
|
|
|
|
|
|
|
|
|
`MailboxRequest.command_argv` is nonempty and every element is UTF-8 and
|
|
|
|
|
NUL-free. Element zero is an absolute path and must be byte-for-byte equal to
|
|
|
|
|
the rule's canonical executable path; elements one onward are the arguments
|
|
|
|
|
matched against `args`. Lazaret performs no `PATH` lookup. The structured v1
|
|
|
|
|
request language has no command-string or shell-expansion form; such an
|
|
|
|
|
unsupported input is `CommandRequiresShell` and cannot auto-approve. The host
|
|
|
|
|
launcher never inserts or interprets a shell. An explicitly configured exact
|
|
|
|
|
vector such as `/bin/sh`, `-c`, and a fixed command string remains a direct
|
|
|
|
|
vector and can match only that exact rule. A configured script remains eligible:
|
|
|
|
|
executing the same opened script object uses ordinary kernel shebang handling
|
|
|
|
|
without turning its arguments into a Lazaret-interpreted shell command.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class TrustedHostConfigurationV1 {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
schema_id
|
|
|
|
|
profiles
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ResolvedDomainConfiguration {
|
|
|
|
|
<<runtime>>
|
|
|
|
|
selected_profile
|
|
|
|
|
domain_id
|
|
|
|
|
configuration_fingerprint
|
|
|
|
|
effective_network_policy
|
|
|
|
|
ephemeral_environment
|
|
|
|
|
confined_authorities
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SandboxLayoutV1 {
|
|
|
|
|
<<runtime>>
|
|
|
|
|
protected_destinations
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ConfigurationFingerprintRecordV1 {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
selected_profile
|
|
|
|
|
storage_root
|
|
|
|
|
runtime_root
|
|
|
|
|
image
|
|
|
|
|
isolate_gitignored
|
|
|
|
|
persistent_dirs
|
|
|
|
|
environment_references
|
|
|
|
|
volumes
|
|
|
|
|
effective_allow_prefixes
|
|
|
|
|
effective_deny_prefixes
|
2026-07-16 20:41:13 +09:00
|
|
|
network_readiness
|
2026-07-14 23:34:56 +09:00
|
|
|
escalation_enabled
|
|
|
|
|
auto_approval_rules
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class EnvironmentReference {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
sandbox_name
|
|
|
|
|
host_name
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ResolvedVolume {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
canonical_host_source
|
|
|
|
|
container_path
|
|
|
|
|
kind
|
|
|
|
|
access
|
|
|
|
|
create
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ResolvedAutoApprovalRule {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
canonical_executable
|
|
|
|
|
args
|
|
|
|
|
allow_extra_args
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-16 20:41:13 +09:00
|
|
|
class ResolvedNetworkReadinessV1 {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
denied
|
|
|
|
|
permitted
|
|
|
|
|
dns
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-14 23:34:56 +09:00
|
|
|
class ConfinedPathPlan {
|
|
|
|
|
<<runtime>>
|
|
|
|
|
retained_ancestor
|
|
|
|
|
ancestor_device
|
|
|
|
|
ancestor_inode
|
|
|
|
|
ancestor_mount_id
|
|
|
|
|
relative_suffix
|
|
|
|
|
canonical_label
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TrustedHostConfigurationV1 --> ResolvedDomainConfiguration : resolves selected profile
|
|
|
|
|
SandboxLayoutV1 --> ResolvedDomainConfiguration : constrains sandbox destinations
|
|
|
|
|
ResolvedDomainConfiguration --> ConfigurationFingerprintRecordV1
|
|
|
|
|
ConfigurationFingerprintRecordV1 --> EnvironmentReference
|
|
|
|
|
ConfigurationFingerprintRecordV1 --> ResolvedVolume
|
|
|
|
|
ConfigurationFingerprintRecordV1 --> ResolvedAutoApprovalRule
|
2026-07-16 20:41:13 +09:00
|
|
|
ConfigurationFingerprintRecordV1 --> ResolvedNetworkReadinessV1
|
2026-07-14 23:34:56 +09:00
|
|
|
ResolvedDomainConfiguration --> ConfinedPathPlan
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`ResolvedDomainConfiguration` is one move-owned, non-serializable value. It is
|
|
|
|
|
the only successful output of loading a selected profile and owns all retained
|
|
|
|
|
path descriptors, normalized selected-profile data, confined use plans, and
|
|
|
|
|
resolved environment values. Resolved environment values have no field in
|
|
|
|
|
`ConfigurationFingerprintRecordV1`; they are never serialized, hashed, logged,
|
|
|
|
|
or persisted. The parsed source and nonselected profiles do not become runtime
|
|
|
|
|
configuration authority.
|
|
|
|
|
|
|
|
|
|
`SandboxLayoutV1` is an internal, non-serializable product value with no public
|
|
|
|
|
unchecked constructor. Configuration resolution cannot succeed without it. Its
|
|
|
|
|
production constructor is owned by sandbox-layout construction and supplies the
|
|
|
|
|
complete normalized protected-destination set; configuration loading neither
|
|
|
|
|
guesses unnamed destinations nor permits a caller to remove `/workspace`. Every
|
|
|
|
|
member is a normalized, absolute, non-root sandbox path using the sandbox-path
|
|
|
|
|
grammar above; the finite set is nonempty and contains no duplicate member.
|
|
|
|
|
|
|
|
|
|
`ConfinedPathPlan` owns a retained ancestor directory descriptor and exposes to
|
|
|
|
|
consumers only its typed device, inode, and mount identity plus a normalized
|
|
|
|
|
relative suffix. `canonical_label` is diagnostic or fingerprint input, not open
|
|
|
|
|
authority. Consumers reopen relative to the retained descriptor and revalidate
|
|
|
|
|
the intended type and identity constraints. They do not receive an ambient
|
|
|
|
|
absolute path with which to repeat authorization.
|
|
|
|
|
|
|
|
|
|
### Domain and configuration digests
|
|
|
|
|
|
|
|
|
|
`DomainIdV1` is the 32-byte SHA-256 digest of the following preimage:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
"lazaret-domain-id-v1\0"
|
|
|
|
|
|| bytes(selected_profile_utf8)
|
|
|
|
|
|| bytes(canonical_workspace_path)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`ConfigurationFingerprintV1` is the 32-byte SHA-256 digest of the following
|
|
|
|
|
canonical record:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
"lazaret-configuration-fingerprint-v1\0"
|
|
|
|
|
|| bytes(selected_profile_utf8)
|
|
|
|
|
|| bytes(canonical_storage_root)
|
|
|
|
|
|| bytes(canonical_runtime_root)
|
|
|
|
|
|| bytes(image_utf8)
|
|
|
|
|
|| boolean(isolate_gitignored)
|
|
|
|
|
|| list(persistent_dirs)
|
|
|
|
|
|| list(environment_reference_records)
|
|
|
|
|
|| list(volume_records)
|
|
|
|
|
|| list(effective_allow_prefixes)
|
|
|
|
|
|| list(effective_deny_prefixes)
|
|
|
|
|
|| boolean(escalation_enabled)
|
|
|
|
|
|| list(auto_approval_rule_records)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The Domain-ID separator is the exact 20 ASCII bytes
|
|
|
|
|
`lazaret-domain-id-v1` followed by one NUL byte. Both variable fields use
|
|
|
|
|
`bytes`; concatenating their unframed bytes is not a valid v1 preimage.
|
|
|
|
|
`bytes(x)` is `u32be(length(x)) || x`; lengths and list counts must fit in
|
|
|
|
|
`u32`. A Boolean is one byte, `0x00` or `0x01`. Each list is
|
|
|
|
|
`u32be(item_count)` followed by `bytes(item_encoding)` for every item. Every
|
|
|
|
|
listed collection is order-independent and sorts complete item encodings by
|
|
|
|
|
unsigned bytewise order before framing, except that arguments inside one
|
|
|
|
|
auto-approval record retain their declared order. Strings use UTF-8 bytes and
|
|
|
|
|
canonical host paths use raw Linux pathname bytes.
|
|
|
|
|
|
|
|
|
|
An environment-reference record is `bytes(sandbox_name) || bytes(host_name)`.
|
|
|
|
|
A persistent-path item is `bytes(path)`, and an argument item is `bytes(arg)`.
|
|
|
|
|
A volume record is `bytes(canonical_host_source) || bytes(container_path) ||
|
|
|
|
|
kind || access || boolean(create)`, where file/directory are `0x00`/`0x01` and
|
|
|
|
|
read-only/read-write are `0x00`/`0x01`. An IPv4 prefix is its four network-order
|
|
|
|
|
address bytes followed by its one-byte prefix length. An auto-approval record is
|
|
|
|
|
`bytes(canonical_executable) || list_in_declared_order(args) ||
|
|
|
|
|
boolean(allow_extra_args)`. A declared-order argument list uses the same list
|
|
|
|
|
framing without sorting.
|
|
|
|
|
|
|
|
|
|
Source comments, TOML declaration order, defaults versus their explicit equal
|
|
|
|
|
values, nonselected profiles, configuration source pathname, host environment
|
|
|
|
|
values, retained descriptor numbers, filesystem inode metadata, and executable
|
|
|
|
|
contents are excluded. Every resolved selected-profile field above is included.
|
|
|
|
|
Neither digest is an authentication credential.
|
2026-07-11 23:33:04 +09:00
|
|
|
|
|
|
|
|
## Domain Store
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
2026-07-14 23:34:56 +09:00
|
|
|
class DomainStore {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
}
|
2026-07-11 23:33:04 +09:00
|
|
|
|
|
|
|
|
class StoreMetadata {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
schema_id
|
|
|
|
|
schema_version
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Domain {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
domain_id
|
|
|
|
|
profile_name
|
|
|
|
|
canonical_workspace
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Generation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
configuration_fingerprint
|
|
|
|
|
coordinator_id
|
|
|
|
|
network_sidecar_id
|
|
|
|
|
sandbox_id
|
|
|
|
|
durable_decision
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Participant {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
generation_id
|
|
|
|
|
role
|
|
|
|
|
state
|
|
|
|
|
ownership
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ParticipantState {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Intent
|
|
|
|
|
LeaseHeld
|
|
|
|
|
Prepared
|
|
|
|
|
Committed
|
|
|
|
|
ReleaseIntent
|
|
|
|
|
Clean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ParticipantOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<union>>
|
|
|
|
|
PreparedLower
|
|
|
|
|
StateAnchor
|
|
|
|
|
GitRouting
|
|
|
|
|
Network
|
|
|
|
|
Helper
|
|
|
|
|
Sandbox
|
|
|
|
|
Publication
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Session {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
generation_id
|
|
|
|
|
session_id
|
|
|
|
|
cli_id
|
|
|
|
|
session_anchor_id
|
|
|
|
|
session_phase
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 01:27:19 +09:00
|
|
|
class SessionTerminal {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
generation_id
|
|
|
|
|
session_id
|
|
|
|
|
state
|
|
|
|
|
container_id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionTerminalState {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Intent
|
|
|
|
|
Running
|
|
|
|
|
ReleaseIntent
|
|
|
|
|
Clean
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-11 23:33:04 +09:00
|
|
|
class Mailbox {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
generation_id
|
|
|
|
|
identity_path
|
|
|
|
|
inbox_path
|
|
|
|
|
outbox_path
|
|
|
|
|
state
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DomainStore "1" *-- "1" StoreMetadata
|
|
|
|
|
DomainStore "1" *-- "1" Domain
|
|
|
|
|
Domain "1" --> "0..*" Generation
|
|
|
|
|
Generation "1" --> "0..*" Participant
|
|
|
|
|
Participant --> ParticipantState
|
2026-07-14 01:46:58 +09:00
|
|
|
Participant --> "0..1" ParticipantOwnership
|
2026-07-11 23:33:04 +09:00
|
|
|
Generation "1" --> "0..*" Session
|
2026-07-12 01:27:19 +09:00
|
|
|
Session "1" --> "0..1" SessionTerminal
|
|
|
|
|
SessionTerminal --> SessionTerminalState
|
2026-07-11 23:33:04 +09:00
|
|
|
Generation "1" --> "0..1" Mailbox
|
|
|
|
|
Mailbox --> ParticipantState
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`durable_decision` and `session_phase` contain values defined by the application
|
|
|
|
|
protocol model. This schema records them without redefining either state machine.
|
2026-07-14 01:46:58 +09:00
|
|
|
Each store carries its own schema identity and version. The current Domain Store
|
2026-07-15 14:01:46 +09:00
|
|
|
identity is `lazaret-domain-store-v1` with version `1`. Unknown, unversioned,
|
|
|
|
|
older, and newer metadata refuses before any row is interpreted. The
|
2026-07-14 01:46:58 +09:00
|
|
|
Storage Catalog remains `lazaret-storage-catalog-v1` with version `1`.
|
|
|
|
|
|
|
|
|
|
### Host process identity and staged ownership
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class PidfsProcessAuthorityV1 {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
boot_id
|
|
|
|
|
pidfs_st_dev
|
|
|
|
|
pidfs_st_ino
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PidfsProcessIdentityV1 {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
host_pid
|
|
|
|
|
start_time_ticks
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class HostProcessIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-15 14:01:46 +09:00
|
|
|
identity
|
2026-07-14 01:46:58 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PersistedHostProcessOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
<<union>>
|
|
|
|
|
Unassigned
|
|
|
|
|
Staged
|
|
|
|
|
Committed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class HostProcessOwnershipSlot {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
SandboxHostCoordinator
|
|
|
|
|
SandboxRuntimeSupervisor
|
|
|
|
|
SandboxAttachedRunsc
|
|
|
|
|
StateAnchorDaemon
|
|
|
|
|
GitRoutingDaemon
|
|
|
|
|
NetworkRuntimeSupervisor
|
|
|
|
|
HelperConnectivityHelper
|
|
|
|
|
HelperRuntimeSupervisor
|
|
|
|
|
SessionTerminalHostCoordinator
|
|
|
|
|
SessionTerminalExecClient
|
|
|
|
|
EscalationHostProcess
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProcessOwnershipMessageVersion {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
V1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class StagedProcessOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
version
|
|
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
coordinator_id
|
|
|
|
|
slot
|
|
|
|
|
identity
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProcessOwnershipCommitAck {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
version
|
|
|
|
|
committed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PidfsProcessIdentityV1 --> PidfsProcessAuthorityV1 : authority
|
2026-07-15 14:01:46 +09:00
|
|
|
HostProcessIdentity --> PidfsProcessIdentityV1 : current authority
|
2026-07-14 01:46:58 +09:00
|
|
|
PersistedHostProcessOwnership --> PidfsProcessIdentityV1 : Staged
|
|
|
|
|
PersistedHostProcessOwnership --> HostProcessIdentity : Committed
|
|
|
|
|
StagedProcessOwnership --> ProcessOwnershipMessageVersion
|
|
|
|
|
StagedProcessOwnership --> HostProcessOwnershipSlot
|
|
|
|
|
StagedProcessOwnership --> PidfsProcessIdentityV1
|
|
|
|
|
ProcessOwnershipCommitAck --> ProcessOwnershipMessageVersion
|
|
|
|
|
ProcessOwnershipCommitAck --> StagedProcessOwnership : committed
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`boot_id` is the canonical 16-byte UUID value from the current Linux boot ID;
|
|
|
|
|
`pidfs_st_dev` and `pidfs_st_ino` are distinct unsigned 64-bit pidfs types. Only
|
|
|
|
|
their typed `PidfsProcessAuthorityV1` tuple is positive durable authority.
|
|
|
|
|
`host_pid` is an unsigned 32-bit host-PID-namespace locator and
|
|
|
|
|
`start_time_ticks` is unsigned 64-bit negative evidence. Equality of the latter
|
|
|
|
|
two fields cannot produce or upgrade authority.
|
|
|
|
|
|
|
|
|
|
Every persisted host-process edge uses `PersistedHostProcessOwnership`.
|
|
|
|
|
`Unassigned` records that no process ownership has been acquired. `Staged`
|
|
|
|
|
contains only a current pidfs identity. It is positive authority for exact
|
|
|
|
|
same-handle cleanup and `PidfsRecoveryMatch`, including bootstrap recovery, but
|
|
|
|
|
cannot satisfy readiness, publication, dependent-resource creation, or
|
2026-07-15 14:01:46 +09:00
|
|
|
adoption. `Committed` contains the current pidfs identity and is the only
|
|
|
|
|
serviceable process-ownership phase.
|
2026-07-14 01:46:58 +09:00
|
|
|
|
|
|
|
|
Participant `Intent` and `ReleaseIntent` may retain any process-slot phase.
|
|
|
|
|
Every active participant state and Session Terminal `Running` requires current
|
|
|
|
|
committed ownership in every role-required process slot. `Clean` requires every
|
|
|
|
|
process slot to be `Unassigned`.
|
|
|
|
|
|
|
|
|
|
`StagedProcessOwnership` binds one acquisition to its Domain, generation,
|
|
|
|
|
generation-scoped Session Coordinator ID, exact ownership slot, and complete
|
|
|
|
|
pidfs identity. `ProcessOwnershipCommitAck.committed` echoes that exact staged
|
|
|
|
|
value. The receiver accepts one matching v1 acknowledgment only while that
|
|
|
|
|
exact launch barrier is pending on the authenticated generation channel. A
|
|
|
|
|
mismatched, duplicated after release, unknown-version, lost, or unauthenticated
|
|
|
|
|
acknowledgment cannot release a barrier. These shapes define correlation and
|
|
|
|
|
the durable boundary; they do not select the authentication or transport codec.
|
2026-07-11 23:33:04 +09:00
|
|
|
|
2026-07-12 01:27:19 +09:00
|
|
|
### Session terminal ownership
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class SessionTerminal {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
generation_id
|
|
|
|
|
session_id
|
|
|
|
|
state
|
|
|
|
|
container_id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PtyIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
master_fd
|
|
|
|
|
device
|
|
|
|
|
inode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class GuestProcessIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
leader_pid
|
|
|
|
|
leader_start_time
|
|
|
|
|
process_group_id
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-14 01:46:58 +09:00
|
|
|
SessionTerminal --> PersistedHostProcessOwnership : host_coordinator
|
2026-07-12 01:27:19 +09:00
|
|
|
SessionTerminal --> PtyIdentity : pty_master
|
2026-07-14 01:46:58 +09:00
|
|
|
SessionTerminal --> PersistedHostProcessOwnership : exec_client
|
2026-07-12 01:27:19 +09:00
|
|
|
SessionTerminal --> GuestProcessIdentity : guest_process
|
|
|
|
|
```
|
|
|
|
|
|
2026-07-14 01:46:58 +09:00
|
|
|
Host process ownership uses the phase-aware pidfs dispatch above. Guest
|
|
|
|
|
process identity uses the leader PID and start time observed inside the exact
|
|
|
|
|
generation-bound runsc container; its process-group ID is relative to that
|
|
|
|
|
container's root PID namespace and never converts to host process authority.
|
2026-07-12 01:27:19 +09:00
|
|
|
The PTY identity is exact only in combination with its Host Coordinator process
|
|
|
|
|
identity. `SessionTerminalState` is a physical recovery state below the
|
|
|
|
|
application protocol model; it does not redefine `session_phase`.
|
|
|
|
|
|
2026-07-14 01:46:58 +09:00
|
|
|
`SessionTerminal=Intent` permits partial acquisition: `container_id`,
|
|
|
|
|
`pty_master`, and `guest_process` are optional, while both process slots use the
|
|
|
|
|
three-phase ownership union. `Running` requires all three non-process identities
|
|
|
|
|
and current committed HC and exec-client ownership. `ReleaseIntent` retains all
|
|
|
|
|
recorded evidence, including staged current pidfs authority. `Clean` requires
|
|
|
|
|
all three optional identities absent and both process slots unassigned. A bare
|
|
|
|
|
Intent may become this explicit cleared snapshot only after runtime absence is
|
|
|
|
|
proven.
|
|
|
|
|
|
2026-07-12 01:27:19 +09:00
|
|
|
## Session terminal protocol
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class SessionTerminalEvent {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
<<union>>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TerminalInput {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
session_id
|
|
|
|
|
bytes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TerminalResize {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
session_id
|
|
|
|
|
rows
|
|
|
|
|
columns
|
|
|
|
|
pixel_width
|
|
|
|
|
pixel_height
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TerminalSignal {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
session_id
|
|
|
|
|
signal
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TerminalSignalKind {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Interrupt
|
|
|
|
|
Quit
|
|
|
|
|
Suspend
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionClose {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
session_id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionTerminalMessage {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
<<union>>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TerminalOutput {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
session_id
|
|
|
|
|
bytes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionExit {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
session_id
|
|
|
|
|
outcome
|
|
|
|
|
exit_code
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionExitOutcome {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 01:27:19 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Exited
|
|
|
|
|
Terminated
|
|
|
|
|
RuntimeLost
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-16 16:28:18 +09:00
|
|
|
class NonInteractiveSessionRequest {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
protocol_version
|
|
|
|
|
session_id
|
|
|
|
|
argv
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NonInteractiveOutput {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
session_id
|
|
|
|
|
bytes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NonInteractiveSessionMessage {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
<<union>>
|
|
|
|
|
Stdout
|
|
|
|
|
Stderr
|
|
|
|
|
Exit
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-17 06:59:39 +09:00
|
|
|
class InteractiveSessionRequest {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
protocol_version
|
|
|
|
|
session_id
|
|
|
|
|
argv
|
|
|
|
|
initial_size
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class InteractiveSessionEvent {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
<<union>>
|
|
|
|
|
Terminal
|
|
|
|
|
PromptDecision
|
|
|
|
|
Poll
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TerminalPrompt {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
session_id
|
|
|
|
|
request_id
|
|
|
|
|
request_sha256
|
|
|
|
|
agent_profile
|
|
|
|
|
command_argv
|
|
|
|
|
justification
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class InteractiveSessionMessage {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
<<union>>
|
|
|
|
|
Terminal
|
|
|
|
|
Prompt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class InteractiveSessionBatch {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
session_id
|
|
|
|
|
messages
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 01:27:19 +09:00
|
|
|
SessionTerminalEvent --> TerminalInput
|
|
|
|
|
SessionTerminalEvent --> TerminalResize
|
|
|
|
|
SessionTerminalEvent --> TerminalSignal
|
|
|
|
|
SessionTerminalEvent --> SessionClose
|
|
|
|
|
TerminalSignal --> TerminalSignalKind
|
|
|
|
|
SessionTerminalMessage --> TerminalOutput
|
|
|
|
|
SessionTerminalMessage --> SessionExit
|
|
|
|
|
SessionExit --> SessionExitOutcome
|
2026-07-16 16:28:18 +09:00
|
|
|
NonInteractiveSessionMessage --> NonInteractiveOutput : Stdout / Stderr
|
|
|
|
|
NonInteractiveSessionMessage --> SessionExit : Exit
|
2026-07-17 06:59:39 +09:00
|
|
|
InteractiveSessionRequest --> TerminalResize : initial_size
|
|
|
|
|
InteractiveSessionEvent --> SessionTerminalEvent : Terminal
|
|
|
|
|
InteractiveSessionMessage --> SessionTerminalMessage : Terminal
|
|
|
|
|
InteractiveSessionMessage --> TerminalPrompt : Prompt
|
|
|
|
|
InteractiveSessionBatch --> InteractiveSessionMessage
|
2026-07-12 01:27:19 +09:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`exit_code` is present only for `Exited` and is the status collected from the
|
|
|
|
|
non-detached runsc exec client. Interactive PTY output is one merged byte stream;
|
2026-07-12 03:08:09 +09:00
|
|
|
it does not preserve stdout and stderr as separate channels.
|
|
|
|
|
|
|
|
|
|
## Protocol cryptography
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class GenerationIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
agent_profile
|
|
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
configuration_fingerprint
|
|
|
|
|
coordinator_id
|
|
|
|
|
sandbox_id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TrustManifest {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
generation_identity
|
|
|
|
|
tls_ca_sha256
|
|
|
|
|
protocol_issuer_public_key
|
|
|
|
|
issuer_signature
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TlsCredential {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
generation_identity
|
|
|
|
|
role
|
|
|
|
|
subject_id
|
|
|
|
|
certificate_der
|
|
|
|
|
certificate_sha256
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProtocolPublicationIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
generation_identity
|
|
|
|
|
tls_ca_certificate_der
|
|
|
|
|
trust_manifest_sha256
|
|
|
|
|
coordinator_tls_certificate_sha256
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-15 17:54:46 +09:00
|
|
|
class ClientEnrollmentRequest {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
protocol_version
|
|
|
|
|
generation_identity
|
|
|
|
|
cli_id
|
|
|
|
|
certificate_signing_request_der
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ClientEnrollmentResponse {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
protocol_version
|
|
|
|
|
credential
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionRegistrationRequest {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionRegistrationResponse {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
protocol_version
|
|
|
|
|
session_capability
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ControlRequest {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
<<union>>
|
|
|
|
|
Enroll
|
|
|
|
|
Register
|
2026-07-16 16:28:18 +09:00
|
|
|
Execute
|
2026-07-17 06:59:39 +09:00
|
|
|
ExecuteInteractive
|
2026-07-15 17:54:46 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ControlResponse {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
<<union>>
|
|
|
|
|
Enrolled
|
|
|
|
|
Registered
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-12 03:08:09 +09:00
|
|
|
class SandboxCredentialBundle {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
generation_identity
|
|
|
|
|
trust_manifest
|
|
|
|
|
coordinator_protocol_credential
|
|
|
|
|
sandbox_protocol_credential
|
|
|
|
|
sandbox_private_key
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class TlsRole {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
SessionCoordinator
|
|
|
|
|
ClientCLI
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProtocolCredential {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
credential_id
|
|
|
|
|
generation_identity
|
|
|
|
|
role
|
|
|
|
|
subject_id
|
|
|
|
|
public_key
|
|
|
|
|
issuer_signature
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ProtocolCredentialRole {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
SessionCoordinator
|
|
|
|
|
AgentSandbox
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionBinding {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
generation_identity
|
|
|
|
|
cli_id
|
|
|
|
|
session_id
|
|
|
|
|
session_anchor_public_key
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SessionRequestCapability {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
capability_id
|
|
|
|
|
session_binding
|
|
|
|
|
coordinator_credential_id
|
|
|
|
|
sandbox_credential_id
|
|
|
|
|
coordinator_signature
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TrustManifest --> GenerationIdentity
|
|
|
|
|
TlsCredential --> TlsRole
|
|
|
|
|
TlsCredential --> GenerationIdentity
|
|
|
|
|
ProtocolPublicationIdentity --> GenerationIdentity
|
|
|
|
|
ProtocolPublicationIdentity --> TrustManifest
|
|
|
|
|
ProtocolPublicationIdentity --> TlsCredential : coordinator TLS leaf
|
2026-07-15 17:54:46 +09:00
|
|
|
ClientEnrollmentRequest --> GenerationIdentity
|
|
|
|
|
ClientEnrollmentResponse --> TlsCredential
|
|
|
|
|
SessionRegistrationRequest --> SessionBinding
|
|
|
|
|
SessionRegistrationResponse --> SessionRequestCapability
|
|
|
|
|
ControlRequest --> ClientEnrollmentRequest : Enroll
|
|
|
|
|
ControlRequest --> SessionRegistrationRequest : Register
|
2026-07-16 16:28:18 +09:00
|
|
|
ControlRequest --> NonInteractiveSessionRequest : Execute
|
2026-07-15 17:54:46 +09:00
|
|
|
ControlResponse --> ClientEnrollmentResponse : Enrolled
|
|
|
|
|
ControlResponse --> SessionRegistrationResponse : Registered
|
2026-07-12 03:08:09 +09:00
|
|
|
SandboxCredentialBundle --> GenerationIdentity
|
|
|
|
|
SandboxCredentialBundle --> TrustManifest
|
|
|
|
|
SandboxCredentialBundle --> ProtocolCredential : coordinator verifier
|
|
|
|
|
SandboxCredentialBundle --> ProtocolCredential : sandbox signer
|
|
|
|
|
ProtocolCredential --> GenerationIdentity
|
|
|
|
|
ProtocolCredential --> ProtocolCredentialRole
|
|
|
|
|
SessionBinding --> GenerationIdentity
|
|
|
|
|
SessionRequestCapability --> SessionBinding
|
|
|
|
|
SessionRequestCapability --> ProtocolCredential : coordinator signer
|
|
|
|
|
SessionRequestCapability --> ProtocolCredential : sandbox subject
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Trust Manifests, credentials, capabilities, and private keys are ephemeral
|
|
|
|
|
protocol material, not Domain Store records.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class SignedProtocolRecord {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
<<union>>
|
|
|
|
|
payload_bytes
|
|
|
|
|
signature
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MailboxRequest {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
request_id
|
|
|
|
|
session_capability
|
|
|
|
|
sandbox_credential_id
|
|
|
|
|
command_argv
|
|
|
|
|
justification
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MailboxCancellation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
request_id
|
|
|
|
|
session_capability
|
|
|
|
|
sandbox_credential_id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MailboxResultAck {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
request_id
|
|
|
|
|
request_sha256
|
|
|
|
|
session_capability
|
|
|
|
|
sandbox_credential_id
|
|
|
|
|
highest_contiguous_sequence
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DeveloperDecision {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
request_id
|
|
|
|
|
request_sha256
|
|
|
|
|
decision
|
|
|
|
|
approved_command_argv
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DeveloperDecisionKind {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Approve
|
|
|
|
|
Deny
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MailboxResult {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
request_id
|
|
|
|
|
request_sha256
|
|
|
|
|
coordinator_credential_id
|
|
|
|
|
outcome
|
|
|
|
|
exit_code
|
|
|
|
|
chunk_count
|
|
|
|
|
stdout_sha256
|
|
|
|
|
stderr_sha256
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MailboxResultChunk {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
protocol_version
|
|
|
|
|
session_binding
|
|
|
|
|
request_id
|
|
|
|
|
request_sha256
|
|
|
|
|
coordinator_credential_id
|
|
|
|
|
sequence
|
|
|
|
|
stream
|
|
|
|
|
bytes
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ResultStream {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Stdout
|
|
|
|
|
Stderr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class EscalationOutcome {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-12 03:08:09 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Completed
|
|
|
|
|
Denied
|
|
|
|
|
TimedOut
|
|
|
|
|
Cancelled
|
|
|
|
|
Failed
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SignedProtocolRecord --> MailboxRequest
|
|
|
|
|
SignedProtocolRecord --> MailboxCancellation
|
|
|
|
|
SignedProtocolRecord --> MailboxResultAck
|
|
|
|
|
SignedProtocolRecord --> DeveloperDecision
|
|
|
|
|
SignedProtocolRecord --> MailboxResult
|
|
|
|
|
SignedProtocolRecord --> MailboxResultChunk
|
|
|
|
|
MailboxRequest --> SessionBinding
|
|
|
|
|
MailboxRequest --> SessionRequestCapability
|
|
|
|
|
MailboxCancellation --> SessionBinding
|
|
|
|
|
MailboxCancellation --> SessionRequestCapability
|
|
|
|
|
MailboxResultAck --> SessionBinding
|
|
|
|
|
MailboxResultAck --> SessionRequestCapability
|
|
|
|
|
DeveloperDecision --> SessionBinding
|
|
|
|
|
DeveloperDecision --> DeveloperDecisionKind
|
|
|
|
|
MailboxResult --> SessionBinding
|
|
|
|
|
MailboxResult --> EscalationOutcome
|
|
|
|
|
MailboxResultChunk --> SessionBinding
|
|
|
|
|
MailboxResultChunk --> ResultStream
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`SessionCoordinator` is the logical protocol identity served physically by the
|
|
|
|
|
Host Coordinator. It is not a distinct Host Coordinator principal. Physical
|
|
|
|
|
encoding, signing, size, and validation rules are defined by the specification.
|
2026-07-12 01:27:19 +09:00
|
|
|
|
2026-07-15 15:55:08 +09:00
|
|
|
For embedded signed claims, the field order shown above is the Postcard field
|
|
|
|
|
order. A protocol credential ID is SHA-256 over the minimally encoded claim
|
|
|
|
|
fields excluding `credential_id` and `issuer_signature`. A Session Request
|
|
|
|
|
Capability ID is SHA-256 over the minimally encoded claim fields excluding
|
|
|
|
|
`capability_id` and `coordinator_signature`. A Trust Manifest digest is SHA-256
|
|
|
|
|
over the complete minimally encoded manifest, including its issuer signature.
|
|
|
|
|
The manifest issuer signs its minimally encoded fields excluding
|
|
|
|
|
`issuer_signature`.
|
|
|
|
|
|
|
|
|
|
Every signature input is the ASCII `lazaret/v1/` prefix plus the lower-kebab
|
|
|
|
|
record name, followed by the unsigned 64-bit big-endian payload length and the
|
|
|
|
|
exact payload bytes. Mailbox signatures use the bytes carried in
|
|
|
|
|
`SignedProtocolRecord`; verification occurs before decoding those payload bytes.
|
|
|
|
|
Result stream digests are SHA-256 over the ordered concatenation of bytes for
|
|
|
|
|
that stream.
|
|
|
|
|
|
2026-07-11 23:33:04 +09:00
|
|
|
### Participant ownership
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class ParticipantOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<union>>
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NamespaceIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
device
|
|
|
|
|
inode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class MountIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
mount_id
|
|
|
|
|
device
|
|
|
|
|
inode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PreparedLowerOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
optional prepared_artifact_id
|
|
|
|
|
optional source_identity
|
|
|
|
|
optional lease_state
|
|
|
|
|
optional path
|
|
|
|
|
optional device
|
|
|
|
|
optional inode
|
2026-07-17 05:38:43 +09:00
|
|
|
optional released_state_anchor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class StateAnchorReleaseEvidence {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
daemon
|
|
|
|
|
user_namespace
|
|
|
|
|
mount_namespace
|
|
|
|
|
mount
|
2026-07-11 23:33:04 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class StateAnchorOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
optional lower_artifact_id
|
|
|
|
|
optional upper_path
|
|
|
|
|
optional work_path
|
|
|
|
|
optional merged_path
|
2026-07-11 23:33:04 +09:00
|
|
|
daemon
|
2026-07-14 01:46:58 +09:00
|
|
|
optional mount
|
2026-07-11 23:33:04 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class GitRoutingOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
optional mountpoint
|
|
|
|
|
optional host_root
|
|
|
|
|
optional isolated_root
|
2026-07-11 23:33:04 +09:00
|
|
|
daemon
|
2026-07-14 01:46:58 +09:00
|
|
|
optional mount
|
2026-07-11 23:33:04 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NetworkOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
optional derived_policy_digest
|
|
|
|
|
optional readiness_fingerprint
|
|
|
|
|
optional readiness_evidence
|
|
|
|
|
optional namespace
|
2026-07-11 23:33:04 +09:00
|
|
|
runtime_supervisor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class HelperOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
optional network_sidecar_id
|
2026-07-11 23:33:04 +09:00
|
|
|
connectivity_helper
|
|
|
|
|
runtime_supervisor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class SandboxOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-14 01:46:58 +09:00
|
|
|
optional container_id
|
|
|
|
|
optional runtime_root
|
2026-07-17 06:48:49 +09:00
|
|
|
optional runtime_root_identity
|
2026-07-14 01:46:58 +09:00
|
|
|
optional bundle_digest
|
2026-07-11 23:33:04 +09:00
|
|
|
host_coordinator
|
|
|
|
|
runtime_supervisor
|
|
|
|
|
attached_runsc
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PublicationOwnership {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-17 06:48:49 +09:00
|
|
|
optional staged_socket_path
|
|
|
|
|
optional staged_identity_path
|
2026-07-14 01:46:58 +09:00
|
|
|
optional socket_path
|
|
|
|
|
optional identity_path
|
2026-07-17 06:48:49 +09:00
|
|
|
optional socket_identity
|
|
|
|
|
optional identity_file_identity
|
2026-07-11 23:33:04 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ParticipantOwnership --> PreparedLowerOwnership
|
2026-07-17 05:38:43 +09:00
|
|
|
PreparedLowerOwnership --> StateAnchorReleaseEvidence : released_state_anchor
|
|
|
|
|
StateAnchorReleaseEvidence --> PersistedHostProcessOwnership : daemon
|
|
|
|
|
StateAnchorReleaseEvidence --> NamespaceIdentity : user_namespace
|
|
|
|
|
StateAnchorReleaseEvidence --> NamespaceIdentity : mount_namespace
|
|
|
|
|
StateAnchorReleaseEvidence --> MountIdentity : mount
|
2026-07-11 23:33:04 +09:00
|
|
|
ParticipantOwnership --> StateAnchorOwnership
|
|
|
|
|
ParticipantOwnership --> GitRoutingOwnership
|
|
|
|
|
ParticipantOwnership --> NetworkOwnership
|
|
|
|
|
ParticipantOwnership --> HelperOwnership
|
|
|
|
|
ParticipantOwnership --> SandboxOwnership
|
|
|
|
|
ParticipantOwnership --> PublicationOwnership
|
2026-07-14 01:46:58 +09:00
|
|
|
StateAnchorOwnership --> PersistedHostProcessOwnership : daemon
|
2026-07-11 23:33:04 +09:00
|
|
|
StateAnchorOwnership --> MountIdentity : mount
|
2026-07-14 01:46:58 +09:00
|
|
|
GitRoutingOwnership --> PersistedHostProcessOwnership : daemon
|
2026-07-11 23:33:04 +09:00
|
|
|
GitRoutingOwnership --> MountIdentity : mount
|
|
|
|
|
NetworkOwnership --> NamespaceIdentity : namespace
|
2026-07-14 01:46:58 +09:00
|
|
|
NetworkOwnership --> PersistedHostProcessOwnership : runtime_supervisor
|
2026-07-11 23:33:04 +09:00
|
|
|
NetworkOwnership --> NetworkReadinessEvidence : readiness_evidence
|
2026-07-14 01:46:58 +09:00
|
|
|
HelperOwnership --> PersistedHostProcessOwnership : connectivity_helper
|
|
|
|
|
HelperOwnership --> PersistedHostProcessOwnership : runtime_supervisor
|
|
|
|
|
SandboxOwnership --> PersistedHostProcessOwnership : host_coordinator
|
|
|
|
|
SandboxOwnership --> PersistedHostProcessOwnership : runtime_supervisor
|
|
|
|
|
SandboxOwnership --> PersistedHostProcessOwnership : attached_runsc
|
2026-07-11 23:33:04 +09:00
|
|
|
```
|
|
|
|
|
|
2026-07-14 01:46:58 +09:00
|
|
|
`Participant.ownership=None` is the single encoding of a bare role-bound
|
|
|
|
|
Intent. Once a role snapshot exists it never returns to `None`. `Intent` admits
|
|
|
|
|
a non-empty partial matching snapshot. `ReleaseIntent` admits a non-empty
|
|
|
|
|
partial or complete matching snapshot and retains every exact acquired value.
|
|
|
|
|
`Clean` requires a matching explicit empty snapshot: all optional physical
|
|
|
|
|
fields are absent and all process slots are unassigned. This distinguishes
|
|
|
|
|
"nothing acquired yet" from "absence was proved and cleanup committed."
|
|
|
|
|
|
|
|
|
|
The only serviceable role/state pairs are:
|
|
|
|
|
|
|
|
|
|
| Role | Active state | Required physical evidence |
|
|
|
|
|
|---|---|---|
|
|
|
|
|
| `PreparedLower` | `LeaseHeld` | artifact ID, source, `lease_state=LeaseHeld`, path, device, inode |
|
|
|
|
|
| `StateAnchor` | `Prepared` | lower artifact, three paths, mount, current committed daemon |
|
|
|
|
|
| `GitRouting` | `Prepared` | three paths, mount, current committed daemon |
|
|
|
|
|
| `Network` | `Committed` | policy digest, fingerprint, readiness evidence, namespace, current committed RS |
|
|
|
|
|
| `Helper` | `Committed` | sidecar ID, current committed helper and RS |
|
2026-07-17 06:48:49 +09:00
|
|
|
| `Sandbox` | `Committed` | container, runtime root and exact mount/device/inode identity, bundle digest, current committed HC, RS, and runsc |
|
|
|
|
|
| `Publication` | `Committed` | staged and exposed fixed labels plus exact socket and identity-file mount/device/inode identities |
|
2026-07-14 01:46:58 +09:00
|
|
|
|
|
|
|
|
Network readiness evidence must name the enclosing Participant generation and
|
|
|
|
|
match its policy digest, fingerprint, namespace, and committed RS identity.
|
|
|
|
|
|
|
|
|
|
Intent acquisition is monotonic: optional fields move only absent-to-present,
|
|
|
|
|
and newly acquired child slots move only `Unassigned` to `Staged` to exact
|
|
|
|
|
matching current `Committed`. A current committed owner or supervisor may
|
2026-07-15 14:22:43 +09:00
|
|
|
enter a newly created dependent-role snapshot directly and is then immutable.
|
|
|
|
|
Recorded evidence cannot be replaced or cleared. A transition to ReleaseIntent
|
2026-07-17 05:38:43 +09:00
|
|
|
preserves all evidence. PreparedLower changes its lease phase to
|
|
|
|
|
`ReleaseIntent` and may atomically add the exact released State Anchor daemon,
|
|
|
|
|
user namespace, mount namespace, and mount evidence needed to resume physical
|
|
|
|
|
release. That release evidence is immutable within ReleaseIntent. ReleaseIntent
|
|
|
|
|
becomes Clean only after independent absence proof and atomically clears every
|
|
|
|
|
physical field. A bare Intent may become Clean only after the same sealed
|
|
|
|
|
runtime-absence check.
|
2026-07-14 01:46:58 +09:00
|
|
|
|
|
|
|
|
The direct existing-process edges are Network RS, Helper RS, Sandbox HC, and
|
|
|
|
|
Session Terminal HC. State Anchor daemon, Git-routing daemon, Helper process,
|
|
|
|
|
Sandbox RS, attached runsc, and Session Terminal exec client are acquired child
|
|
|
|
|
edges and require staging.
|
|
|
|
|
No bare Intent moves directly to an active state. PreparedLower must also move
|
|
|
|
|
from recorded `lease_state=Intent` to `LeaseHeld`; it cannot acquire the catalog
|
|
|
|
|
lease from an absent lease phase.
|
|
|
|
|
|
2026-07-11 23:33:04 +09:00
|
|
|
## Storage Catalog
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
2026-07-14 23:34:56 +09:00
|
|
|
class StorageCatalog {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
}
|
2026-07-11 23:33:04 +09:00
|
|
|
|
|
|
|
|
class StoreMetadata {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
schema_id
|
|
|
|
|
schema_version
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PreparedArtifact {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
prepared_artifact_id
|
|
|
|
|
source_identity
|
|
|
|
|
selected_manifest_digest
|
|
|
|
|
policy_id
|
|
|
|
|
id_map_digest
|
|
|
|
|
path
|
|
|
|
|
device
|
|
|
|
|
inode
|
|
|
|
|
state
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ArtifactState {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Available
|
|
|
|
|
Reclaiming
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class ArtifactLease {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
prepared_artifact_id
|
|
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PrepareOperation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
operation_id
|
|
|
|
|
expected_artifact_id
|
|
|
|
|
source_identity
|
2026-07-15 15:22:02 +09:00
|
|
|
selected_manifest_digest
|
|
|
|
|
policy_id
|
|
|
|
|
id_map_digest
|
2026-07-11 23:33:04 +09:00
|
|
|
stage_path
|
2026-07-15 15:22:02 +09:00
|
|
|
stage_state
|
2026-07-11 23:33:04 +09:00
|
|
|
device
|
|
|
|
|
inode
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-15 15:22:02 +09:00
|
|
|
class PrepareStageState {
|
|
|
|
|
<<serialized>>
|
|
|
|
|
<<enumeration>>
|
|
|
|
|
Intent
|
|
|
|
|
Owned
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-11 23:33:04 +09:00
|
|
|
StorageCatalog "1" *-- "1" StoreMetadata
|
|
|
|
|
StorageCatalog "1" *-- "0..*" PreparedArtifact
|
|
|
|
|
StorageCatalog "1" *-- "0..*" ArtifactLease
|
|
|
|
|
StorageCatalog "1" *-- "0..*" PrepareOperation
|
|
|
|
|
PreparedArtifact --> ArtifactState
|
|
|
|
|
PreparedArtifact "1" --> "0..*" ArtifactLease
|
|
|
|
|
PrepareOperation "0..*" --> "0..1" PreparedArtifact : publishes
|
2026-07-15 15:22:02 +09:00
|
|
|
PrepareOperation --> PrepareStageState
|
2026-07-11 23:33:04 +09:00
|
|
|
```
|
|
|
|
|
|
2026-07-15 15:22:02 +09:00
|
|
|
A prepare operation is durably recorded with `stage_state=Intent` and absent
|
|
|
|
|
device/inode evidence before its stage is created. The exact same operation then
|
|
|
|
|
moves to `Owned` with both values present. Only an owned operation can publish or
|
|
|
|
|
authorize exact abandoned-stage recovery.
|
|
|
|
|
|
2026-07-11 23:33:04 +09:00
|
|
|
An artifact lease identifies one prepared artifact, Domain, and generation. Its
|
|
|
|
|
Domain and generation fields correspond to a Domain Store generation; the stores
|
|
|
|
|
do not form one transactional database.
|
|
|
|
|
|
|
|
|
|
`ReleaseIntent` is a physical recovery state. It does not redefine the modeled
|
|
|
|
|
lease lifecycle: the specification defines how Domain Store release intent,
|
|
|
|
|
physical unmount, and Storage Catalog lease removal refine model unmount and
|
2026-07-12 01:27:19 +09:00
|
|
|
release actions. After Host Coordinator loss, the exact Runtime Supervisor may
|
|
|
|
|
unmount under the retained Prepared ownership record, but the Artifact Lease
|
|
|
|
|
remains until bootstrap Host Coordinator recovery records release intent.
|
2026-07-11 23:33:04 +09:00
|
|
|
|
|
|
|
|
## Derived network policy
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class DerivedNetworkPolicy {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
schema_id
|
|
|
|
|
address_families
|
|
|
|
|
default_actions
|
|
|
|
|
prefix_rules
|
|
|
|
|
resolvers
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AddressFamilyDisposition {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
family
|
|
|
|
|
disposition
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DefaultAction {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
family
|
|
|
|
|
action
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PrefixRule {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
family
|
|
|
|
|
network
|
|
|
|
|
action
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Resolver {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
family
|
|
|
|
|
address
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class AddressFamily {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
IPv4
|
|
|
|
|
IPv6
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PolicyAction {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
Allow
|
|
|
|
|
Deny
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DerivedNetworkPolicy "1" *-- "2" AddressFamilyDisposition
|
|
|
|
|
DerivedNetworkPolicy "1" *-- "1..2" DefaultAction
|
|
|
|
|
DerivedNetworkPolicy "1" *-- "0..*" PrefixRule
|
|
|
|
|
DerivedNetworkPolicy "1" *-- "1..*" Resolver
|
|
|
|
|
AddressFamilyDisposition --> AddressFamily
|
|
|
|
|
DefaultAction --> AddressFamily
|
|
|
|
|
DefaultAction --> PolicyAction
|
|
|
|
|
PrefixRule --> AddressFamily
|
|
|
|
|
PrefixRule --> PolicyAction
|
|
|
|
|
Resolver --> AddressFamily
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The policy has exactly one disposition for each address family. Each enabled
|
|
|
|
|
family has exactly one default action. Prefixes and addresses are canonical, and
|
|
|
|
|
equal-prefix action conflicts are invalid. Policy identity is the SHA-256 digest
|
|
|
|
|
of its canonical form with a schema-specific domain separator.
|
|
|
|
|
|
2026-07-15 16:58:30 +09:00
|
|
|
`DerivedNetworkPolicy.schema_id` is exactly
|
|
|
|
|
`lazaret-derived-network-policy-v1`. Its canonical form is the minimal Postcard
|
|
|
|
|
encoding of the complete document after address-family dispositions, default
|
|
|
|
|
actions, prefix rules, and resolvers are sorted respectively by family; family;
|
|
|
|
|
`(family, address bytes, prefix length, action)`; and `(family, address bytes)`.
|
|
|
|
|
Duplicate prefixes and resolvers are invalid rather than silently removed. The
|
|
|
|
|
policy-digest domain separator is the UTF-8 schema ID followed by exactly one
|
|
|
|
|
zero byte.
|
|
|
|
|
|
2026-07-11 23:33:04 +09:00
|
|
|
## Network readiness
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
classDiagram
|
|
|
|
|
class NetworkReadinessEvidence {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
network_sidecar_id
|
|
|
|
|
readiness_fingerprint
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NetworkReadinessAttestation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
schema_id
|
|
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
configuration_fingerprint
|
|
|
|
|
network_sidecar_id
|
|
|
|
|
derived_policy_digest
|
|
|
|
|
enforcement_namespace
|
|
|
|
|
runtime_supervisor
|
|
|
|
|
connectivity_helper
|
|
|
|
|
observation
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NetworkObservation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
policy_delivery
|
|
|
|
|
helper_ready
|
|
|
|
|
observed_routes
|
|
|
|
|
routes_attested
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PolicyDelivery {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
<<enumeration>>
|
|
|
|
|
SealedMemfd
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NetworkReadinessIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
schema_id
|
|
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
configuration_fingerprint
|
|
|
|
|
network_sidecar_id
|
|
|
|
|
derived_policy_digest
|
|
|
|
|
enforcement_namespace
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NamespaceIdentity {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
device
|
|
|
|
|
inode
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class NetworkReachabilityProbe {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
domain_id
|
|
|
|
|
generation_id
|
|
|
|
|
enforcement_namespace
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DeniedDestinationObservation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
destination
|
|
|
|
|
unreachable
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class PermittedDestinationObservation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
destination
|
|
|
|
|
reachable
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class DnsObservation {
|
2026-07-14 23:34:56 +09:00
|
|
|
<<serialized>>
|
2026-07-11 23:33:04 +09:00
|
|
|
resolver
|
|
|
|
|
query_name
|
|
|
|
|
resolved_addresses
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetworkReadinessEvidence --> NetworkReadinessAttestation : accepts
|
|
|
|
|
NetworkReadinessEvidence --> NetworkReadinessIdentity : fingerprints
|
|
|
|
|
NetworkReadinessEvidence --> NetworkReachabilityProbe : includes
|
|
|
|
|
NetworkReadinessAttestation --> NamespaceIdentity : enforcement_namespace
|
2026-07-14 01:46:58 +09:00
|
|
|
NetworkReadinessAttestation --> PidfsProcessIdentityV1 : runtime_supervisor
|
|
|
|
|
NetworkReadinessAttestation --> PidfsProcessIdentityV1 : connectivity_helper
|
2026-07-11 23:33:04 +09:00
|
|
|
NetworkReadinessAttestation --> NetworkObservation
|
|
|
|
|
NetworkObservation --> PolicyDelivery
|
|
|
|
|
NetworkReadinessIdentity --> NamespaceIdentity : enforcement_namespace
|
|
|
|
|
NetworkReadinessAttestation ..> NetworkReadinessIdentity : projects
|
|
|
|
|
NetworkReachabilityProbe --> NamespaceIdentity : enforcement_namespace
|
|
|
|
|
NetworkReachabilityProbe "1" *-- "1..*" DeniedDestinationObservation
|
|
|
|
|
NetworkReachabilityProbe "1" *-- "1..*" PermittedDestinationObservation
|
|
|
|
|
NetworkReachabilityProbe "1" *-- "1..*" DnsObservation
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The readiness fingerprint is the SHA-256 digest of the canonical readiness
|
|
|
|
|
identity with a schema-specific domain separator. Process identities and network
|
|
|
|
|
observations are attestation evidence but are not part of that fingerprint. The
|
|
|
|
|
Host Coordinator binds the accepted attestation and generation-bound reachability
|
|
|
|
|
probe into Network Readiness Evidence before publication.
|
2026-07-13 04:00:50 +09:00
|
|
|
|
|
|
|
|
`NetworkReadinessAttestation.schema_id` is exactly
|
|
|
|
|
`lazaret-network-attestation-v1`.
|
|
|
|
|
`NetworkReadinessIdentity.schema_id` is exactly
|
|
|
|
|
`lazaret-network-readiness-identity-v1`. They are independent version-dispatch
|
|
|
|
|
domains: the v1 attestation projects only to the v1 readiness identity, and any
|
|
|
|
|
other identifier or version is refused without fallback or cross-domain
|
|
|
|
|
interpretation.
|
|
|
|
|
|
|
|
|
|
The readiness-fingerprint domain separator is the UTF-8 bytes of
|
|
|
|
|
`lazaret-network-readiness-identity-v1` followed by exactly one zero byte. This
|
2026-07-15 16:58:30 +09:00
|
|
|
prefixes the minimal Postcard encoding of the complete
|
|
|
|
|
`NetworkReadinessIdentity` document. The schema ID is therefore present in both
|
|
|
|
|
the domain-separation context and the encoded version-dispatched document.
|