lazaret/docs/schema.md

9.9 KiB

Lazaret schemas

This document is the normative design schema for Lazaret records. The specification 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

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

Participant ownership

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

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.

Derived network policy

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

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.