552 lines
13 KiB
Markdown
552 lines
13 KiB
Markdown
# Lazaret schemas
|
|
|
|
This document is the normative design schema for Lazaret records and protocol
|
|
data shapes. The
|
|
[specification](specification.md) defines their physical use, while the TLA+
|
|
models define lifecycle and ordering above the implementation abstraction. The
|
|
diagrams define logical fields, variants, and relationships; they do not select a
|
|
programming-language representation.
|
|
|
|
## Domain Store
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class DomainStore
|
|
|
|
class StoreMetadata {
|
|
schema_id
|
|
schema_version
|
|
}
|
|
|
|
class Domain {
|
|
domain_id
|
|
profile_name
|
|
canonical_workspace
|
|
}
|
|
|
|
class Generation {
|
|
domain_id
|
|
generation_id
|
|
configuration_fingerprint
|
|
coordinator_id
|
|
network_sidecar_id
|
|
sandbox_id
|
|
durable_decision
|
|
}
|
|
|
|
class Participant {
|
|
generation_id
|
|
role
|
|
state
|
|
ownership
|
|
}
|
|
|
|
class ParticipantState {
|
|
<<enumeration>>
|
|
Intent
|
|
LeaseHeld
|
|
Prepared
|
|
Committed
|
|
ReleaseIntent
|
|
Clean
|
|
}
|
|
|
|
class ParticipantOwnership {
|
|
<<union>>
|
|
PreparedLower
|
|
StateAnchor
|
|
GitRouting
|
|
Network
|
|
Helper
|
|
Sandbox
|
|
Publication
|
|
}
|
|
|
|
class Session {
|
|
generation_id
|
|
session_id
|
|
cli_id
|
|
session_anchor_id
|
|
session_phase
|
|
}
|
|
|
|
class SessionTerminal {
|
|
generation_id
|
|
session_id
|
|
state
|
|
container_id
|
|
}
|
|
|
|
class SessionTerminalState {
|
|
<<enumeration>>
|
|
Intent
|
|
Running
|
|
ReleaseIntent
|
|
Clean
|
|
}
|
|
|
|
class Mailbox {
|
|
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
|
|
Participant --> ParticipantOwnership
|
|
Generation "1" --> "0..*" Session
|
|
Session "1" --> "0..1" SessionTerminal
|
|
SessionTerminal --> SessionTerminalState
|
|
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.
|
|
Each store carries its own schema identity and version.
|
|
|
|
### Session terminal ownership
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class SessionTerminal {
|
|
generation_id
|
|
session_id
|
|
state
|
|
container_id
|
|
}
|
|
|
|
class PtyIdentity {
|
|
master_fd
|
|
device
|
|
inode
|
|
}
|
|
|
|
class ProcessIdentity {
|
|
pid
|
|
start_time
|
|
}
|
|
|
|
class GuestProcessIdentity {
|
|
leader_pid
|
|
leader_start_time
|
|
process_group_id
|
|
}
|
|
|
|
SessionTerminal --> ProcessIdentity : host_coordinator
|
|
SessionTerminal --> PtyIdentity : pty_master
|
|
SessionTerminal --> ProcessIdentity : exec_client
|
|
SessionTerminal --> GuestProcessIdentity : guest_process
|
|
```
|
|
|
|
Host process identities use host pid and start time. 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.
|
|
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`.
|
|
|
|
## Session terminal protocol
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class SessionTerminalEvent {
|
|
<<union>>
|
|
}
|
|
|
|
class TerminalInput {
|
|
session_id
|
|
bytes
|
|
}
|
|
|
|
class TerminalResize {
|
|
session_id
|
|
rows
|
|
columns
|
|
pixel_width
|
|
pixel_height
|
|
}
|
|
|
|
class TerminalSignal {
|
|
session_id
|
|
signal
|
|
}
|
|
|
|
class TerminalSignalKind {
|
|
<<enumeration>>
|
|
Interrupt
|
|
Quit
|
|
Suspend
|
|
}
|
|
|
|
class SessionClose {
|
|
session_id
|
|
}
|
|
|
|
class SessionTerminalMessage {
|
|
<<union>>
|
|
}
|
|
|
|
class TerminalOutput {
|
|
session_id
|
|
bytes
|
|
}
|
|
|
|
class SessionExit {
|
|
session_id
|
|
outcome
|
|
exit_code
|
|
}
|
|
|
|
class SessionExitOutcome {
|
|
<<enumeration>>
|
|
Exited
|
|
Terminated
|
|
RuntimeLost
|
|
}
|
|
|
|
SessionTerminalEvent --> TerminalInput
|
|
SessionTerminalEvent --> TerminalResize
|
|
SessionTerminalEvent --> TerminalSignal
|
|
SessionTerminalEvent --> SessionClose
|
|
TerminalSignal --> TerminalSignalKind
|
|
SessionTerminalMessage --> TerminalOutput
|
|
SessionTerminalMessage --> SessionExit
|
|
SessionExit --> SessionExitOutcome
|
|
```
|
|
|
|
`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;
|
|
it does not preserve stdout and stderr as separate channels. Protocol
|
|
cryptographic envelopes and wire encoding are outside this schema.
|
|
|
|
### Participant ownership
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class ParticipantOwnership {
|
|
<<union>>
|
|
}
|
|
|
|
class ProcessIdentity {
|
|
pid
|
|
start_time
|
|
}
|
|
|
|
class NamespaceIdentity {
|
|
device
|
|
inode
|
|
}
|
|
|
|
class MountIdentity {
|
|
mount_id
|
|
device
|
|
inode
|
|
}
|
|
|
|
class PreparedLowerOwnership {
|
|
prepared_artifact_id
|
|
source_identity
|
|
lease_state
|
|
path
|
|
device
|
|
inode
|
|
}
|
|
|
|
class StateAnchorOwnership {
|
|
lower_artifact_id
|
|
upper_path
|
|
work_path
|
|
merged_path
|
|
daemon
|
|
mount
|
|
}
|
|
|
|
class GitRoutingOwnership {
|
|
mountpoint
|
|
host_root
|
|
isolated_root
|
|
daemon
|
|
mount
|
|
}
|
|
|
|
class NetworkOwnership {
|
|
derived_policy_digest
|
|
readiness_fingerprint
|
|
readiness_evidence
|
|
namespace
|
|
runtime_supervisor
|
|
}
|
|
|
|
class HelperOwnership {
|
|
network_sidecar_id
|
|
connectivity_helper
|
|
runtime_supervisor
|
|
}
|
|
|
|
class SandboxOwnership {
|
|
container_id
|
|
runtime_root
|
|
bundle_digest
|
|
host_coordinator
|
|
runtime_supervisor
|
|
attached_runsc
|
|
}
|
|
|
|
class PublicationOwnership {
|
|
socket_path
|
|
identity_path
|
|
}
|
|
|
|
ParticipantOwnership --> PreparedLowerOwnership
|
|
ParticipantOwnership --> StateAnchorOwnership
|
|
ParticipantOwnership --> GitRoutingOwnership
|
|
ParticipantOwnership --> NetworkOwnership
|
|
ParticipantOwnership --> HelperOwnership
|
|
ParticipantOwnership --> SandboxOwnership
|
|
ParticipantOwnership --> PublicationOwnership
|
|
StateAnchorOwnership --> ProcessIdentity : daemon
|
|
StateAnchorOwnership --> MountIdentity : mount
|
|
GitRoutingOwnership --> ProcessIdentity : daemon
|
|
GitRoutingOwnership --> MountIdentity : mount
|
|
NetworkOwnership --> NamespaceIdentity : namespace
|
|
NetworkOwnership --> ProcessIdentity : runtime_supervisor
|
|
NetworkOwnership --> NetworkReadinessEvidence : readiness_evidence
|
|
HelperOwnership --> ProcessIdentity : connectivity_helper
|
|
HelperOwnership --> ProcessIdentity : runtime_supervisor
|
|
SandboxOwnership --> ProcessIdentity : host_coordinator
|
|
SandboxOwnership --> ProcessIdentity : runtime_supervisor
|
|
SandboxOwnership --> ProcessIdentity : attached_runsc
|
|
```
|
|
|
|
## Storage Catalog
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class StorageCatalog
|
|
|
|
class StoreMetadata {
|
|
schema_id
|
|
schema_version
|
|
}
|
|
|
|
class PreparedArtifact {
|
|
prepared_artifact_id
|
|
source_identity
|
|
selected_manifest_digest
|
|
policy_id
|
|
id_map_digest
|
|
path
|
|
device
|
|
inode
|
|
state
|
|
}
|
|
|
|
class ArtifactState {
|
|
<<enumeration>>
|
|
Available
|
|
Reclaiming
|
|
}
|
|
|
|
class ArtifactLease {
|
|
prepared_artifact_id
|
|
domain_id
|
|
generation_id
|
|
}
|
|
|
|
class PrepareOperation {
|
|
operation_id
|
|
expected_artifact_id
|
|
source_identity
|
|
stage_path
|
|
device
|
|
inode
|
|
}
|
|
|
|
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
|
|
```
|
|
|
|
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
|
|
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.
|
|
|
|
## Derived network policy
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class DerivedNetworkPolicy {
|
|
schema_id
|
|
address_families
|
|
default_actions
|
|
prefix_rules
|
|
resolvers
|
|
}
|
|
|
|
class AddressFamilyDisposition {
|
|
family
|
|
disposition
|
|
}
|
|
|
|
class DefaultAction {
|
|
family
|
|
action
|
|
}
|
|
|
|
class PrefixRule {
|
|
family
|
|
network
|
|
action
|
|
}
|
|
|
|
class Resolver {
|
|
family
|
|
address
|
|
}
|
|
|
|
class AddressFamily {
|
|
<<enumeration>>
|
|
IPv4
|
|
IPv6
|
|
}
|
|
|
|
class PolicyAction {
|
|
<<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.
|
|
|
|
## Network readiness
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class NetworkReadinessEvidence {
|
|
domain_id
|
|
generation_id
|
|
network_sidecar_id
|
|
readiness_fingerprint
|
|
}
|
|
|
|
class NetworkReadinessAttestation {
|
|
schema_id
|
|
domain_id
|
|
generation_id
|
|
configuration_fingerprint
|
|
network_sidecar_id
|
|
derived_policy_digest
|
|
enforcement_namespace
|
|
runtime_supervisor
|
|
connectivity_helper
|
|
observation
|
|
}
|
|
|
|
class NetworkObservation {
|
|
policy_delivery
|
|
helper_ready
|
|
observed_routes
|
|
routes_attested
|
|
}
|
|
|
|
class PolicyDelivery {
|
|
<<enumeration>>
|
|
SealedMemfd
|
|
}
|
|
|
|
class NetworkReadinessIdentity {
|
|
schema_id
|
|
domain_id
|
|
generation_id
|
|
configuration_fingerprint
|
|
network_sidecar_id
|
|
derived_policy_digest
|
|
enforcement_namespace
|
|
}
|
|
|
|
class NamespaceIdentity {
|
|
device
|
|
inode
|
|
}
|
|
|
|
class ProcessIdentity {
|
|
pid
|
|
start_time
|
|
}
|
|
|
|
class NetworkReachabilityProbe {
|
|
domain_id
|
|
generation_id
|
|
enforcement_namespace
|
|
}
|
|
|
|
class DeniedDestinationObservation {
|
|
destination
|
|
unreachable
|
|
}
|
|
|
|
class PermittedDestinationObservation {
|
|
destination
|
|
reachable
|
|
}
|
|
|
|
class DnsObservation {
|
|
resolver
|
|
query_name
|
|
resolved_addresses
|
|
}
|
|
|
|
NetworkReadinessEvidence --> NetworkReadinessAttestation : accepts
|
|
NetworkReadinessEvidence --> NetworkReadinessIdentity : fingerprints
|
|
NetworkReadinessEvidence --> NetworkReachabilityProbe : includes
|
|
NetworkReadinessAttestation --> NamespaceIdentity : enforcement_namespace
|
|
NetworkReadinessAttestation --> ProcessIdentity : runtime_supervisor
|
|
NetworkReadinessAttestation --> ProcessIdentity : connectivity_helper
|
|
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.
|