docs: formalize protocol identity and transition to regular-file escalation mailbox
- Replaces stream/socket escalation with a sandboxed regular-file Escalation Mailbox to satisfy runsc isolation boundaries without exposing `host-uds=open`. - Expands the TLA+ protocol model with role-bound certificates, tuple authorization, and structured domain-failure recovery paths. - Adds physical integration journals for host terminfo injection, persistent /etc DNS shims, rootless Podman network topology, and static client delivery. - Establishes specification requirements for safe host-only State Anchor inspection and crash-consistent reset operations.
This commit is contained in:
parent
045387dc79
commit
682d7c7db7
4 changed files with 408 additions and 50 deletions
|
|
@ -24,10 +24,10 @@ default_deny = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[escalation]
|
[escalation]
|
||||||
# Set to true to enable the agent-to-host escalation Unix Domain Socket server on the host.
|
# Set to true to enable agent-to-host escalation through Lazaret's host-private control plane.
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
||||||
# socket_dir is optional. Lazaret defaults to a private directory beneath
|
# runtime_dir is optional. Lazaret defaults to a private directory beneath
|
||||||
# $XDG_RUNTIME_DIR.
|
# $XDG_RUNTIME_DIR.
|
||||||
|
|
||||||
# Host commands that the agent is allowed to execute on the host automatically
|
# Host commands that the agent is allowed to execute on the host automatically
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@ CONSTANTS
|
||||||
PromptCmd = promptCmd
|
PromptCmd = promptCmd
|
||||||
ShellCmd = shellCmd
|
ShellCmd = shellCmd
|
||||||
EditedCmd = editedCmd
|
EditedCmd = editedCmd
|
||||||
|
Identities <- IdentitiesFixture
|
||||||
|
SessionAnchors <- SessionAnchorsFixture
|
||||||
Domains <- DomainsFixture
|
Domains <- DomainsFixture
|
||||||
Sessions <- SessionsFixture
|
Sessions <- SessionsFixture
|
||||||
Requests <- RequestsFixture
|
Requests <- RequestsFixture
|
||||||
|
|
@ -20,17 +22,34 @@ CONSTANTS
|
||||||
SessionDomain <- SessionDomainFixture
|
SessionDomain <- SessionDomainFixture
|
||||||
SessionFingerprint <- SessionFingerprintFixture
|
SessionFingerprint <- SessionFingerprintFixture
|
||||||
DomainFingerprint <- DomainFingerprintFixture
|
DomainFingerprint <- DomainFingerprintFixture
|
||||||
|
DomainCoordinatorIdentity <- DomainCoordinatorIdentityFixture
|
||||||
|
DomainSidecarIdentity <- DomainSidecarIdentityFixture
|
||||||
|
DomainSandboxIdentity <- DomainSandboxIdentityFixture
|
||||||
|
SessionCliIdentity <- SessionCliIdentityFixture
|
||||||
|
SessionAnchorIdentity <- SessionAnchorIdentityFixture
|
||||||
|
CoordinatorCertificateValid <- CoordinatorCertificateValidFixture
|
||||||
|
SidecarCertificateValid <- SidecarCertificateValidFixture
|
||||||
|
SandboxCertificateValid <- SandboxCertificateValidFixture
|
||||||
|
CliCertificateValid <- CliCertificateValidFixture
|
||||||
ConfigSafe <- ConfigSafeFixture
|
ConfigSafe <- ConfigSafeFixture
|
||||||
SandboxIsolationSafe <- SandboxIsolationSafeFixture
|
SandboxIsolationSafe <- SandboxIsolationSafeFixture
|
||||||
RequestSession <- RequestSessionFixture
|
RequestSession <- RequestSessionFixture
|
||||||
RequestCommand <- RequestCommandFixture
|
RequestCommand <- RequestCommandFixture
|
||||||
CertificateValid <- CertificateValidFixture
|
RequestSandboxIdentity <- RequestSandboxIdentityFixture
|
||||||
SignatureValid <- SignatureValidFixture
|
RequestCliIdentity <- RequestCliIdentityFixture
|
||||||
|
RequestSessionAnchor <- RequestSessionAnchorFixture
|
||||||
|
RequestCredentialValid <- RequestCredentialValidFixture
|
||||||
|
RequestSignatureValid <- RequestSignatureValidFixture
|
||||||
|
ApprovalCliIdentity <- ApprovalCliIdentityFixture
|
||||||
|
ApprovalSessionAnchor <- ApprovalSessionAnchorFixture
|
||||||
|
ApprovalSignatureValid <- ApprovalSignatureValidFixture
|
||||||
|
ApprovalCommand <- ApprovalCommandFixture
|
||||||
AutoRuleMatches <- AutoRuleMatchesFixture
|
AutoRuleMatches <- AutoRuleMatchesFixture
|
||||||
CommandRequiresShell <- CommandRequiresShellFixture
|
CommandRequiresShell <- CommandRequiresShellFixture
|
||||||
|
CommandContentSafe <- CommandContentSafeFixture
|
||||||
|
|
||||||
SPECIFICATION Spec
|
SPECIFICATION Spec
|
||||||
\* Fully closed or failed application states intentionally have no successor.
|
\* Fully closed application states intentionally have no successor.
|
||||||
CHECK_DEADLOCK FALSE
|
CHECK_DEADLOCK FALSE
|
||||||
|
|
||||||
INVARIANTS
|
INVARIANTS
|
||||||
|
|
@ -39,14 +58,22 @@ INVARIANTS
|
||||||
SandboxNamespaceIsolation
|
SandboxNamespaceIsolation
|
||||||
OrderedNetworkStartup
|
OrderedNetworkStartup
|
||||||
PublishedDomainsReady
|
PublishedDomainsReady
|
||||||
|
ExclusiveBootstrapOwnership
|
||||||
|
TeardownNotJoinable
|
||||||
RegisteredSessionsConnected
|
RegisteredSessionsConnected
|
||||||
AttachedSessionsValid
|
AttachedSessionsValid
|
||||||
AuthenticatedRequestsOnly
|
AuthenticatedRequestsOnly
|
||||||
|
RuntimeRoleIdentitySeparation
|
||||||
|
RegisteredSessionIdentityUniqueness
|
||||||
|
LiveRequestIdentityAuthorized
|
||||||
|
DeveloperApprovalAuthenticated
|
||||||
HostExecutionAuthorized
|
HostExecutionAuthorized
|
||||||
AutoApprovalNoShell
|
AutoApprovalNoShell
|
||||||
TerminalIsolation
|
TerminalIsolation
|
||||||
NoOrphanHostProcess
|
NoOrphanHostProcess
|
||||||
StateAnchorOwnership
|
StateAnchorOwnership
|
||||||
|
FailedDomainIsolation
|
||||||
|
OrderedFailureRecovery
|
||||||
ResultDeliveryStateConsistent
|
ResultDeliveryStateConsistent
|
||||||
|
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
|
|
@ -54,3 +81,4 @@ PROPERTIES
|
||||||
RequestEventuallyResolves
|
RequestEventuallyResolves
|
||||||
PromptEventuallyRestoresTerminal
|
PromptEventuallyRestoresTerminal
|
||||||
EmptyDomainEventuallyStops
|
EmptyDomainEventuallyStops
|
||||||
|
FailedDomainEventuallyRecovers
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@ EXTENDS Naturals, FiniteSets, Sequences, TLC
|
||||||
(***************************************************************************
|
(***************************************************************************
|
||||||
Application-wide protocol model for Lazaret.
|
Application-wide protocol model for Lazaret.
|
||||||
|
|
||||||
The model covers Domain startup, ordered resource preparation, sandbox launch
|
The model covers Domain startup, ordered resource preparation, role-separated
|
||||||
isolation, Client Session registration, host escalation, correlated result
|
runtime identity tuples, sandbox launch isolation, Client Session registration,
|
||||||
delivery, terminal ownership, failure, and teardown.
|
host escalation, correlated result delivery, terminal ownership, failure, and
|
||||||
|
teardown.
|
||||||
Cryptographic algorithms, serialization, container commands, filesystems, and
|
Cryptographic algorithms, serialization, container commands, filesystems, and
|
||||||
network packet handling are refinement boundaries validated by implementation
|
network packet handling are refinement boundaries validated by implementation
|
||||||
tests rather than modeled internally.
|
tests rather than modeled internally.
|
||||||
|
|
@ -17,6 +18,8 @@ CONSTANTS
|
||||||
Sessions,
|
Sessions,
|
||||||
Requests,
|
Requests,
|
||||||
Commands,
|
Commands,
|
||||||
|
Identities,
|
||||||
|
SessionAnchors,
|
||||||
NoSession,
|
NoSession,
|
||||||
NoRequest,
|
NoRequest,
|
||||||
NoCommand,
|
NoCommand,
|
||||||
|
|
@ -24,14 +27,31 @@ CONSTANTS
|
||||||
SessionDomain,
|
SessionDomain,
|
||||||
SessionFingerprint,
|
SessionFingerprint,
|
||||||
DomainFingerprint,
|
DomainFingerprint,
|
||||||
|
DomainCoordinatorIdentity,
|
||||||
|
DomainSidecarIdentity,
|
||||||
|
DomainSandboxIdentity,
|
||||||
|
SessionCliIdentity,
|
||||||
|
SessionAnchorIdentity,
|
||||||
|
CoordinatorCertificateValid,
|
||||||
|
SidecarCertificateValid,
|
||||||
|
SandboxCertificateValid,
|
||||||
|
CliCertificateValid,
|
||||||
ConfigSafe,
|
ConfigSafe,
|
||||||
SandboxIsolationSafe,
|
SandboxIsolationSafe,
|
||||||
RequestSession,
|
RequestSession,
|
||||||
RequestCommand,
|
RequestCommand,
|
||||||
CertificateValid,
|
RequestSandboxIdentity,
|
||||||
SignatureValid,
|
RequestCliIdentity,
|
||||||
|
RequestSessionAnchor,
|
||||||
|
RequestCredentialValid,
|
||||||
|
RequestSignatureValid,
|
||||||
|
ApprovalCliIdentity,
|
||||||
|
ApprovalSessionAnchor,
|
||||||
|
ApprovalSignatureValid,
|
||||||
|
ApprovalCommand,
|
||||||
AutoRuleMatches,
|
AutoRuleMatches,
|
||||||
CommandRequiresShell,
|
CommandRequiresShell,
|
||||||
|
CommandContentSafe,
|
||||||
D1,
|
D1,
|
||||||
S1,
|
S1,
|
||||||
S2,
|
S2,
|
||||||
|
|
@ -48,6 +68,8 @@ ASSUME
|
||||||
/\ IsFiniteSet(Sessions)
|
/\ IsFiniteSet(Sessions)
|
||||||
/\ IsFiniteSet(Requests)
|
/\ IsFiniteSet(Requests)
|
||||||
/\ IsFiniteSet(Commands)
|
/\ IsFiniteSet(Commands)
|
||||||
|
/\ IsFiniteSet(Identities)
|
||||||
|
/\ IsFiniteSet(SessionAnchors)
|
||||||
/\ Domains # {}
|
/\ Domains # {}
|
||||||
/\ Sessions # {}
|
/\ Sessions # {}
|
||||||
/\ Requests # {}
|
/\ Requests # {}
|
||||||
|
|
@ -57,16 +79,35 @@ ASSUME
|
||||||
/\ SessionDomain \in [Sessions -> Domains]
|
/\ SessionDomain \in [Sessions -> Domains]
|
||||||
/\ SessionFingerprint \in [Sessions -> STRING]
|
/\ SessionFingerprint \in [Sessions -> STRING]
|
||||||
/\ DomainFingerprint \in [Domains -> STRING]
|
/\ DomainFingerprint \in [Domains -> STRING]
|
||||||
|
/\ DomainCoordinatorIdentity \in [Domains -> Identities]
|
||||||
|
/\ DomainSidecarIdentity \in [Domains -> Identities]
|
||||||
|
/\ DomainSandboxIdentity \in [Domains -> Identities]
|
||||||
|
/\ SessionCliIdentity \in [Sessions -> Identities]
|
||||||
|
/\ SessionAnchorIdentity \in [Sessions -> SessionAnchors]
|
||||||
|
/\ CoordinatorCertificateValid \in [Domains -> BOOLEAN]
|
||||||
|
/\ SidecarCertificateValid \in [Domains -> BOOLEAN]
|
||||||
|
/\ SandboxCertificateValid \in [Domains -> BOOLEAN]
|
||||||
|
/\ CliCertificateValid \in [Sessions -> BOOLEAN]
|
||||||
/\ ConfigSafe \in [Domains -> BOOLEAN]
|
/\ ConfigSafe \in [Domains -> BOOLEAN]
|
||||||
/\ SandboxIsolationSafe \in [Domains -> BOOLEAN]
|
/\ SandboxIsolationSafe \in [Domains -> BOOLEAN]
|
||||||
/\ RequestSession \in [Requests -> Sessions]
|
/\ RequestSession \in [Requests -> Sessions]
|
||||||
/\ RequestCommand \in [Requests -> Commands]
|
/\ RequestCommand \in [Requests -> Commands]
|
||||||
/\ CertificateValid \in [Requests -> BOOLEAN]
|
/\ RequestSandboxIdentity \in [Requests -> Identities]
|
||||||
/\ SignatureValid \in [Requests -> BOOLEAN]
|
/\ RequestCliIdentity \in [Requests -> Identities]
|
||||||
|
/\ RequestSessionAnchor \in [Requests -> SessionAnchors]
|
||||||
|
/\ RequestCredentialValid \in [Requests -> BOOLEAN]
|
||||||
|
/\ RequestSignatureValid \in [Requests -> BOOLEAN]
|
||||||
|
/\ ApprovalCliIdentity \in [Requests -> Identities]
|
||||||
|
/\ ApprovalSessionAnchor \in [Requests -> SessionAnchors]
|
||||||
|
/\ ApprovalSignatureValid \in [Requests -> BOOLEAN]
|
||||||
|
/\ ApprovalCommand \in [Requests -> Commands]
|
||||||
/\ AutoRuleMatches \in [Requests -> BOOLEAN]
|
/\ AutoRuleMatches \in [Requests -> BOOLEAN]
|
||||||
/\ CommandRequiresShell \in [Commands -> BOOLEAN]
|
/\ CommandRequiresShell \in [Commands -> BOOLEAN]
|
||||||
|
/\ CommandContentSafe \in [Commands -> BOOLEAN]
|
||||||
|
|
||||||
DomainPhases == {"Absent", "Starting", "Ready", "Stopping", "Failed"}
|
DomainPhases == {
|
||||||
|
"Absent", "Starting", "Ready", "Stopping", "Failed", "Recovering"
|
||||||
|
}
|
||||||
CoordinatorStates == {"Absent", "Starting", "Ready", "Stopping", "Failed"}
|
CoordinatorStates == {"Absent", "Starting", "Ready", "Stopping", "Failed"}
|
||||||
MountStates == {"Unmounted", "Mounted"}
|
MountStates == {"Unmounted", "Mounted"}
|
||||||
ResourceStates == {"Stopped", "Ready", "Failed"}
|
ResourceStates == {"Stopped", "Ready", "Failed"}
|
||||||
|
|
@ -106,21 +147,56 @@ DomainsFixture == {D1}
|
||||||
SessionsFixture == {S1, S2}
|
SessionsFixture == {S1, S2}
|
||||||
RequestsFixture == {R1, R2, R3}
|
RequestsFixture == {R1, R2, R3}
|
||||||
CommandsFixture == {ExactCmd, PromptCmd, ShellCmd, EditedCmd}
|
CommandsFixture == {ExactCmd, PromptCmd, ShellCmd, EditedCmd}
|
||||||
|
IdentitiesFixture == {
|
||||||
|
"coordinator-1", "sidecar-1", "sandbox-1", "sandbox-other",
|
||||||
|
"cli-1", "cli-2"
|
||||||
|
}
|
||||||
|
SessionAnchorsFixture == {"anchor-1", "anchor-2"}
|
||||||
|
|
||||||
SessionDomainFixture == (S1 :> D1) @@ (S2 :> D1)
|
SessionDomainFixture == (S1 :> D1) @@ (S2 :> D1)
|
||||||
SessionFingerprintFixture ==
|
SessionFingerprintFixture ==
|
||||||
(S1 :> "config-a") @@ (S2 :> "config-a")
|
(S1 :> "config-a") @@ (S2 :> "config-a")
|
||||||
DomainFingerprintFixture == D1 :> "config-a"
|
DomainFingerprintFixture == D1 :> "config-a"
|
||||||
|
DomainCoordinatorIdentityFixture == D1 :> "coordinator-1"
|
||||||
|
DomainSidecarIdentityFixture == D1 :> "sidecar-1"
|
||||||
|
DomainSandboxIdentityFixture == D1 :> "sandbox-1"
|
||||||
|
SessionCliIdentityFixture == (S1 :> "cli-1") @@ (S2 :> "cli-2")
|
||||||
|
SessionAnchorIdentityFixture ==
|
||||||
|
(S1 :> "anchor-1") @@ (S2 :> "anchor-2")
|
||||||
|
CoordinatorCertificateValidFixture == D1 :> TRUE
|
||||||
|
SidecarCertificateValidFixture == D1 :> TRUE
|
||||||
|
SandboxCertificateValidFixture == D1 :> TRUE
|
||||||
|
CliCertificateValidFixture == (S1 :> TRUE) @@ (S2 :> TRUE)
|
||||||
ConfigSafeFixture == D1 :> TRUE
|
ConfigSafeFixture == D1 :> TRUE
|
||||||
SandboxIsolationSafeFixture == D1 :> TRUE
|
SandboxIsolationSafeFixture == D1 :> TRUE
|
||||||
RequestSessionFixture ==
|
RequestSessionFixture ==
|
||||||
(R1 :> S1) @@ (R2 :> S2) @@ (R3 :> S1)
|
(R1 :> S1) @@ (R2 :> S2) @@ (R3 :> S1)
|
||||||
RequestCommandFixture ==
|
RequestCommandFixture ==
|
||||||
(R1 :> ExactCmd) @@ (R2 :> PromptCmd) @@ (R3 :> ShellCmd)
|
(R1 :> ExactCmd) @@ (R2 :> PromptCmd) @@ (R3 :> ShellCmd)
|
||||||
CertificateValidFixture ==
|
RequestSandboxIdentityFixture ==
|
||||||
(R1 :> TRUE) @@ (R2 :> TRUE) @@ (R3 :> FALSE)
|
(R1 :> "sandbox-1") @@
|
||||||
SignatureValidFixture ==
|
(R2 :> "sandbox-1") @@
|
||||||
(R1 :> TRUE) @@ (R2 :> TRUE) @@ (R3 :> FALSE)
|
(R3 :> "sandbox-other")
|
||||||
|
RequestCliIdentityFixture ==
|
||||||
|
(R1 :> "cli-1") @@ (R2 :> "cli-2") @@ (R3 :> "cli-1")
|
||||||
|
RequestSessionAnchorFixture ==
|
||||||
|
(R1 :> "anchor-1") @@
|
||||||
|
(R2 :> "anchor-2") @@
|
||||||
|
(R3 :> "anchor-1")
|
||||||
|
RequestCredentialValidFixture ==
|
||||||
|
(R1 :> TRUE) @@ (R2 :> TRUE) @@ (R3 :> TRUE)
|
||||||
|
RequestSignatureValidFixture ==
|
||||||
|
(R1 :> TRUE) @@ (R2 :> TRUE) @@ (R3 :> TRUE)
|
||||||
|
ApprovalCliIdentityFixture ==
|
||||||
|
(R1 :> "cli-1") @@ (R2 :> "cli-2") @@ (R3 :> "cli-1")
|
||||||
|
ApprovalSessionAnchorFixture ==
|
||||||
|
(R1 :> "anchor-1") @@
|
||||||
|
(R2 :> "anchor-2") @@
|
||||||
|
(R3 :> "anchor-1")
|
||||||
|
ApprovalSignatureValidFixture ==
|
||||||
|
(R1 :> TRUE) @@ (R2 :> TRUE) @@ (R3 :> TRUE)
|
||||||
|
ApprovalCommandFixture ==
|
||||||
|
(R1 :> ExactCmd) @@ (R2 :> EditedCmd) @@ (R3 :> ShellCmd)
|
||||||
AutoRuleMatchesFixture ==
|
AutoRuleMatchesFixture ==
|
||||||
(R1 :> TRUE) @@ (R2 :> FALSE) @@ (R3 :> TRUE)
|
(R1 :> TRUE) @@ (R2 :> FALSE) @@ (R3 :> TRUE)
|
||||||
CommandRequiresShellFixture ==
|
CommandRequiresShellFixture ==
|
||||||
|
|
@ -128,6 +204,11 @@ CommandRequiresShellFixture ==
|
||||||
(PromptCmd :> FALSE) @@
|
(PromptCmd :> FALSE) @@
|
||||||
(ShellCmd :> TRUE) @@
|
(ShellCmd :> TRUE) @@
|
||||||
(EditedCmd :> FALSE)
|
(EditedCmd :> FALSE)
|
||||||
|
CommandContentSafeFixture ==
|
||||||
|
(ExactCmd :> TRUE) @@
|
||||||
|
(PromptCmd :> TRUE) @@
|
||||||
|
(ShellCmd :> TRUE) @@
|
||||||
|
(EditedCmd :> TRUE)
|
||||||
|
|
||||||
VARIABLES
|
VARIABLES
|
||||||
domainPhase,
|
domainPhase,
|
||||||
|
|
@ -175,6 +256,41 @@ ReqSession(r) == RequestSession[r]
|
||||||
ReqDomain(r) == Dom(ReqSession(r))
|
ReqDomain(r) == Dom(ReqSession(r))
|
||||||
IsTerminalRequest(r) == requestPhase[r] \in TerminalRequestPhases
|
IsTerminalRequest(r) == requestPhase[r] \in TerminalRequestPhases
|
||||||
|
|
||||||
|
RuntimeIdentityTupleReady(d) ==
|
||||||
|
/\ trustReady[d]
|
||||||
|
/\ sidecarState[d] = "Ready"
|
||||||
|
/\ sandboxState[d] = "Ready"
|
||||||
|
/\ CoordinatorCertificateValid[d]
|
||||||
|
/\ SidecarCertificateValid[d]
|
||||||
|
/\ SandboxCertificateValid[d]
|
||||||
|
/\ Cardinality({
|
||||||
|
DomainCoordinatorIdentity[d],
|
||||||
|
DomainSidecarIdentity[d],
|
||||||
|
DomainSandboxIdentity[d]
|
||||||
|
}) = 3
|
||||||
|
|
||||||
|
SessionIdentityTupleRegistered(s) ==
|
||||||
|
/\ s \in registered[Dom(s)]
|
||||||
|
/\ s \in connected[Dom(s)]
|
||||||
|
/\ CliCertificateValid[s]
|
||||||
|
|
||||||
|
RequestIdentityTupleMatches(r) ==
|
||||||
|
LET s == ReqSession(r)
|
||||||
|
d == ReqDomain(r)
|
||||||
|
IN
|
||||||
|
/\ RequestSandboxIdentity[r] = DomainSandboxIdentity[d]
|
||||||
|
/\ RequestCliIdentity[r] = SessionCliIdentity[s]
|
||||||
|
/\ RequestSessionAnchor[r] = SessionAnchorIdentity[s]
|
||||||
|
|
||||||
|
ApprovalIdentityTupleMatches(r) ==
|
||||||
|
LET s == ReqSession(r) IN
|
||||||
|
/\ ApprovalCliIdentity[r] = SessionCliIdentity[s]
|
||||||
|
/\ ApprovalSessionAnchor[r] = SessionAnchorIdentity[s]
|
||||||
|
\* This predicate abstracts verification over the request ID, decision, and
|
||||||
|
\* exact approved command bytes, not merely verification of any signature by
|
||||||
|
\* the registered key.
|
||||||
|
/\ ApprovalSignatureValid[r]
|
||||||
|
|
||||||
Interested(d) == {
|
Interested(d) == {
|
||||||
s \in Sessions :
|
s \in Sessions :
|
||||||
Dom(s) = d /\
|
Dom(s) = d /\
|
||||||
|
|
@ -281,6 +397,7 @@ CreateTrustAnchor(d) ==
|
||||||
/\ domainPhase[d] = "Starting"
|
/\ domainPhase[d] = "Starting"
|
||||||
/\ coordinatorState[d] = "Starting"
|
/\ coordinatorState[d] = "Starting"
|
||||||
/\ ~trustReady[d]
|
/\ ~trustReady[d]
|
||||||
|
/\ CoordinatorCertificateValid[d]
|
||||||
/\ trustReady' = [trustReady EXCEPT ![d] = TRUE]
|
/\ trustReady' = [trustReady EXCEPT ![d] = TRUE]
|
||||||
/\ UNCHANGED <<
|
/\ UNCHANGED <<
|
||||||
domainPhase, coordinatorState, stateAnchorState, sidecarState,
|
domainPhase, coordinatorState, stateAnchorState, sidecarState,
|
||||||
|
|
@ -293,6 +410,7 @@ StartSidecar(d) ==
|
||||||
/\ domainPhase[d] = "Starting"
|
/\ domainPhase[d] = "Starting"
|
||||||
/\ stateAnchorState[d] = "Mounted"
|
/\ stateAnchorState[d] = "Mounted"
|
||||||
/\ trustReady[d]
|
/\ trustReady[d]
|
||||||
|
/\ SidecarCertificateValid[d]
|
||||||
/\ sidecarState[d] = "Stopped"
|
/\ sidecarState[d] = "Stopped"
|
||||||
/\ sidecarState' = [sidecarState EXCEPT ![d] = "Ready"]
|
/\ sidecarState' = [sidecarState EXCEPT ![d] = "Ready"]
|
||||||
/\ UNCHANGED <<
|
/\ UNCHANGED <<
|
||||||
|
|
@ -307,6 +425,7 @@ StartSandbox(d) ==
|
||||||
/\ sidecarState[d] = "Ready"
|
/\ sidecarState[d] = "Ready"
|
||||||
/\ sandboxState[d] = "Stopped"
|
/\ sandboxState[d] = "Stopped"
|
||||||
/\ SandboxIsolationSafe[d]
|
/\ SandboxIsolationSafe[d]
|
||||||
|
/\ SandboxCertificateValid[d]
|
||||||
/\ sandboxState' = [sandboxState EXCEPT ![d] = "Ready"]
|
/\ sandboxState' = [sandboxState EXCEPT ![d] = "Ready"]
|
||||||
/\ UNCHANGED <<
|
/\ UNCHANGED <<
|
||||||
domainPhase, coordinatorState, stateAnchorState, sidecarState,
|
domainPhase, coordinatorState, stateAnchorState, sidecarState,
|
||||||
|
|
@ -368,6 +487,7 @@ RegisterSession(s) ==
|
||||||
/\ connectionState[s] = "Connected"
|
/\ connectionState[s] = "Connected"
|
||||||
/\ domainPhase[d] = "Ready"
|
/\ domainPhase[d] = "Ready"
|
||||||
/\ SessionFingerprint[s] = DomainFingerprint[d]
|
/\ SessionFingerprint[s] = DomainFingerprint[d]
|
||||||
|
/\ CliCertificateValid[s]
|
||||||
/\ registered' = [registered EXCEPT ![d] = @ \cup {s}]
|
/\ registered' = [registered EXCEPT ![d] = @ \cup {s}]
|
||||||
/\ connected' = [connected EXCEPT ![d] = @ \cup {s}]
|
/\ connected' = [connected EXCEPT ![d] = @ \cup {s}]
|
||||||
/\ sessionPhase' = [sessionPhase EXCEPT ![s] = "Attached"]
|
/\ sessionPhase' = [sessionPhase EXCEPT ![s] = "Attached"]
|
||||||
|
|
@ -382,6 +502,8 @@ RegisterSession(s) ==
|
||||||
DisconnectSession(s) ==
|
DisconnectSession(s) ==
|
||||||
LET d == Dom(s)
|
LET d == Dom(s)
|
||||||
r == activeRequest[s]
|
r == activeRequest[s]
|
||||||
|
leaderLost ==
|
||||||
|
lockOwner[d] = s /\ domainPhase[d] = "Starting"
|
||||||
IN
|
IN
|
||||||
/\ sessionPhase[s] \in {
|
/\ sessionPhase[s] \in {
|
||||||
"Waiting", "Registering", "Attached", "Prompting", "HostExecuting"
|
"Waiting", "Registering", "Attached", "Prompting", "HostExecuting"
|
||||||
|
|
@ -397,9 +519,17 @@ DisconnectSession(s) ==
|
||||||
THEN "Cancelled"
|
THEN "Cancelled"
|
||||||
ELSE requestPhase[q]]
|
ELSE requestPhase[q]]
|
||||||
/\ hostRunning' = IF r = NoRequest THEN hostRunning ELSE hostRunning \ {r}
|
/\ hostRunning' = IF r = NoRequest THEN hostRunning ELSE hostRunning \ {r}
|
||||||
|
/\ domainPhase' = [domainPhase EXCEPT
|
||||||
|
![d] = IF leaderLost THEN "Failed" ELSE @]
|
||||||
|
/\ coordinatorState' = [coordinatorState EXCEPT
|
||||||
|
![d] = IF leaderLost THEN "Failed" ELSE @]
|
||||||
|
/\ trustReady' = [trustReady EXCEPT
|
||||||
|
![d] = IF leaderLost THEN FALSE ELSE @]
|
||||||
|
/\ lockOwner' = [lockOwner EXCEPT
|
||||||
|
![d] = IF leaderLost THEN NoSession ELSE @]
|
||||||
|
/\ published' = IF leaderLost THEN published \ {d} ELSE published
|
||||||
/\ UNCHANGED <<
|
/\ UNCHANGED <<
|
||||||
domainPhase, coordinatorState, stateAnchorState, sidecarState,
|
stateAnchorState, sidecarState, sandboxState, approvalSource,
|
||||||
sandboxState, trustReady, lockOwner, published, approvalSource,
|
|
||||||
approvedCommand
|
approvedCommand
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
|
@ -483,8 +613,11 @@ ReceiveEscalation(r) ==
|
||||||
/\ activeRequest[s] = NoRequest
|
/\ activeRequest[s] = NoRequest
|
||||||
/\ s \in registered[d]
|
/\ s \in registered[d]
|
||||||
/\ s \in connected[d]
|
/\ s \in connected[d]
|
||||||
/\ CertificateValid[r]
|
/\ RuntimeIdentityTupleReady(d)
|
||||||
/\ SignatureValid[r]
|
/\ SessionIdentityTupleRegistered(s)
|
||||||
|
/\ RequestIdentityTupleMatches(r)
|
||||||
|
/\ RequestCredentialValid[r]
|
||||||
|
/\ RequestSignatureValid[r]
|
||||||
/\ requestPhase' = [requestPhase EXCEPT ![r] = "Verified"]
|
/\ requestPhase' = [requestPhase EXCEPT ![r] = "Verified"]
|
||||||
/\ activeRequest' = [activeRequest EXCEPT ![s] = r]
|
/\ activeRequest' = [activeRequest EXCEPT ![s] = r]
|
||||||
/\ UNCHANGED <<
|
/\ UNCHANGED <<
|
||||||
|
|
@ -536,7 +669,9 @@ DeveloperApprove(r, cmd) ==
|
||||||
LET s == ReqSession(r) IN
|
LET s == ReqSession(r) IN
|
||||||
/\ requestPhase[r] = "AwaitingApproval"
|
/\ requestPhase[r] = "AwaitingApproval"
|
||||||
/\ sessionPhase[s] = "Prompting"
|
/\ sessionPhase[s] = "Prompting"
|
||||||
|
/\ ApprovalIdentityTupleMatches(r)
|
||||||
/\ cmd \in Commands
|
/\ cmd \in Commands
|
||||||
|
/\ cmd = ApprovalCommand[r]
|
||||||
/\ requestPhase' = [requestPhase EXCEPT ![r] = "Approved"]
|
/\ requestPhase' = [requestPhase EXCEPT ![r] = "Approved"]
|
||||||
/\ approvalSource' = [approvalSource EXCEPT ![r] = "Developer"]
|
/\ approvalSource' = [approvalSource EXCEPT ![r] = "Developer"]
|
||||||
/\ approvedCommand' = [approvedCommand EXCEPT ![r] = cmd]
|
/\ approvedCommand' = [approvedCommand EXCEPT ![r] = cmd]
|
||||||
|
|
@ -550,6 +685,7 @@ DeveloperDeny(r) ==
|
||||||
LET s == ReqSession(r) IN
|
LET s == ReqSession(r) IN
|
||||||
/\ requestPhase[r] = "AwaitingApproval"
|
/\ requestPhase[r] = "AwaitingApproval"
|
||||||
/\ sessionPhase[s] = "Prompting"
|
/\ sessionPhase[s] = "Prompting"
|
||||||
|
/\ ApprovalIdentityTupleMatches(r)
|
||||||
/\ requestPhase' = [requestPhase EXCEPT ![r] = "DenialPending"]
|
/\ requestPhase' = [requestPhase EXCEPT ![r] = "DenialPending"]
|
||||||
/\ sessionPhase' = [sessionPhase EXCEPT ![s] = "Attached"]
|
/\ sessionPhase' = [sessionPhase EXCEPT ![s] = "Attached"]
|
||||||
/\ terminalRoute' = [terminalRoute EXCEPT ![s] = "Sandbox"]
|
/\ terminalRoute' = [terminalRoute EXCEPT ![s] = "Sandbox"]
|
||||||
|
|
@ -568,6 +704,7 @@ StartHostExecution(r) ==
|
||||||
/\ activeRequest[s] = r
|
/\ activeRequest[s] = r
|
||||||
/\ s \in connected[d]
|
/\ s \in connected[d]
|
||||||
/\ sessionPhase[s] \in {"Attached", "Prompting"}
|
/\ sessionPhase[s] \in {"Attached", "Prompting"}
|
||||||
|
/\ CommandContentSafe[approvedCommand[r]]
|
||||||
/\ requestPhase' = [requestPhase EXCEPT ![r] = "Executing"]
|
/\ requestPhase' = [requestPhase EXCEPT ![r] = "Executing"]
|
||||||
/\ sessionPhase' = [sessionPhase EXCEPT ![s] = "HostExecuting"]
|
/\ sessionPhase' = [sessionPhase EXCEPT ![s] = "HostExecuting"]
|
||||||
/\ terminalRoute' = [terminalRoute EXCEPT ![s] = "HostProcess"]
|
/\ terminalRoute' = [terminalRoute EXCEPT ![s] = "HostProcess"]
|
||||||
|
|
@ -662,9 +799,6 @@ FailDomain(d) ==
|
||||||
/\ domainPhase[d] \in {"Starting", "Ready", "Stopping"}
|
/\ domainPhase[d] \in {"Starting", "Ready", "Stopping"}
|
||||||
/\ domainPhase' = [domainPhase EXCEPT ![d] = "Failed"]
|
/\ domainPhase' = [domainPhase EXCEPT ![d] = "Failed"]
|
||||||
/\ coordinatorState' = [coordinatorState EXCEPT ![d] = "Failed"]
|
/\ coordinatorState' = [coordinatorState EXCEPT ![d] = "Failed"]
|
||||||
/\ stateAnchorState' = [stateAnchorState EXCEPT ![d] = "Unmounted"]
|
|
||||||
/\ sidecarState' = [sidecarState EXCEPT ![d] = "Stopped"]
|
|
||||||
/\ sandboxState' = [sandboxState EXCEPT ![d] = "Stopped"]
|
|
||||||
/\ trustReady' = [trustReady EXCEPT ![d] = FALSE]
|
/\ trustReady' = [trustReady EXCEPT ![d] = FALSE]
|
||||||
/\ lockOwner' = [lockOwner EXCEPT ![d] = NoSession]
|
/\ lockOwner' = [lockOwner EXCEPT ![d] = NoSession]
|
||||||
/\ published' = published \ {d}
|
/\ published' = published \ {d}
|
||||||
|
|
@ -685,12 +819,18 @@ FailDomain(d) ==
|
||||||
THEN "Failed"
|
THEN "Failed"
|
||||||
ELSE requestPhase[r]]
|
ELSE requestPhase[r]]
|
||||||
/\ hostRunning' = hostRunning \ RequestsForDomain(d)
|
/\ hostRunning' = hostRunning \ RequestsForDomain(d)
|
||||||
/\ UNCHANGED <<approvalSource, approvedCommand>>
|
/\ UNCHANGED <<
|
||||||
|
stateAnchorState, sidecarState, sandboxState, approvalSource,
|
||||||
|
approvedCommand
|
||||||
|
>>
|
||||||
|
|
||||||
ResetFailedDomain(d) ==
|
BeginRecovery(d) ==
|
||||||
/\ domainPhase[d] = "Failed"
|
/\ domainPhase[d] = "Failed"
|
||||||
/\ domainPhase' = [domainPhase EXCEPT ![d] = "Absent"]
|
/\ registered[d] = {}
|
||||||
/\ coordinatorState' = [coordinatorState EXCEPT ![d] = "Absent"]
|
/\ connected[d] = {}
|
||||||
|
/\ hostRunning \cap RequestsForDomain(d) = {}
|
||||||
|
/\ domainPhase' = [domainPhase EXCEPT ![d] = "Recovering"]
|
||||||
|
/\ coordinatorState' = [coordinatorState EXCEPT ![d] = "Stopping"]
|
||||||
/\ UNCHANGED <<
|
/\ UNCHANGED <<
|
||||||
stateAnchorState, sidecarState, sandboxState, trustReady, lockOwner,
|
stateAnchorState, sidecarState, sandboxState, trustReady, lockOwner,
|
||||||
published, registered, connected, sessionPhase, terminalRoute,
|
published, registered, connected, sessionPhase, terminalRoute,
|
||||||
|
|
@ -698,6 +838,57 @@ ResetFailedDomain(d) ==
|
||||||
approvedCommand, hostRunning
|
approvedCommand, hostRunning
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
RecoverSandbox(d) ==
|
||||||
|
/\ domainPhase[d] = "Recovering"
|
||||||
|
/\ sandboxState[d] # "Stopped"
|
||||||
|
/\ sandboxState' = [sandboxState EXCEPT ![d] = "Stopped"]
|
||||||
|
/\ UNCHANGED <<
|
||||||
|
domainPhase, coordinatorState, stateAnchorState, sidecarState,
|
||||||
|
trustReady, lockOwner, published, registered, connected, sessionPhase,
|
||||||
|
terminalRoute, connectionState, activeRequest, requestPhase,
|
||||||
|
approvalSource, approvedCommand, hostRunning
|
||||||
|
>>
|
||||||
|
|
||||||
|
RecoverSidecar(d) ==
|
||||||
|
/\ domainPhase[d] = "Recovering"
|
||||||
|
/\ sandboxState[d] = "Stopped"
|
||||||
|
/\ sidecarState[d] # "Stopped"
|
||||||
|
/\ sidecarState' = [sidecarState EXCEPT ![d] = "Stopped"]
|
||||||
|
/\ UNCHANGED <<
|
||||||
|
domainPhase, coordinatorState, stateAnchorState, sandboxState,
|
||||||
|
trustReady, lockOwner, published, registered, connected, sessionPhase,
|
||||||
|
terminalRoute, connectionState, activeRequest, requestPhase,
|
||||||
|
approvalSource, approvedCommand, hostRunning
|
||||||
|
>>
|
||||||
|
|
||||||
|
RecoverStateAnchor(d) ==
|
||||||
|
/\ domainPhase[d] = "Recovering"
|
||||||
|
/\ sandboxState[d] = "Stopped"
|
||||||
|
/\ sidecarState[d] = "Stopped"
|
||||||
|
/\ stateAnchorState[d] = "Mounted"
|
||||||
|
/\ stateAnchorState' = [stateAnchorState EXCEPT ![d] = "Unmounted"]
|
||||||
|
/\ UNCHANGED <<
|
||||||
|
domainPhase, coordinatorState, sidecarState, sandboxState, trustReady,
|
||||||
|
lockOwner, published, registered, connected, sessionPhase,
|
||||||
|
terminalRoute, connectionState, activeRequest, requestPhase,
|
||||||
|
approvalSource, approvedCommand, hostRunning
|
||||||
|
>>
|
||||||
|
|
||||||
|
FinishRecovery(d) ==
|
||||||
|
/\ domainPhase[d] = "Recovering"
|
||||||
|
/\ stateAnchorState[d] = "Unmounted"
|
||||||
|
/\ sidecarState[d] = "Stopped"
|
||||||
|
/\ sandboxState[d] = "Stopped"
|
||||||
|
/\ domainPhase' = [domainPhase EXCEPT ![d] = "Absent"]
|
||||||
|
/\ coordinatorState' = [coordinatorState EXCEPT ![d] = "Absent"]
|
||||||
|
/\ lockOwner' = [lockOwner EXCEPT ![d] = NoSession]
|
||||||
|
/\ UNCHANGED <<
|
||||||
|
stateAnchorState, sidecarState, sandboxState, trustReady, published,
|
||||||
|
registered, connected, sessionPhase, terminalRoute, connectionState,
|
||||||
|
activeRequest, requestPhase, approvalSource, approvedCommand,
|
||||||
|
hostRunning
|
||||||
|
>>
|
||||||
|
|
||||||
DomainProgress(d) ==
|
DomainProgress(d) ==
|
||||||
\/ MountStateAnchor(d)
|
\/ MountStateAnchor(d)
|
||||||
\/ CreateTrustAnchor(d)
|
\/ CreateTrustAnchor(d)
|
||||||
|
|
@ -709,7 +900,11 @@ DomainProgress(d) ==
|
||||||
\/ StopSidecar(d)
|
\/ StopSidecar(d)
|
||||||
\/ UnmountStateAnchor(d)
|
\/ UnmountStateAnchor(d)
|
||||||
\/ FinishTeardown(d)
|
\/ FinishTeardown(d)
|
||||||
\/ ResetFailedDomain(d)
|
\/ BeginRecovery(d)
|
||||||
|
\/ RecoverSandbox(d)
|
||||||
|
\/ RecoverSidecar(d)
|
||||||
|
\/ RecoverStateAnchor(d)
|
||||||
|
\/ FinishRecovery(d)
|
||||||
|
|
||||||
SessionProgress(s) ==
|
SessionProgress(s) ==
|
||||||
\/ StartNewDomain(s)
|
\/ StartNewDomain(s)
|
||||||
|
|
@ -793,6 +988,18 @@ PublishedDomainsReady ==
|
||||||
/\ sandboxState[d] = "Ready"
|
/\ sandboxState[d] = "Ready"
|
||||||
/\ trustReady[d]
|
/\ trustReady[d]
|
||||||
|
|
||||||
|
ExclusiveBootstrapOwnership ==
|
||||||
|
\A d \in Domains : lockOwner[d] # NoSession =>
|
||||||
|
/\ domainPhase[d] = "Starting"
|
||||||
|
/\ coordinatorState[d] = "Starting"
|
||||||
|
/\ sessionPhase[lockOwner[d]] = "Waiting"
|
||||||
|
|
||||||
|
TeardownNotJoinable ==
|
||||||
|
\A d \in Domains : domainPhase[d] \in {"Stopping", "Failed", "Recovering"} =>
|
||||||
|
/\ d \notin published
|
||||||
|
/\ registered[d] = {}
|
||||||
|
/\ connected[d] = {}
|
||||||
|
|
||||||
RegisteredSessionsConnected ==
|
RegisteredSessionsConnected ==
|
||||||
\A d \in Domains : registered[d] \subseteq connected[d]
|
\A d \in Domains : registered[d] \subseteq connected[d]
|
||||||
|
|
||||||
|
|
@ -806,14 +1013,52 @@ AttachedSessionsValid ==
|
||||||
|
|
||||||
AuthenticatedRequestsOnly ==
|
AuthenticatedRequestsOnly ==
|
||||||
\A r \in Requests : requestPhase[r] # "Unused" =>
|
\A r \in Requests : requestPhase[r] # "Unused" =>
|
||||||
/\ CertificateValid[r]
|
/\ RequestCredentialValid[r]
|
||||||
/\ SignatureValid[r]
|
/\ RequestSignatureValid[r]
|
||||||
|
/\ RequestIdentityTupleMatches(r)
|
||||||
|
|
||||||
|
RuntimeRoleIdentitySeparation ==
|
||||||
|
/\ \A d \in Domains :
|
||||||
|
Cardinality({
|
||||||
|
DomainCoordinatorIdentity[d],
|
||||||
|
DomainSidecarIdentity[d],
|
||||||
|
DomainSandboxIdentity[d]
|
||||||
|
}) = 3
|
||||||
|
/\ \A s \in Sessions :
|
||||||
|
LET d == Dom(s) IN
|
||||||
|
SessionCliIdentity[s] \notin {
|
||||||
|
DomainCoordinatorIdentity[d],
|
||||||
|
DomainSidecarIdentity[d],
|
||||||
|
DomainSandboxIdentity[d]
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisteredSessionIdentityUniqueness ==
|
||||||
|
\A s1, s2 \in Sessions :
|
||||||
|
/\ s1 # s2
|
||||||
|
/\ s1 \in registered[Dom(s1)]
|
||||||
|
/\ s2 \in registered[Dom(s2)]
|
||||||
|
=> /\ SessionCliIdentity[s1] # SessionCliIdentity[s2]
|
||||||
|
/\ SessionAnchorIdentity[s1] # SessionAnchorIdentity[s2]
|
||||||
|
|
||||||
|
LiveRequestIdentityAuthorized ==
|
||||||
|
\A r \in Requests :
|
||||||
|
requestPhase[r] \notin {"Unused"} \cup TerminalRequestPhases =>
|
||||||
|
/\ RuntimeIdentityTupleReady(ReqDomain(r))
|
||||||
|
/\ SessionIdentityTupleRegistered(ReqSession(r))
|
||||||
|
|
||||||
|
DeveloperApprovalAuthenticated ==
|
||||||
|
\A r \in Requests : approvalSource[r] = "Developer" =>
|
||||||
|
/\ ApprovalCliIdentity[r] = SessionCliIdentity[ReqSession(r)]
|
||||||
|
/\ ApprovalSessionAnchor[r] = SessionAnchorIdentity[ReqSession(r)]
|
||||||
|
/\ ApprovalSignatureValid[r]
|
||||||
|
/\ approvedCommand[r] = ApprovalCommand[r]
|
||||||
|
|
||||||
HostExecutionAuthorized ==
|
HostExecutionAuthorized ==
|
||||||
\A r \in hostRunning :
|
\A r \in hostRunning :
|
||||||
/\ requestPhase[r] = "Executing"
|
/\ requestPhase[r] = "Executing"
|
||||||
/\ approvalSource[r] \in {"AutoRule", "Developer"}
|
/\ approvalSource[r] \in {"AutoRule", "Developer"}
|
||||||
/\ approvedCommand[r] \in Commands
|
/\ approvedCommand[r] \in Commands
|
||||||
|
/\ CommandContentSafe[approvedCommand[r]]
|
||||||
|
|
||||||
AutoApprovalNoShell ==
|
AutoApprovalNoShell ==
|
||||||
\A r \in Requests : approvalSource[r] = "AutoRule" =>
|
\A r \in Requests : approvalSource[r] = "AutoRule" =>
|
||||||
|
|
@ -833,7 +1078,22 @@ NoOrphanHostProcess ==
|
||||||
|
|
||||||
StateAnchorOwnership ==
|
StateAnchorOwnership ==
|
||||||
\A d \in Domains : stateAnchorState[d] = "Mounted" =>
|
\A d \in Domains : stateAnchorState[d] = "Mounted" =>
|
||||||
coordinatorState[d] \in {"Starting", "Ready", "Stopping"}
|
coordinatorState[d] \in {"Starting", "Ready", "Stopping", "Failed"}
|
||||||
|
|
||||||
|
FailedDomainIsolation ==
|
||||||
|
\A d \in Domains : domainPhase[d] \in {"Failed", "Recovering"} =>
|
||||||
|
/\ d \notin published
|
||||||
|
/\ registered[d] = {}
|
||||||
|
/\ connected[d] = {}
|
||||||
|
/\ ~trustReady[d]
|
||||||
|
/\ hostRunning \cap RequestsForDomain(d) = {}
|
||||||
|
|
||||||
|
OrderedFailureRecovery ==
|
||||||
|
\A d \in Domains : domainPhase[d] = "Recovering" =>
|
||||||
|
/\ (sidecarState[d] = "Stopped" => sandboxState[d] = "Stopped")
|
||||||
|
/\ (stateAnchorState[d] = "Unmounted" =>
|
||||||
|
/\ sandboxState[d] = "Stopped"
|
||||||
|
/\ sidecarState[d] = "Stopped")
|
||||||
|
|
||||||
ResultDeliveryStateConsistent ==
|
ResultDeliveryStateConsistent ==
|
||||||
/\ \A r \in Requests : requestPhase[r] \in PendingResultPhases =>
|
/\ \A r \in Requests : requestPhase[r] \in PendingResultPhases =>
|
||||||
|
|
@ -852,14 +1112,22 @@ Safety ==
|
||||||
/\ SandboxNamespaceIsolation
|
/\ SandboxNamespaceIsolation
|
||||||
/\ OrderedNetworkStartup
|
/\ OrderedNetworkStartup
|
||||||
/\ PublishedDomainsReady
|
/\ PublishedDomainsReady
|
||||||
|
/\ ExclusiveBootstrapOwnership
|
||||||
|
/\ TeardownNotJoinable
|
||||||
/\ RegisteredSessionsConnected
|
/\ RegisteredSessionsConnected
|
||||||
/\ AttachedSessionsValid
|
/\ AttachedSessionsValid
|
||||||
/\ AuthenticatedRequestsOnly
|
/\ AuthenticatedRequestsOnly
|
||||||
|
/\ RuntimeRoleIdentitySeparation
|
||||||
|
/\ RegisteredSessionIdentityUniqueness
|
||||||
|
/\ LiveRequestIdentityAuthorized
|
||||||
|
/\ DeveloperApprovalAuthenticated
|
||||||
/\ HostExecutionAuthorized
|
/\ HostExecutionAuthorized
|
||||||
/\ AutoApprovalNoShell
|
/\ AutoApprovalNoShell
|
||||||
/\ TerminalIsolation
|
/\ TerminalIsolation
|
||||||
/\ NoOrphanHostProcess
|
/\ NoOrphanHostProcess
|
||||||
/\ StateAnchorOwnership
|
/\ StateAnchorOwnership
|
||||||
|
/\ FailedDomainIsolation
|
||||||
|
/\ OrderedFailureRecovery
|
||||||
/\ ResultDeliveryStateConsistent
|
/\ ResultDeliveryStateConsistent
|
||||||
|
|
||||||
(***************************************************************************
|
(***************************************************************************
|
||||||
|
|
@ -886,4 +1154,8 @@ EmptyDomainEventuallyStops ==
|
||||||
\A d \in Domains :
|
\A d \in Domains :
|
||||||
(<>[](Interested(d) = {})) => <>(domainPhase[d] = "Absent")
|
(<>[](Interested(d) = {})) => <>(domainPhase[d] = "Absent")
|
||||||
|
|
||||||
|
FailedDomainEventuallyRecovers ==
|
||||||
|
\A d \in Domains :
|
||||||
|
domainPhase[d] = "Failed" ~> domainPhase[d] = "Absent"
|
||||||
|
|
||||||
=============================================================================
|
=============================================================================
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,12 @@ implementation plan, logs, and user interfaces.
|
||||||
| **Agent Workspace** | The canonical host project directory mounted read-write at `/workspace` in the Agent Sandbox. |
|
| **Agent Workspace** | The canonical host project directory mounted read-write at `/workspace` in the Agent Sandbox. |
|
||||||
| **Agent Sandbox** | The rootless gVisor container in which an agent and its child processes execute. One sandbox is shared by all Client Sessions in a Domain. |
|
| **Agent Sandbox** | The rootless gVisor container in which an agent and its child processes execute. One sandbox is shared by all Client Sessions in a Domain. |
|
||||||
| **Agent Sandbox ID** | A runtime-unique identifier assigned to one Agent Sandbox instance and bound to its Domain protocol identity. |
|
| **Agent Sandbox ID** | A runtime-unique identifier assigned to one Agent Sandbox instance and bound to its Domain protocol identity. |
|
||||||
|
| **Client CLI ID** | A runtime-unique identifier assigned to one host Lazaret CLI process. It is authenticated as a protocol identity and bound to one Client Session. |
|
||||||
| **Client Session** | One active host Lazaret CLI process and the interactive or non-interactive command it attaches to the Agent Sandbox. |
|
| **Client Session** | One active host Lazaret CLI process and the interactive or non-interactive command it attaches to the Agent Sandbox. |
|
||||||
| **Session ID** | A cryptographically random identifier unique to one Client Session. |
|
| **Session ID** | A cryptographically random identifier unique to one Client Session. |
|
||||||
| **Session Anchor** | Ephemeral session credentials that bind protocol messages to a registered Session ID and route them to the owning host CLI. |
|
| **Session Anchor** | Ephemeral session credentials that bind protocol messages to a registered Session ID and route them to the owning host CLI. |
|
||||||
| **Session Coordinator** | The ephemeral host process that exclusively owns and coordinates a Domain's runtime resources and Client Sessions. |
|
| **Session Coordinator** | The ephemeral host process that exclusively owns and coordinates a Domain's runtime resources and Client Sessions. |
|
||||||
|
| **Session Coordinator ID** | A runtime-unique identifier assigned to one Session Coordinator instance and bound to its Domain protocol identity. |
|
||||||
| **Domain** | The shared runtime and persistent-state scope for one `(Agent Profile, canonical Agent Workspace)` pair. |
|
| **Domain** | The shared runtime and persistent-state scope for one `(Agent Profile, canonical Agent Workspace)` pair. |
|
||||||
| **Domain ID** | A deterministic identifier derived from the Agent Profile name and canonical Agent Workspace path. It namespaces Domain resources but is not an authentication credential. |
|
| **Domain ID** | A deterministic identifier derived from the Agent Profile name and canonical Agent Workspace path. It namespaces Domain resources but is not an authentication credential. |
|
||||||
| **Domain Root** | The host-only directory containing persistent state and metadata for one Domain. |
|
| **Domain Root** | The host-only directory containing persistent state and metadata for one Domain. |
|
||||||
|
|
@ -79,8 +81,10 @@ implementation plan, logs, and user interfaces.
|
||||||
| **Git Sentry** | The protective mount layout that preserves bidirectional workspace and Git access while preventing writes to the host's default Git hooks and repository configuration. |
|
| **Git Sentry** | The protective mount layout that preserves bidirectional workspace and Git access while preventing writes to the host's default Git hooks and repository configuration. |
|
||||||
| **Ignored Workspace State** | Domain-scoped sandbox-local storage presented at Git-ignored Agent Workspace paths instead of exposing the corresponding host content. |
|
| **Ignored Workspace State** | Domain-scoped sandbox-local storage presented at Git-ignored Agent Workspace paths instead of exposing the corresponding host content. |
|
||||||
| **State Anchor** | The Domain-scoped persistent writable filesystem layer merged over selected paths from the sandbox base image. |
|
| **State Anchor** | The Domain-scoped persistent writable filesystem layer merged over selected paths from the sandbox base image. |
|
||||||
| **Trust Anchor** | The ephemeral Domain-scoped certificate authority used to authenticate Lazaret protocol peers. |
|
| **Trust Anchor** | The ephemeral Domain-scoped certificate authority used to authenticate role-bound Lazaret protocol identities. |
|
||||||
|
| **Protocol Identity** | An authenticated binding of a component role, Agent Profile, Domain ID, and runtime component ID. Identifiers name components but do not authenticate them by themselves. |
|
||||||
| **Escalation Client** | The Lazaret-provided executable through which a sandboxed process requests a host action. |
|
| **Escalation Client** | The Lazaret-provided executable through which a sandboxed process requests a host action. |
|
||||||
|
| **Escalation Mailbox** | Host-private, Domain-scoped regular-file message paths mounted into the Agent Sandbox for signed escalation requests and correlated results. |
|
||||||
| **Escalation Request ID** | A cryptographically random identifier used to correlate one host escalation request and response. |
|
| **Escalation Request ID** | A cryptographically random identifier used to correlate one host escalation request and response. |
|
||||||
| **Escalation Result** | The terminal response to an accepted Host Escalation, correlated by Escalation Request ID and carrying its outcome plus command exit status and output when execution occurred. |
|
| **Escalation Result** | The terminal response to an accepted Host Escalation, correlated by Escalation Request ID and carrying its outcome plus command exit status and output when execution occurred. |
|
||||||
| **Host Escalation** | A request by a sandboxed process for Lazaret to execute a developer-approved or auto-approved action with host authority. |
|
| **Host Escalation** | A request by a sandboxed process for Lazaret to execute a developer-approved or auto-approved action with host authority. |
|
||||||
|
|
@ -100,6 +104,7 @@ flowchart LR
|
||||||
Coordinator[Session Coordinator]
|
Coordinator[Session Coordinator]
|
||||||
State[State Anchor]
|
State[State Anchor]
|
||||||
Gateway[Network Sidecar]
|
Gateway[Network Sidecar]
|
||||||
|
Mailbox[Escalation Mailbox]
|
||||||
HostExec[Approved host process]
|
HostExec[Approved host process]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -114,10 +119,10 @@ flowchart LR
|
||||||
CLI <--> Coordinator
|
CLI <--> Coordinator
|
||||||
Coordinator --> State
|
Coordinator --> State
|
||||||
Coordinator --> Gateway
|
Coordinator --> Gateway
|
||||||
Coordinator --> Agent
|
Coordinator <--> Mailbox
|
||||||
Agent <--> Workspace
|
Agent <--> Workspace
|
||||||
Agent --> Escalate
|
Agent --> Escalate
|
||||||
Escalate --> Coordinator
|
Escalate <--> Mailbox
|
||||||
Coordinator --> HostExec
|
Coordinator --> HostExec
|
||||||
Agent --> Gateway
|
Agent --> Gateway
|
||||||
Gateway --> Network[Permitted destinations]
|
Gateway --> Network[Permitted destinations]
|
||||||
|
|
@ -132,10 +137,10 @@ untrusted agent environment.
|
||||||
### 3.2 Domain and Session Lifecycle
|
### 3.2 Domain and Session Lifecycle
|
||||||
|
|
||||||
The Session Coordinator is the single owner of a Domain's Agent Sandbox, Network
|
The Session Coordinator is the single owner of a Domain's Agent Sandbox, Network
|
||||||
Sidecar, State Anchor, sockets, and active-session registry. Concurrent CLI
|
Sidecar, State Anchor, host-only sockets, Escalation Mailbox, and active-session
|
||||||
processes for the same Domain join the existing coordinator and attach separate
|
registry. Concurrent CLI processes for the same Domain join the existing
|
||||||
Client Sessions to the shared sandbox. Different Domains never share these
|
coordinator and attach separate Client Sessions to the shared sandbox. Different
|
||||||
resources.
|
Domains never share these resources.
|
||||||
|
|
||||||
The first Client Session starts the Domain. The coordinator prepares persistent
|
The first Client Session starts the Domain. The coordinator prepares persistent
|
||||||
state, establishes network policy, starts the Agent Sandbox, and then accepts the
|
state, establishes network policy, starts the Agent Sandbox, and then accepts the
|
||||||
|
|
@ -145,6 +150,25 @@ retaining Domain-scoped persistent state.
|
||||||
Startup, registration, cancellation, recovery, and teardown transitions are
|
Startup, registration, cancellation, recovery, and teardown transitions are
|
||||||
defined by the [TLA+ application protocol model](protocol/Lazaret.tla).
|
defined by the [TLA+ application protocol model](protocol/Lazaret.tla).
|
||||||
|
|
||||||
|
A Domain failure first withdraws publication, invalidates active trust material,
|
||||||
|
disconnects sessions, and terminates associated host processes. It does not
|
||||||
|
assume that already-created sandbox, sidecar, or mount resources disappeared.
|
||||||
|
Recovery stops the sandbox, then the sidecar, then unmounts the State Anchor
|
||||||
|
before the Domain may return to the absent state and accept a new startup leader.
|
||||||
|
|
||||||
|
The Trust Anchor authenticates distinct Protocol Identities for the Session
|
||||||
|
Coordinator, Client CLI, Network Sidecar, and Agent Sandbox. Certificates bind a
|
||||||
|
peer's role, Agent Profile, Domain ID, and runtime component ID; a certificate for
|
||||||
|
one role or Domain cannot authorize another. Session registration additionally
|
||||||
|
binds the authenticated Client CLI ID to its Session ID and Session Anchor.
|
||||||
|
|
||||||
|
Authorization uses the relevant current identity tuple rather than any identifier
|
||||||
|
alone. Network attachment binds the `(Domain ID, Network Sidecar ID, Agent Sandbox
|
||||||
|
ID)` tuple. Session control binds the `(Domain ID, Session Coordinator ID, Client
|
||||||
|
CLI ID, Session ID)` tuple. Host Escalation binds the authenticated Agent Sandbox
|
||||||
|
ID to the registered `(Client CLI ID, Session ID, Session Anchor)` tuple in that
|
||||||
|
Domain.
|
||||||
|
|
||||||
### 3.3 Filesystem and Git Model
|
### 3.3 Filesystem and Git Model
|
||||||
|
|
||||||
The Agent Workspace is mounted read-write. Tracked paths and untracked paths that
|
The Agent Workspace is mounted read-write. Tracked paths and untracked paths that
|
||||||
|
|
@ -196,6 +220,8 @@ override Lazaret's host control plane.
|
||||||
The Network Sidecar establishes the Domain's egress routes before the Agent
|
The Network Sidecar establishes the Domain's egress routes before the Agent
|
||||||
Sandbox starts. The sidecar alone receives the network-administration capability
|
Sandbox starts. The sidecar alone receives the network-administration capability
|
||||||
needed to install policy; the Agent Sandbox does not receive that capability.
|
needed to install policy; the Agent Sandbox does not receive that capability.
|
||||||
|
The Agent Sandbox may join only the sidecar's prepared network namespace, not the
|
||||||
|
host network namespace.
|
||||||
|
|
||||||
IPv4 destinations are permitted by default except for the RFC 1918 private
|
IPv4 destinations are permitted by default except for the RFC 1918 private
|
||||||
address ranges, which are denied by default. Explicit, more-specific allow rules
|
address ranges, which are denied by default. Explicit, more-specific allow rules
|
||||||
|
|
@ -215,10 +241,15 @@ that property.
|
||||||
|
|
||||||
### 3.6 Host Escalation
|
### 3.6 Host Escalation
|
||||||
|
|
||||||
The Escalation Client communicates with the Session Coordinator over a
|
The Escalation Client exchanges request and result records through the
|
||||||
Domain-scoped host-private Unix socket. The Trust Anchor authenticates the Domain
|
Escalation Mailbox. Records are regular files written by atomic rename beneath
|
||||||
peer, and the Session Anchor binds the request to a registered Client Session. A
|
host-private, Domain-scoped paths. The sandbox-writable request path and
|
||||||
verified request is routed only to that session's host CLI.
|
sandbox-readable result path may have different mount modes. The mailbox is not
|
||||||
|
trusted as an authentication boundary: each request carries authenticated Domain
|
||||||
|
credentials and a Session Anchor signature binding it to a registered Client
|
||||||
|
Session and to the exact request content. A verified request is routed only to
|
||||||
|
that session's host CLI. Host-only CLI/coordinator control may use host-private
|
||||||
|
Unix sockets that are never mounted into the Agent Sandbox.
|
||||||
|
|
||||||
A host command may run only when the developer approves it interactively or when
|
A host command may run only when the developer approves it interactively or when
|
||||||
it matches an auto-approval rule in trusted host configuration. Auto-approved
|
it matches an auto-approval rule in trusted host configuration. Auto-approved
|
||||||
|
|
@ -228,16 +259,38 @@ explicit property of an individual rule.
|
||||||
|
|
||||||
Interactive approval may allow the developer to approve, deny, or edit a request.
|
Interactive approval may allow the developer to approve, deny, or edit a request.
|
||||||
Every accepted request must produce an Escalation Result for its Escalation
|
Every accepted request must produce an Escalation Result for its Escalation
|
||||||
Client while its Client Session remains connected. The result reports approval,
|
Client while its Client Session remains connected. The result reports completion,
|
||||||
denial, timeout, cancellation, or failure and, when a host command ran, its exit
|
denial, timeout, cancellation, or failure and, when a host command ran, its exit
|
||||||
status and standard-output and standard-error data. A request reaches its terminal
|
status and standard-output and standard-error data. Approval is an authorization
|
||||||
state only after this result is delivered or its Client Session disconnects.
|
decision, not a terminal result. A request reaches its terminal state only after
|
||||||
|
this result is delivered or its Client Session disconnects.
|
||||||
Terminal ownership must return to the sandbox session after resolution.
|
Terminal ownership must return to the sandbox session after resolution.
|
||||||
|
|
||||||
Authentication, message correlation, approval, execution, cancellation, and
|
Authentication, message correlation, approval, execution, cancellation, and
|
||||||
terminal-routing transitions are defined by the
|
terminal-routing transitions are defined by the
|
||||||
[TLA+ application protocol model](protocol/Lazaret.tla).
|
[TLA+ application protocol model](protocol/Lazaret.tla).
|
||||||
|
|
||||||
|
### 3.7 State Inspection and Reset
|
||||||
|
|
||||||
|
The host CLI provides read-only discovery, inspection, structural verification,
|
||||||
|
and explicit reset operations for Domain State Anchors. These operations resolve
|
||||||
|
a Domain through trusted host metadata and never accept an arbitrary host
|
||||||
|
filesystem path as an upper-layer target.
|
||||||
|
|
||||||
|
Inspection reports metadata and overlay changes without printing file contents by
|
||||||
|
default. Structural verification requires an inactive Domain and exclusive
|
||||||
|
lifecycle ownership so its result is not invalidated by concurrent writes. A
|
||||||
|
reset may target one configured persistent container path or all State Anchors in
|
||||||
|
the Domain. It discards the selected upper-layer state so the next launch follows
|
||||||
|
the current base-image lower layer; it does not modify the base image, Agent
|
||||||
|
Workspace, Ignored Workspace State, or unselected State Anchors.
|
||||||
|
|
||||||
|
Reset is permitted only after Lazaret holds the Domain's exclusive lifecycle lock
|
||||||
|
and has established that no Client Session, coordinator, sandbox, sidecar, host
|
||||||
|
process, or overlay mount is using the selected state. Confirmation flags may
|
||||||
|
suppress the human prompt but may not bypass these safety conditions. Reset must
|
||||||
|
be crash-consistent and must never follow a symlink outside the Domain Root.
|
||||||
|
|
||||||
## 4. Requirements
|
## 4. Requirements
|
||||||
|
|
||||||
### 4.1 Security Requirements
|
### 4.1 Security Requirements
|
||||||
|
|
@ -246,17 +299,18 @@ terminal-routing transitions are defined by the
|
||||||
| :--- | :--- |
|
| :--- | :--- |
|
||||||
| **SR-1** | Agent processes shall execute in a rootless gVisor sandbox and shall not receive host root authority. |
|
| **SR-1** | Agent processes shall execute in a rootless gVisor sandbox and shall not receive host root authority. |
|
||||||
| **SR-2** | Host configuration shall never be mounted into the Agent Sandbox or located beneath a host path mounted into it. |
|
| **SR-2** | Host configuration shall never be mounted into the Agent Sandbox or located beneath a host path mounted into it. |
|
||||||
| **SR-3** | Host paths outside the Agent Workspace and developer-configured volumes shall not be accessible to the Agent Sandbox. |
|
| **SR-3** | Host paths outside the Agent Workspace, developer-configured volumes, and Lazaret-owned fixed control mounts shall not be accessible to the Agent Sandbox. |
|
||||||
| **SR-4** | The sandbox shall be unable to modify the host repository's `.git/config` or default `.git/hooks` directory through the workspace mount. |
|
| **SR-4** | The sandbox shall be unable to modify the host repository's `.git/config` or default `.git/hooks` directory through the workspace mount. |
|
||||||
| **SR-5** | The Network Sidecar shall establish network policy before the Agent Sandbox starts, and the Agent Sandbox shall not receive network-administration capability. |
|
| **SR-5** | The Network Sidecar shall establish network policy before the Agent Sandbox starts, and the Agent Sandbox shall not receive network-administration capability. |
|
||||||
| **SR-6** | Network policy shall cover every enabled address family and shall deny equal-specificity policy conflicts. |
|
| **SR-6** | Network policy shall cover every enabled address family and shall deny equal-specificity policy conflicts. |
|
||||||
| **SR-7** | A host action shall execute only after interactive developer approval or a match against a trusted host auto-approval rule. |
|
| **SR-7** | A host action shall execute only after interactive developer approval or a match against a trusted host auto-approval rule. |
|
||||||
| **SR-8** | Auto-approved host commands shall execute without a shell and shall permit trailing arguments only when the matched rule explicitly grants them. |
|
| **SR-8** | Auto-approved host commands shall execute without a shell and shall permit trailing arguments only when the matched rule explicitly grants them. |
|
||||||
| **SR-9** | Escalation requests shall be authenticated to a Domain and bound to a registered Session ID before routing or execution. |
|
| **SR-9** | Every protocol peer shall be authenticated to its component role, Agent Profile, Domain ID, and runtime component ID. Authorization shall require the relevant current identity tuple; an identifier or certificate for another role, Domain, component instance, or Client Session shall not be accepted. |
|
||||||
| **SR-10** | Domain sockets and coordination files shall reside in a host-private directory owned by the developer. |
|
| **SR-10** | Domain sockets, mailboxes, and coordination files shall reside in a host-private directory owned by the developer. |
|
||||||
| **SR-11** | Runtime and persistent resources belonging to different Domain IDs shall remain isolated. |
|
| **SR-11** | Runtime and persistent resources belonging to different Domain IDs shall remain isolated. |
|
||||||
| **SR-12** | The Agent Sandbox shall not join host user, PID, IPC, UTS, cgroup, or network namespaces; the only shared network namespace permitted is the Domain's Network Sidecar enforcement namespace. |
|
| **SR-12** | The Agent Sandbox shall not join host user, PID, IPC, UTS, cgroup, or network namespaces; the only shared network namespace permitted is the Domain's Network Sidecar enforcement namespace. |
|
||||||
| **SR-13** | Git-ignored Agent Workspace paths shall use Ignored Workspace State by default, preventing the sandbox from reading or modifying corresponding host content; only trusted host configuration may disable this behavior. |
|
| **SR-13** | Git-ignored Agent Workspace paths shall use Ignored Workspace State by default, preventing the sandbox from reading or modifying corresponding host content; only trusted host configuration may disable this behavior. |
|
||||||
|
| **SR-14** | State Anchor maintenance shall remain confined to the resolved Domain Root. Destructive maintenance shall require exclusive lifecycle ownership and an inactive, unmounted target. |
|
||||||
|
|
||||||
### 4.2 Functional Requirements
|
### 4.2 Functional Requirements
|
||||||
|
|
||||||
|
|
@ -268,9 +322,11 @@ terminal-routing transitions are defined by the
|
||||||
| **FR-4** | Selected sandbox paths and Ignored Workspace State shall persist across Domain restarts without copying Lazaret host configuration into the sandbox. |
|
| **FR-4** | Selected sandbox paths and Ignored Workspace State shall persist across Domain restarts without copying Lazaret host configuration into the sandbox. |
|
||||||
| **FR-5** | The coordinator shall route each escalation prompt to the Client Session identified by the verified Session ID and deliver the correlated Escalation Result to the requesting Escalation Client. |
|
| **FR-5** | The coordinator shall route each escalation prompt to the Client Session identified by the verified Session ID and deliver the correlated Escalation Result to the requesting Escalation Client. |
|
||||||
| **FR-6** | The final Client Session leaving a Domain shall trigger teardown of transient Domain resources. |
|
| **FR-6** | The final Client Session leaving a Domain shall trigger teardown of transient Domain resources. |
|
||||||
| **FR-7** | Startup and teardown shall recover safely from interrupted or stale prior executions. |
|
| **FR-7** | Startup and teardown shall recover safely from interrupted or stale prior executions without assuming that external runtime resources disappeared with their owner process. |
|
||||||
| **FR-8** | Lazaret shall support interactive terminal sessions without degrading supported host terminal capabilities. |
|
| **FR-8** | Lazaret shall support interactive terminal sessions without degrading supported host terminal capabilities. |
|
||||||
| **FR-9** | Trusted host configuration shall allow the developer to disable Git-ignored path isolation for an Agent Profile. |
|
| **FR-9** | Trusted host configuration shall allow the developer to disable Git-ignored path isolation for an Agent Profile. |
|
||||||
|
| **FR-10** | Session registration shall bind one authenticated Client CLI ID, Session ID, and Session Anchor, and escalation routing and approval shall preserve that binding. |
|
||||||
|
| **FR-11** | The host CLI shall list, inspect, structurally verify, and reset all or selected State Anchors without requiring direct manipulation of Lazaret's storage layout. |
|
||||||
|
|
||||||
### 4.3 Developer-Experience Requirements
|
### 4.3 Developer-Experience Requirements
|
||||||
|
|
||||||
|
|
@ -281,6 +337,7 @@ terminal-routing transitions are defined by the
|
||||||
| **DX-3** | Normal source editing, `git status`, staging, committing, and reference updates shall work from inside the Agent Sandbox. |
|
| **DX-3** | Normal source editing, `git status`, staging, committing, and reference updates shall work from inside the Agent Sandbox. |
|
||||||
| **DX-4** | Escalation prompts shall identify the requesting profile, session, command, and justification without mixing terminal input or output between sessions. |
|
| **DX-4** | Escalation prompts shall identify the requesting profile, session, command, and justification without mixing terminal input or output between sessions. |
|
||||||
| **DX-5** | Failures shall report actionable diagnostics and shall not leave the developer's terminal in a corrupted mode. |
|
| **DX-5** | Failures shall report actionable diagnostics and shall not leave the developer's terminal in a corrupted mode. |
|
||||||
|
| **DX-6** | State inspection shall provide human-readable and machine-readable output without exposing persisted file contents by default, and reset shall show its resolved Domain and exact scope before confirmation. |
|
||||||
|
|
||||||
### 4.4 Operational Requirements
|
### 4.4 Operational Requirements
|
||||||
|
|
||||||
|
|
@ -290,3 +347,4 @@ terminal-routing transitions are defined by the
|
||||||
| **OR-2** | Every accepted protocol request shall resolve to a delivered completed, denied, timed-out, cancelled, or failed result, unless its Client Session disconnects first. |
|
| **OR-2** | Every accepted protocol request shall resolve to a delivered completed, denied, timed-out, cancelled, or failed result, unless its Client Session disconnects first. |
|
||||||
| **OR-3** | Cancellation and process termination shall not strand an active host command or permanently block another Client Session. |
|
| **OR-3** | Cancellation and process termination shall not strand an active host command or permanently block another Client Session. |
|
||||||
| **OR-4** | Security-sensitive behavior shall be covered by integration tests on supported Podman, runsc, filesystem, and network configurations. Test evidence belongs in the journal. |
|
| **OR-4** | Security-sensitive behavior shall be covered by integration tests on supported Podman, runsc, filesystem, and network configurations. Test evidence belongs in the journal. |
|
||||||
|
| **OR-5** | An interrupted State Anchor reset shall recover to either the prior generation or a new empty generation; it shall not leave a partially reset active upper layer. |
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue