933 lines
26 KiB
Markdown
933 lines
26 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 --> "0..1" 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. The current Domain Store
|
|
identity is `lazaret-domain-store-v2` with version `2`. Domain Store v1 metadata
|
|
dispatches only to legacy migration handling; it is never decoded as v2. The
|
|
Storage Catalog remains `lazaret-storage-catalog-v1` with version `1`.
|
|
|
|
### Host process identity and staged ownership
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class PidfsProcessAuthorityV1 {
|
|
boot_id
|
|
pidfs_st_dev
|
|
pidfs_st_ino
|
|
}
|
|
|
|
class PidfsProcessIdentityV1 {
|
|
host_pid
|
|
start_time_ticks
|
|
}
|
|
|
|
class LegacyUnverifiedProcessIdentityV1 {
|
|
host_pid
|
|
start_time_ticks
|
|
}
|
|
|
|
class HostProcessIdentity {
|
|
<<union>>
|
|
PidfsV1
|
|
LegacyUnverifiedV1
|
|
}
|
|
|
|
class PersistedHostProcessOwnership {
|
|
<<union>>
|
|
Unassigned
|
|
Staged
|
|
Committed
|
|
}
|
|
|
|
class HostProcessOwnershipSlot {
|
|
<<enumeration>>
|
|
SandboxHostCoordinator
|
|
SandboxRuntimeSupervisor
|
|
SandboxAttachedRunsc
|
|
StateAnchorDaemon
|
|
GitRoutingDaemon
|
|
NetworkRuntimeSupervisor
|
|
HelperConnectivityHelper
|
|
HelperRuntimeSupervisor
|
|
SessionTerminalHostCoordinator
|
|
SessionTerminalExecClient
|
|
EscalationHostProcess
|
|
}
|
|
|
|
class ProcessOwnershipMessageVersion {
|
|
<<enumeration>>
|
|
V1
|
|
}
|
|
|
|
class StagedProcessOwnership {
|
|
version
|
|
domain_id
|
|
generation_id
|
|
coordinator_id
|
|
slot
|
|
identity
|
|
}
|
|
|
|
class ProcessOwnershipCommitAck {
|
|
version
|
|
committed
|
|
}
|
|
|
|
PidfsProcessIdentityV1 --> PidfsProcessAuthorityV1 : authority
|
|
HostProcessIdentity --> PidfsProcessIdentityV1 : PidfsV1
|
|
HostProcessIdentity --> LegacyUnverifiedProcessIdentityV1 : LegacyUnverifiedV1
|
|
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
|
|
adoption. `Committed` may contain a current pidfs identity or a
|
|
legacy-unverified v1 PID/start-only value. Only committed current pidfs
|
|
ownership is serviceable; the legacy variant always refuses positive process
|
|
action. There is no observation-based conversion from legacy data to
|
|
`PidfsProcessIdentityV1`.
|
|
|
|
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.
|
|
|
|
### Session terminal ownership
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class SessionTerminal {
|
|
generation_id
|
|
session_id
|
|
state
|
|
container_id
|
|
}
|
|
|
|
class PtyIdentity {
|
|
master_fd
|
|
device
|
|
inode
|
|
}
|
|
|
|
class GuestProcessIdentity {
|
|
leader_pid
|
|
leader_start_time
|
|
process_group_id
|
|
}
|
|
|
|
SessionTerminal --> PersistedHostProcessOwnership : host_coordinator
|
|
SessionTerminal --> PtyIdentity : pty_master
|
|
SessionTerminal --> PersistedHostProcessOwnership : exec_client
|
|
SessionTerminal --> GuestProcessIdentity : guest_process
|
|
```
|
|
|
|
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.
|
|
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`.
|
|
|
|
`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.
|
|
|
|
## 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 cryptography
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class GenerationIdentity {
|
|
agent_profile
|
|
domain_id
|
|
generation_id
|
|
configuration_fingerprint
|
|
coordinator_id
|
|
sandbox_id
|
|
}
|
|
|
|
class TrustManifest {
|
|
protocol_version
|
|
generation_identity
|
|
tls_ca_sha256
|
|
protocol_issuer_public_key
|
|
issuer_signature
|
|
}
|
|
|
|
class TlsCredential {
|
|
generation_identity
|
|
role
|
|
subject_id
|
|
certificate_der
|
|
certificate_sha256
|
|
}
|
|
|
|
class ProtocolPublicationIdentity {
|
|
protocol_version
|
|
generation_identity
|
|
tls_ca_certificate_der
|
|
trust_manifest_sha256
|
|
coordinator_tls_certificate_sha256
|
|
}
|
|
|
|
class SandboxCredentialBundle {
|
|
protocol_version
|
|
generation_identity
|
|
trust_manifest
|
|
coordinator_protocol_credential
|
|
sandbox_protocol_credential
|
|
sandbox_private_key
|
|
}
|
|
|
|
class TlsRole {
|
|
<<enumeration>>
|
|
SessionCoordinator
|
|
ClientCLI
|
|
}
|
|
|
|
class ProtocolCredential {
|
|
protocol_version
|
|
credential_id
|
|
generation_identity
|
|
role
|
|
subject_id
|
|
public_key
|
|
issuer_signature
|
|
}
|
|
|
|
class ProtocolCredentialRole {
|
|
<<enumeration>>
|
|
SessionCoordinator
|
|
AgentSandbox
|
|
}
|
|
|
|
class SessionBinding {
|
|
generation_identity
|
|
cli_id
|
|
session_id
|
|
session_anchor_public_key
|
|
}
|
|
|
|
class SessionRequestCapability {
|
|
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
|
|
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 {
|
|
<<union>>
|
|
payload_bytes
|
|
signature
|
|
}
|
|
|
|
class MailboxRequest {
|
|
protocol_version
|
|
session_binding
|
|
request_id
|
|
session_capability
|
|
sandbox_credential_id
|
|
command_argv
|
|
justification
|
|
}
|
|
|
|
class MailboxCancellation {
|
|
protocol_version
|
|
session_binding
|
|
request_id
|
|
session_capability
|
|
sandbox_credential_id
|
|
}
|
|
|
|
class MailboxResultAck {
|
|
protocol_version
|
|
session_binding
|
|
request_id
|
|
request_sha256
|
|
session_capability
|
|
sandbox_credential_id
|
|
highest_contiguous_sequence
|
|
}
|
|
|
|
class DeveloperDecision {
|
|
protocol_version
|
|
session_binding
|
|
request_id
|
|
request_sha256
|
|
decision
|
|
approved_command_argv
|
|
}
|
|
|
|
class DeveloperDecisionKind {
|
|
<<enumeration>>
|
|
Approve
|
|
Deny
|
|
}
|
|
|
|
class MailboxResult {
|
|
protocol_version
|
|
session_binding
|
|
request_id
|
|
request_sha256
|
|
coordinator_credential_id
|
|
outcome
|
|
exit_code
|
|
chunk_count
|
|
stdout_sha256
|
|
stderr_sha256
|
|
}
|
|
|
|
class MailboxResultChunk {
|
|
protocol_version
|
|
session_binding
|
|
request_id
|
|
request_sha256
|
|
coordinator_credential_id
|
|
sequence
|
|
stream
|
|
bytes
|
|
}
|
|
|
|
class ResultStream {
|
|
<<enumeration>>
|
|
Stdout
|
|
Stderr
|
|
}
|
|
|
|
class EscalationOutcome {
|
|
<<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.
|
|
|
|
### Participant ownership
|
|
|
|
```mermaid
|
|
classDiagram
|
|
class ParticipantOwnership {
|
|
<<union>>
|
|
}
|
|
|
|
class NamespaceIdentity {
|
|
device
|
|
inode
|
|
}
|
|
|
|
class MountIdentity {
|
|
mount_id
|
|
device
|
|
inode
|
|
}
|
|
|
|
class PreparedLowerOwnership {
|
|
optional prepared_artifact_id
|
|
optional source_identity
|
|
optional lease_state
|
|
optional path
|
|
optional device
|
|
optional inode
|
|
}
|
|
|
|
class StateAnchorOwnership {
|
|
optional lower_artifact_id
|
|
optional upper_path
|
|
optional work_path
|
|
optional merged_path
|
|
daemon
|
|
optional mount
|
|
}
|
|
|
|
class GitRoutingOwnership {
|
|
optional mountpoint
|
|
optional host_root
|
|
optional isolated_root
|
|
daemon
|
|
optional mount
|
|
}
|
|
|
|
class NetworkOwnership {
|
|
optional derived_policy_digest
|
|
optional readiness_fingerprint
|
|
optional readiness_evidence
|
|
optional namespace
|
|
runtime_supervisor
|
|
}
|
|
|
|
class HelperOwnership {
|
|
optional network_sidecar_id
|
|
connectivity_helper
|
|
runtime_supervisor
|
|
}
|
|
|
|
class SandboxOwnership {
|
|
optional container_id
|
|
optional runtime_root
|
|
optional bundle_digest
|
|
host_coordinator
|
|
runtime_supervisor
|
|
attached_runsc
|
|
}
|
|
|
|
class PublicationOwnership {
|
|
optional socket_path
|
|
optional identity_path
|
|
}
|
|
|
|
ParticipantOwnership --> PreparedLowerOwnership
|
|
ParticipantOwnership --> StateAnchorOwnership
|
|
ParticipantOwnership --> GitRoutingOwnership
|
|
ParticipantOwnership --> NetworkOwnership
|
|
ParticipantOwnership --> HelperOwnership
|
|
ParticipantOwnership --> SandboxOwnership
|
|
ParticipantOwnership --> PublicationOwnership
|
|
StateAnchorOwnership --> PersistedHostProcessOwnership : daemon
|
|
StateAnchorOwnership --> MountIdentity : mount
|
|
GitRoutingOwnership --> PersistedHostProcessOwnership : daemon
|
|
GitRoutingOwnership --> MountIdentity : mount
|
|
NetworkOwnership --> NamespaceIdentity : namespace
|
|
NetworkOwnership --> PersistedHostProcessOwnership : runtime_supervisor
|
|
NetworkOwnership --> NetworkReadinessEvidence : readiness_evidence
|
|
HelperOwnership --> PersistedHostProcessOwnership : connectivity_helper
|
|
HelperOwnership --> PersistedHostProcessOwnership : runtime_supervisor
|
|
SandboxOwnership --> PersistedHostProcessOwnership : host_coordinator
|
|
SandboxOwnership --> PersistedHostProcessOwnership : runtime_supervisor
|
|
SandboxOwnership --> PersistedHostProcessOwnership : attached_runsc
|
|
```
|
|
|
|
`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 |
|
|
| `Sandbox` | `Committed` | container, runtime root, bundle digest, current committed HC, RS, and runsc |
|
|
| `Publication` | `Committed` | socket and identity paths |
|
|
|
|
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
|
|
enter a newly created dependent-role snapshot directly and is then immutable;
|
|
legacy ownership cannot use this rule. Recorded evidence cannot be replaced or
|
|
cleared. A transition to ReleaseIntent preserves all evidence; PreparedLower
|
|
changes only its lease phase to `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.
|
|
|
|
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.
|
|
|
|
## 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 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 --> PidfsProcessIdentityV1 : runtime_supervisor
|
|
NetworkReadinessAttestation --> PidfsProcessIdentityV1 : 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.
|
|
|
|
`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
|
|
fixes the domain-separation context only; it does not select the byte encoding of
|
|
the canonical readiness-identity fields.
|