lazaret/docs/schema.md

552 lines
13 KiB
Markdown
Raw Normal View History

# 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.