Add phase-aware pidfs process ownership records
This commit is contained in:
parent
f840a48376
commit
de57e77dc8
1 changed files with 3513 additions and 246 deletions
266
docs/schema.md
266
docs/schema.md
|
|
@ -98,7 +98,7 @@ classDiagram
|
|||
Domain "1" --> "0..*" Generation
|
||||
Generation "1" --> "0..*" Participant
|
||||
Participant --> ParticipantState
|
||||
Participant --> ParticipantOwnership
|
||||
Participant --> "0..1" ParticipantOwnership
|
||||
Generation "1" --> "0..*" Session
|
||||
Session "1" --> "0..1" SessionTerminal
|
||||
SessionTerminal --> SessionTerminalState
|
||||
|
|
@ -108,7 +108,121 @@ classDiagram
|
|||
|
||||
`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.
|
||||
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
|
||||
|
||||
|
|
@ -127,31 +241,35 @@ classDiagram
|
|||
inode
|
||||
}
|
||||
|
||||
class ProcessIdentity {
|
||||
pid
|
||||
start_time
|
||||
}
|
||||
|
||||
class GuestProcessIdentity {
|
||||
leader_pid
|
||||
leader_start_time
|
||||
process_group_id
|
||||
}
|
||||
|
||||
SessionTerminal --> ProcessIdentity : host_coordinator
|
||||
SessionTerminal --> PersistedHostProcessOwnership : host_coordinator
|
||||
SessionTerminal --> PtyIdentity : pty_master
|
||||
SessionTerminal --> ProcessIdentity : exec_client
|
||||
SessionTerminal --> PersistedHostProcessOwnership : 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.
|
||||
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
|
||||
|
|
@ -452,11 +570,6 @@ classDiagram
|
|||
<<union>>
|
||||
}
|
||||
|
||||
class ProcessIdentity {
|
||||
pid
|
||||
start_time
|
||||
}
|
||||
|
||||
class NamespaceIdentity {
|
||||
device
|
||||
inode
|
||||
|
|
@ -469,57 +582,57 @@ classDiagram
|
|||
}
|
||||
|
||||
class PreparedLowerOwnership {
|
||||
prepared_artifact_id
|
||||
source_identity
|
||||
lease_state
|
||||
path
|
||||
device
|
||||
inode
|
||||
optional prepared_artifact_id
|
||||
optional source_identity
|
||||
optional lease_state
|
||||
optional path
|
||||
optional device
|
||||
optional inode
|
||||
}
|
||||
|
||||
class StateAnchorOwnership {
|
||||
lower_artifact_id
|
||||
upper_path
|
||||
work_path
|
||||
merged_path
|
||||
optional lower_artifact_id
|
||||
optional upper_path
|
||||
optional work_path
|
||||
optional merged_path
|
||||
daemon
|
||||
mount
|
||||
optional mount
|
||||
}
|
||||
|
||||
class GitRoutingOwnership {
|
||||
mountpoint
|
||||
host_root
|
||||
isolated_root
|
||||
optional mountpoint
|
||||
optional host_root
|
||||
optional isolated_root
|
||||
daemon
|
||||
mount
|
||||
optional mount
|
||||
}
|
||||
|
||||
class NetworkOwnership {
|
||||
derived_policy_digest
|
||||
readiness_fingerprint
|
||||
readiness_evidence
|
||||
namespace
|
||||
optional derived_policy_digest
|
||||
optional readiness_fingerprint
|
||||
optional readiness_evidence
|
||||
optional namespace
|
||||
runtime_supervisor
|
||||
}
|
||||
|
||||
class HelperOwnership {
|
||||
network_sidecar_id
|
||||
optional network_sidecar_id
|
||||
connectivity_helper
|
||||
runtime_supervisor
|
||||
}
|
||||
|
||||
class SandboxOwnership {
|
||||
container_id
|
||||
runtime_root
|
||||
bundle_digest
|
||||
optional container_id
|
||||
optional runtime_root
|
||||
optional bundle_digest
|
||||
host_coordinator
|
||||
runtime_supervisor
|
||||
attached_runsc
|
||||
}
|
||||
|
||||
class PublicationOwnership {
|
||||
socket_path
|
||||
identity_path
|
||||
optional socket_path
|
||||
optional identity_path
|
||||
}
|
||||
|
||||
ParticipantOwnership --> PreparedLowerOwnership
|
||||
|
|
@ -529,20 +642,62 @@ classDiagram
|
|||
ParticipantOwnership --> HelperOwnership
|
||||
ParticipantOwnership --> SandboxOwnership
|
||||
ParticipantOwnership --> PublicationOwnership
|
||||
StateAnchorOwnership --> ProcessIdentity : daemon
|
||||
StateAnchorOwnership --> PersistedHostProcessOwnership : daemon
|
||||
StateAnchorOwnership --> MountIdentity : mount
|
||||
GitRoutingOwnership --> ProcessIdentity : daemon
|
||||
GitRoutingOwnership --> PersistedHostProcessOwnership : daemon
|
||||
GitRoutingOwnership --> MountIdentity : mount
|
||||
NetworkOwnership --> NamespaceIdentity : namespace
|
||||
NetworkOwnership --> ProcessIdentity : runtime_supervisor
|
||||
NetworkOwnership --> PersistedHostProcessOwnership : 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
|
||||
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
|
||||
|
|
@ -720,11 +875,6 @@ classDiagram
|
|||
inode
|
||||
}
|
||||
|
||||
class ProcessIdentity {
|
||||
pid
|
||||
start_time
|
||||
}
|
||||
|
||||
class NetworkReachabilityProbe {
|
||||
domain_id
|
||||
generation_id
|
||||
|
|
@ -751,8 +901,8 @@ classDiagram
|
|||
NetworkReadinessEvidence --> NetworkReadinessIdentity : fingerprints
|
||||
NetworkReadinessEvidence --> NetworkReachabilityProbe : includes
|
||||
NetworkReadinessAttestation --> NamespaceIdentity : enforcement_namespace
|
||||
NetworkReadinessAttestation --> ProcessIdentity : runtime_supervisor
|
||||
NetworkReadinessAttestation --> ProcessIdentity : connectivity_helper
|
||||
NetworkReadinessAttestation --> PidfsProcessIdentityV1 : runtime_supervisor
|
||||
NetworkReadinessAttestation --> PidfsProcessIdentityV1 : connectivity_helper
|
||||
NetworkReadinessAttestation --> NetworkObservation
|
||||
NetworkObservation --> PolicyDelivery
|
||||
NetworkReadinessIdentity --> NamespaceIdentity : enforcement_namespace
|
||||
|
|
|
|||
Loading…
Reference in a new issue