Model terminal interaction authority and bounded verification
This commit is contained in:
parent
690738d846
commit
6d3a2cfe16
7 changed files with 785 additions and 14 deletions
|
|
@ -47,6 +47,11 @@ CONSTANTS
|
||||||
AutoRuleMatches <- AutoRuleMatchesFixture
|
AutoRuleMatches <- AutoRuleMatchesFixture
|
||||||
CommandRequiresShell <- CommandRequiresShellFixture
|
CommandRequiresShell <- CommandRequiresShellFixture
|
||||||
CommandContentSafe <- CommandContentSafeFixture
|
CommandContentSafe <- CommandContentSafeFixture
|
||||||
|
TerminalEventPlan <- TerminalNoEventPlanFixture
|
||||||
|
TerminalAuthorityPlan <- TerminalNoAuthorityPlanFixture
|
||||||
|
TerminalAdministrativeAuthorityValid <-
|
||||||
|
TerminalNoAdministrativeAuthorityValidFixture
|
||||||
|
TerminalRoutingFault = "Correct"
|
||||||
|
|
||||||
SPECIFICATION Spec
|
SPECIFICATION Spec
|
||||||
\* Fully closed application states intentionally have no successor.
|
\* Fully closed application states intentionally have no successor.
|
||||||
|
|
@ -86,6 +91,8 @@ INVARIANTS
|
||||||
HostExecutionAuthorized
|
HostExecutionAuthorized
|
||||||
AutoApprovalNoShell
|
AutoApprovalNoShell
|
||||||
TerminalIsolation
|
TerminalIsolation
|
||||||
|
TerminalInteractionAuthoritySeparated
|
||||||
|
LocalTerminationAvailableWhileTransportBlocked
|
||||||
NoOrphanHostProcess
|
NoOrphanHostProcess
|
||||||
StateAnchorOwnership
|
StateAnchorOwnership
|
||||||
FailedDomainIsolation
|
FailedDomainIsolation
|
||||||
|
|
|
||||||
|
|
@ -26,8 +26,11 @@ multi-process presence predicates and generation-scoped genCoordinatorId.
|
||||||
Durable participant intent is multi-role; networkReady gates publication;
|
Durable participant intent is multi-role; networkReady gates publication;
|
||||||
preparedLowerLeased and helperProc refine physical ownership under RS.
|
preparedLowerLeased and helperProc refine physical ownership under RS.
|
||||||
Cryptographic algorithms, serialization, container commands, filesystems, typed
|
Cryptographic algorithms, serialization, container commands, filesystems, typed
|
||||||
redb tables, PTY descriptor identities, process identifiers, signal mechanics,
|
redb tables, PTY descriptor identities, process identifiers, terminal byte and
|
||||||
and network packet handling remain refinement boundaries.
|
signal mechanics, and network packet handling remain refinement boundaries.
|
||||||
|
The model does distinguish keyboard PTY delivery, explicit guest-group signals,
|
||||||
|
local Client controls, and terminal metadata because those carry different
|
||||||
|
authorities.
|
||||||
***************************************************************************)
|
***************************************************************************)
|
||||||
|
|
||||||
CONSTANTS
|
CONSTANTS
|
||||||
|
|
@ -69,6 +72,10 @@ CONSTANTS
|
||||||
AutoRuleMatches,
|
AutoRuleMatches,
|
||||||
CommandRequiresShell,
|
CommandRequiresShell,
|
||||||
CommandContentSafe,
|
CommandContentSafe,
|
||||||
|
TerminalEventPlan,
|
||||||
|
TerminalAuthorityPlan,
|
||||||
|
TerminalAdministrativeAuthorityValid,
|
||||||
|
TerminalRoutingFault,
|
||||||
D1,
|
D1,
|
||||||
S1,
|
S1,
|
||||||
S2,
|
S2,
|
||||||
|
|
@ -138,6 +145,24 @@ SessionPhases == {
|
||||||
}
|
}
|
||||||
TerminalRoutes == {"Detached", "Sandbox", "Prompt", "HostProcess"}
|
TerminalRoutes == {"Detached", "Sandbox", "Prompt", "HostProcess"}
|
||||||
SessionTerminalStates == {"Clean", "Intent", "Running", "ReleaseIntent"}
|
SessionTerminalStates == {"Clean", "Intent", "Running", "ReleaseIntent"}
|
||||||
|
TerminalEventKinds == {
|
||||||
|
"Keyboard", "ExplicitSignal", "Resize", "Break", "LocalSuspend",
|
||||||
|
"LocalResume", "LocalDisconnect", "HostSignal"
|
||||||
|
}
|
||||||
|
TerminalAuthorities == {
|
||||||
|
"None", "Client", "Administrator", "LocalClient", "HostProcess"
|
||||||
|
}
|
||||||
|
TerminalDispositions == {"None", "Delivered", "Refused"}
|
||||||
|
TerminalTargets == {
|
||||||
|
"None", "GuestPtyForeground", "RecordedGuestGroup", "LocalClient",
|
||||||
|
"ExactSessionPty"
|
||||||
|
}
|
||||||
|
TerminalRoutingFaults == {
|
||||||
|
"Correct", "KeyboardRecordedGroup", "KeyboardDuplicated",
|
||||||
|
"CrossSession", "ClientAdministrativeSignal",
|
||||||
|
"BlockedTransportPreventsLocalControl"
|
||||||
|
}
|
||||||
|
TerminalTransportStates == {"Ready", "Blocked"}
|
||||||
ConnectionStates == {"Disconnected", "Connected"}
|
ConnectionStates == {"Disconnected", "Connected"}
|
||||||
RequestPhases == {
|
RequestPhases == {
|
||||||
"Unused", "Verified", "AwaitingApproval", "Approved", "Executing",
|
"Unused", "Verified", "AwaitingApproval", "Approved", "Executing",
|
||||||
|
|
@ -185,6 +210,48 @@ EmptyDurableIntent == [role \in DurableRoles |-> FALSE]
|
||||||
SessionAnchorsFixture == {"anchor-1", "anchor-2"}
|
SessionAnchorsFixture == {"anchor-1", "anchor-2"}
|
||||||
|
|
||||||
SessionDomainFixture == (S1 :> D1) @@ (S2 :> D1)
|
SessionDomainFixture == (S1 :> D1) @@ (S2 :> D1)
|
||||||
|
TerminalEventPlanFixture ==
|
||||||
|
(S1 :> <<
|
||||||
|
"Keyboard", "Resize", "LocalSuspend", "LocalResume",
|
||||||
|
"LocalDisconnect"
|
||||||
|
>>) @@
|
||||||
|
(S2 :> <<
|
||||||
|
"ExplicitSignal", "ExplicitSignal", "Break", "Keyboard", "HostSignal"
|
||||||
|
>>)
|
||||||
|
TerminalAuthorityPlanFixture ==
|
||||||
|
(S1 :> <<
|
||||||
|
"Client", "Client", "LocalClient", "LocalClient", "LocalClient"
|
||||||
|
>>) @@
|
||||||
|
(S2 :> <<
|
||||||
|
"Client", "Administrator", "LocalClient", "Client", "HostProcess"
|
||||||
|
>>)
|
||||||
|
TerminalAdministrativeAuthorityValidFixture ==
|
||||||
|
(S1 :> <<FALSE, FALSE, FALSE, FALSE, FALSE>>) @@
|
||||||
|
(S2 :> <<FALSE, TRUE, FALSE, FALSE, FALSE>>)
|
||||||
|
TerminalNoEventPlanFixture ==
|
||||||
|
(S1 :> <<>>) @@ (S2 :> <<>>)
|
||||||
|
TerminalNoAuthorityPlanFixture ==
|
||||||
|
(S1 :> <<>>) @@ (S2 :> <<>>)
|
||||||
|
TerminalNoAdministrativeAuthorityValidFixture ==
|
||||||
|
(S1 :> <<>>) @@ (S2 :> <<>>)
|
||||||
|
TerminalRoutingEventPlanFixture ==
|
||||||
|
(S1 :> <<"Keyboard", "Resize">>) @@
|
||||||
|
(S2 :> <<"ExplicitSignal", "ExplicitSignal">>)
|
||||||
|
TerminalRoutingAuthorityPlanFixture ==
|
||||||
|
(S1 :> <<"Client", "Client">>) @@
|
||||||
|
(S2 :> <<"Client", "Administrator">>)
|
||||||
|
TerminalRoutingAdministrativeAuthorityValidFixture ==
|
||||||
|
(S1 :> <<FALSE, FALSE>>) @@
|
||||||
|
(S2 :> <<FALSE, TRUE>>)
|
||||||
|
TerminalLocalControlEventPlanFixture ==
|
||||||
|
(S1 :> <<"LocalSuspend", "LocalResume", "LocalDisconnect">>) @@
|
||||||
|
(S2 :> <<"Break", "HostSignal">>)
|
||||||
|
TerminalLocalControlAuthorityPlanFixture ==
|
||||||
|
(S1 :> <<"LocalClient", "LocalClient", "LocalClient">>) @@
|
||||||
|
(S2 :> <<"LocalClient", "HostProcess">>)
|
||||||
|
TerminalLocalControlAdministrativeAuthorityValidFixture ==
|
||||||
|
(S1 :> <<FALSE, FALSE, FALSE>>) @@
|
||||||
|
(S2 :> <<FALSE, FALSE>>)
|
||||||
SessionFingerprintFixture ==
|
SessionFingerprintFixture ==
|
||||||
(S1 :> "config-a") @@ (S2 :> "config-a")
|
(S1 :> "config-a") @@ (S2 :> "config-a")
|
||||||
DomainFingerprintFixture == D1 :> "config-a"
|
DomainFingerprintFixture == D1 :> "config-a"
|
||||||
|
|
@ -279,7 +346,22 @@ VARIABLES
|
||||||
sessionTerminalState,
|
sessionTerminalState,
|
||||||
sessionPtyOpen,
|
sessionPtyOpen,
|
||||||
sessionExecPresent,
|
sessionExecPresent,
|
||||||
sessionGuestKnown
|
sessionGuestKnown,
|
||||||
|
terminalEventIndex,
|
||||||
|
terminalLastEventId,
|
||||||
|
terminalLastEvent,
|
||||||
|
terminalLastSourceSession,
|
||||||
|
terminalLastAuthority,
|
||||||
|
terminalLastAdministrativeAuthorityValid,
|
||||||
|
terminalLastDisposition,
|
||||||
|
terminalLastDestination,
|
||||||
|
terminalLastTarget,
|
||||||
|
terminalLastByteDeliveries,
|
||||||
|
terminalLastSignalDeliveries,
|
||||||
|
terminalLastLocalDeliveries,
|
||||||
|
terminalLastMetadataDeliveries,
|
||||||
|
sessionClientSuspended,
|
||||||
|
sessionTerminalTransportState
|
||||||
|
|
||||||
baseVars == <<
|
baseVars == <<
|
||||||
domainPhase,
|
domainPhase,
|
||||||
|
|
@ -318,13 +400,35 @@ baseVars == <<
|
||||||
helperProc
|
helperProc
|
||||||
>>
|
>>
|
||||||
|
|
||||||
terminalVars == <<
|
terminalLifecycleVars == <<
|
||||||
sessionTerminalState,
|
sessionTerminalState,
|
||||||
sessionPtyOpen,
|
sessionPtyOpen,
|
||||||
sessionExecPresent,
|
sessionExecPresent,
|
||||||
sessionGuestKnown
|
sessionGuestKnown
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
terminalEventRecordVars == <<
|
||||||
|
terminalEventIndex,
|
||||||
|
terminalLastEventId,
|
||||||
|
terminalLastEvent,
|
||||||
|
terminalLastSourceSession,
|
||||||
|
terminalLastAuthority,
|
||||||
|
terminalLastAdministrativeAuthorityValid,
|
||||||
|
terminalLastDisposition,
|
||||||
|
terminalLastDestination,
|
||||||
|
terminalLastTarget,
|
||||||
|
terminalLastByteDeliveries,
|
||||||
|
terminalLastSignalDeliveries,
|
||||||
|
terminalLastLocalDeliveries,
|
||||||
|
terminalLastMetadataDeliveries
|
||||||
|
>>
|
||||||
|
|
||||||
|
terminalInteractionVars == <<
|
||||||
|
terminalEventRecordVars, sessionClientSuspended, sessionTerminalTransportState
|
||||||
|
>>
|
||||||
|
|
||||||
|
terminalVars == <<terminalLifecycleVars, terminalInteractionVars>>
|
||||||
|
|
||||||
vars == <<baseVars, terminalVars>>
|
vars == <<baseVars, terminalVars>>
|
||||||
|
|
||||||
Dom(s) == SessionDomain[s]
|
Dom(s) == SessionDomain[s]
|
||||||
|
|
@ -520,6 +624,22 @@ Init ==
|
||||||
/\ sessionPtyOpen = [s \in Sessions |-> FALSE]
|
/\ sessionPtyOpen = [s \in Sessions |-> FALSE]
|
||||||
/\ sessionExecPresent = [s \in Sessions |-> FALSE]
|
/\ sessionExecPresent = [s \in Sessions |-> FALSE]
|
||||||
/\ sessionGuestKnown = [s \in Sessions |-> FALSE]
|
/\ sessionGuestKnown = [s \in Sessions |-> FALSE]
|
||||||
|
/\ terminalEventIndex = [s \in Sessions |-> 1]
|
||||||
|
/\ terminalLastEventId = [s \in Sessions |-> 0]
|
||||||
|
/\ terminalLastEvent = [s \in Sessions |-> "None"]
|
||||||
|
/\ terminalLastSourceSession = [s \in Sessions |-> NoSession]
|
||||||
|
/\ terminalLastAuthority = [s \in Sessions |-> "None"]
|
||||||
|
/\ terminalLastAdministrativeAuthorityValid =
|
||||||
|
[s \in Sessions |-> FALSE]
|
||||||
|
/\ terminalLastDisposition = [s \in Sessions |-> "None"]
|
||||||
|
/\ terminalLastDestination = [s \in Sessions |-> NoSession]
|
||||||
|
/\ terminalLastTarget = [s \in Sessions |-> "None"]
|
||||||
|
/\ terminalLastByteDeliveries = [s \in Sessions |-> 0]
|
||||||
|
/\ terminalLastSignalDeliveries = [s \in Sessions |-> 0]
|
||||||
|
/\ terminalLastLocalDeliveries = [s \in Sessions |-> 0]
|
||||||
|
/\ terminalLastMetadataDeliveries = [s \in Sessions |-> 0]
|
||||||
|
/\ sessionClientSuspended = [s \in Sessions |-> FALSE]
|
||||||
|
/\ sessionTerminalTransportState = [s \in Sessions |-> "Ready"]
|
||||||
|
|
||||||
(***************************************************************************
|
(***************************************************************************
|
||||||
Domain and Session lifecycle
|
Domain and Session lifecycle
|
||||||
|
|
@ -883,8 +1003,9 @@ DisconnectSession(s) ==
|
||||||
Session Terminal and PTY lifecycle
|
Session Terminal and PTY lifecycle
|
||||||
|
|
||||||
The model retains durable state plus abstract PTY, exec-client, and guest
|
The model retains durable state plus abstract PTY, exec-client, and guest
|
||||||
identity facts. Descriptor identities, PID reuse checks, and signal delivery
|
identity facts. It distinguishes interaction authorities and target classes.
|
||||||
remain physical refinements.
|
Descriptor identities, PID reuse checks, control-character values, terminal
|
||||||
|
modes, and physical byte or signal delivery remain refinements.
|
||||||
***************************************************************************)
|
***************************************************************************)
|
||||||
|
|
||||||
BeginSessionTerminal(s) ==
|
BeginSessionTerminal(s) ==
|
||||||
|
|
@ -898,6 +1019,7 @@ BeginSessionTerminal(s) ==
|
||||||
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = TRUE]
|
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = TRUE]
|
||||||
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = FALSE]
|
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = FALSE]
|
||||||
/\ UNCHANGED baseVars
|
/\ UNCHANGED baseVars
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
CommitSessionTerminal(s) ==
|
CommitSessionTerminal(s) ==
|
||||||
/\ sessionPhase[s] = "Attached"
|
/\ sessionPhase[s] = "Attached"
|
||||||
|
|
@ -909,6 +1031,7 @@ CommitSessionTerminal(s) ==
|
||||||
/\ sessionTerminalState' = [sessionTerminalState EXCEPT ![s] = "Running"]
|
/\ sessionTerminalState' = [sessionTerminalState EXCEPT ![s] = "Running"]
|
||||||
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = TRUE]
|
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = TRUE]
|
||||||
/\ UNCHANGED <<baseVars, sessionPtyOpen, sessionExecPresent>>
|
/\ UNCHANGED <<baseVars, sessionPtyOpen, sessionExecPresent>>
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
DisconnectCleanSession(s) ==
|
DisconnectCleanSession(s) ==
|
||||||
/\ sessionTerminalState[s] = "Clean"
|
/\ sessionTerminalState[s] = "Clean"
|
||||||
|
|
@ -921,6 +1044,7 @@ DisconnectLiveSessionTerminal(s) ==
|
||||||
/\ sessionTerminalState' =
|
/\ sessionTerminalState' =
|
||||||
[sessionTerminalState EXCEPT ![s] = "ReleaseIntent"]
|
[sessionTerminalState EXCEPT ![s] = "ReleaseIntent"]
|
||||||
/\ UNCHANGED <<sessionPtyOpen, sessionExecPresent, sessionGuestKnown>>
|
/\ UNCHANGED <<sessionPtyOpen, sessionExecPresent, sessionGuestKnown>>
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
CompleteSessionTerminal(s) ==
|
CompleteSessionTerminal(s) ==
|
||||||
/\ sessionTerminalState[s] = "Running"
|
/\ sessionTerminalState[s] = "Running"
|
||||||
|
|
@ -929,6 +1053,7 @@ CompleteSessionTerminal(s) ==
|
||||||
[sessionTerminalState EXCEPT ![s] = "ReleaseIntent"]
|
[sessionTerminalState EXCEPT ![s] = "ReleaseIntent"]
|
||||||
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
||||||
/\ UNCHANGED <<sessionPtyOpen, sessionGuestKnown>>
|
/\ UNCHANGED <<sessionPtyOpen, sessionGuestKnown>>
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
ExitSessionTerminalBeforeGuestIdentity(s) ==
|
ExitSessionTerminalBeforeGuestIdentity(s) ==
|
||||||
/\ sessionTerminalState[s] = "Intent"
|
/\ sessionTerminalState[s] = "Intent"
|
||||||
|
|
@ -938,6 +1063,7 @@ ExitSessionTerminalBeforeGuestIdentity(s) ==
|
||||||
/\ sessionPtyOpen' = [sessionPtyOpen EXCEPT ![s] = FALSE]
|
/\ sessionPtyOpen' = [sessionPtyOpen EXCEPT ![s] = FALSE]
|
||||||
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
||||||
/\ UNCHANGED sessionGuestKnown
|
/\ UNCHANGED sessionGuestKnown
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
RetainFailedSessionTerminal(s) ==
|
RetainFailedSessionTerminal(s) ==
|
||||||
/\ sessionPhase[s] = "Failed"
|
/\ sessionPhase[s] = "Failed"
|
||||||
|
|
@ -947,6 +1073,7 @@ RetainFailedSessionTerminal(s) ==
|
||||||
/\ sessionPtyOpen' = [sessionPtyOpen EXCEPT ![s] = FALSE]
|
/\ sessionPtyOpen' = [sessionPtyOpen EXCEPT ![s] = FALSE]
|
||||||
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
||||||
/\ UNCHANGED <<baseVars, sessionGuestKnown>>
|
/\ UNCHANGED <<baseVars, sessionGuestKnown>>
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
CleanKnownSessionTerminal(s) ==
|
CleanKnownSessionTerminal(s) ==
|
||||||
/\ sessionPhase[s] \in {"Closed", "Failed"}
|
/\ sessionPhase[s] \in {"Closed", "Failed"}
|
||||||
|
|
@ -958,6 +1085,7 @@ CleanKnownSessionTerminal(s) ==
|
||||||
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
/\ sessionExecPresent' = [sessionExecPresent EXCEPT ![s] = FALSE]
|
||||||
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = FALSE]
|
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = FALSE]
|
||||||
/\ UNCHANGED baseVars
|
/\ UNCHANGED baseVars
|
||||||
|
/\ UNCHANGED terminalInteractionVars
|
||||||
|
|
||||||
BootstrapCleanSessionTerminalAfterRuntimeAbsence(s) ==
|
BootstrapCleanSessionTerminalAfterRuntimeAbsence(s) ==
|
||||||
/\ sessionPhase[s] \in {"Closed", "Failed"}
|
/\ sessionPhase[s] \in {"Closed", "Failed"}
|
||||||
|
|
@ -968,7 +1096,200 @@ BootstrapCleanSessionTerminalAfterRuntimeAbsence(s) ==
|
||||||
/\ HostCoordinatorAlive(Dom(s))
|
/\ HostCoordinatorAlive(Dom(s))
|
||||||
/\ sessionTerminalState' = [sessionTerminalState EXCEPT ![s] = "Clean"]
|
/\ sessionTerminalState' = [sessionTerminalState EXCEPT ![s] = "Clean"]
|
||||||
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = FALSE]
|
/\ sessionGuestKnown' = [sessionGuestKnown EXCEPT ![s] = FALSE]
|
||||||
/\ UNCHANGED <<baseVars, sessionPtyOpen, sessionExecPresent>>
|
/\ UNCHANGED <<baseVars, sessionPtyOpen, sessionExecPresent,
|
||||||
|
terminalInteractionVars>>
|
||||||
|
|
||||||
|
TerminalInteractionAdmissible(s) ==
|
||||||
|
/\ sessionPhase[s] = "Attached"
|
||||||
|
/\ connectionState[s] = "Connected"
|
||||||
|
/\ terminalRoute[s] = "Sandbox"
|
||||||
|
/\ sessionTerminalState[s] = "Running"
|
||||||
|
/\ HostCoordinatorAlive(Dom(s))
|
||||||
|
|
||||||
|
TerminalEventAvailable(s) ==
|
||||||
|
terminalEventIndex[s] <= Len(TerminalEventPlan[s])
|
||||||
|
|
||||||
|
CurrentTerminalEvent(s) ==
|
||||||
|
IF TerminalEventAvailable(s)
|
||||||
|
THEN TerminalEventPlan[s][terminalEventIndex[s]]
|
||||||
|
ELSE "None"
|
||||||
|
|
||||||
|
CurrentTerminalAuthority(s) ==
|
||||||
|
IF TerminalEventAvailable(s)
|
||||||
|
THEN TerminalAuthorityPlan[s][terminalEventIndex[s]]
|
||||||
|
ELSE "None"
|
||||||
|
|
||||||
|
CurrentTerminalAdministrativeAuthorityValid(s) ==
|
||||||
|
IF TerminalEventAvailable(s)
|
||||||
|
THEN TerminalAdministrativeAuthorityValid[s][terminalEventIndex[s]]
|
||||||
|
ELSE FALSE
|
||||||
|
|
||||||
|
OtherSession(s) == CHOOSE t \in Sessions : t # s
|
||||||
|
|
||||||
|
TerminalDelivery(disposition, destination, target, bytes, signals, local, metadata) ==
|
||||||
|
[disposition |-> disposition,
|
||||||
|
destination |-> destination,
|
||||||
|
target |-> target,
|
||||||
|
byteDeliveries |-> bytes,
|
||||||
|
signalDeliveries |-> signals,
|
||||||
|
localDeliveries |-> local,
|
||||||
|
metadataDeliveries |-> metadata]
|
||||||
|
|
||||||
|
NoTerminalDelivery ==
|
||||||
|
TerminalDelivery("None", NoSession, "None", 0, 0, 0, 0)
|
||||||
|
|
||||||
|
RefusedTerminalDelivery ==
|
||||||
|
TerminalDelivery("Refused", NoSession, "None", 0, 0, 0, 0)
|
||||||
|
|
||||||
|
ExpectedTerminalDelivery(s, event, authority, administrativeAuthorityValid) ==
|
||||||
|
CASE /\ event = "Keyboard"
|
||||||
|
/\ authority = "Client" ->
|
||||||
|
TerminalDelivery("Delivered", s, "GuestPtyForeground", 1, 0, 0, 0)
|
||||||
|
[] /\ event = "ExplicitSignal"
|
||||||
|
/\ authority = "Administrator"
|
||||||
|
/\ administrativeAuthorityValid ->
|
||||||
|
TerminalDelivery("Delivered", s, "RecordedGuestGroup", 0, 1, 0, 0)
|
||||||
|
[] event = "ExplicitSignal" -> RefusedTerminalDelivery
|
||||||
|
[] /\ event = "Resize"
|
||||||
|
/\ authority = "Client" ->
|
||||||
|
TerminalDelivery("Delivered", s, "ExactSessionPty", 0, 0, 0, 1)
|
||||||
|
[] /\ event = "Break"
|
||||||
|
/\ authority = "LocalClient" ->
|
||||||
|
TerminalDelivery("Delivered", s, "ExactSessionPty", 0, 0, 0, 1)
|
||||||
|
[] /\ event \in {"LocalSuspend", "LocalResume", "LocalDisconnect"}
|
||||||
|
/\ authority = "LocalClient" ->
|
||||||
|
TerminalDelivery("Delivered", s, "LocalClient", 0, 0, 1, 0)
|
||||||
|
[] /\ event = "HostSignal"
|
||||||
|
/\ authority = "HostProcess" ->
|
||||||
|
TerminalDelivery("Delivered", s, "LocalClient", 0, 0, 1, 0)
|
||||||
|
[] OTHER -> RefusedTerminalDelivery
|
||||||
|
|
||||||
|
RoutedTerminalDelivery(s, event, authority, administrativeAuthorityValid) ==
|
||||||
|
LET expected == ExpectedTerminalDelivery(
|
||||||
|
s, event, authority, administrativeAuthorityValid) IN
|
||||||
|
CASE /\ TerminalRoutingFault = "KeyboardRecordedGroup"
|
||||||
|
/\ event = "Keyboard" ->
|
||||||
|
TerminalDelivery("Delivered", s, "RecordedGuestGroup", 0, 1, 0, 0)
|
||||||
|
[] /\ TerminalRoutingFault = "KeyboardDuplicated"
|
||||||
|
/\ event = "Keyboard" ->
|
||||||
|
TerminalDelivery("Delivered", s, "GuestPtyForeground", 1, 1, 0, 0)
|
||||||
|
[] /\ TerminalRoutingFault = "CrossSession"
|
||||||
|
/\ expected.disposition = "Delivered" ->
|
||||||
|
[expected EXCEPT !.destination = OtherSession(s)]
|
||||||
|
[] /\ TerminalRoutingFault = "ClientAdministrativeSignal"
|
||||||
|
/\ event = "ExplicitSignal"
|
||||||
|
/\ authority = "Client" ->
|
||||||
|
TerminalDelivery("Delivered", s, "RecordedGuestGroup", 0, 1, 0, 0)
|
||||||
|
[] OTHER -> expected
|
||||||
|
|
||||||
|
RecordTerminalEvent(s) ==
|
||||||
|
LET event == CurrentTerminalEvent(s)
|
||||||
|
authority == CurrentTerminalAuthority(s)
|
||||||
|
administrativeAuthorityValid ==
|
||||||
|
CurrentTerminalAdministrativeAuthorityValid(s)
|
||||||
|
delivery == RoutedTerminalDelivery(
|
||||||
|
s, event, authority, administrativeAuthorityValid)
|
||||||
|
IN
|
||||||
|
/\ terminalEventIndex' =
|
||||||
|
[terminalEventIndex EXCEPT ![s] = @ + 1]
|
||||||
|
/\ terminalLastEventId' =
|
||||||
|
[terminalLastEventId EXCEPT ![s] = terminalEventIndex[s]]
|
||||||
|
/\ terminalLastEvent' = [terminalLastEvent EXCEPT ![s] = event]
|
||||||
|
/\ terminalLastSourceSession' =
|
||||||
|
[terminalLastSourceSession EXCEPT ![s] = s]
|
||||||
|
/\ terminalLastAuthority' =
|
||||||
|
[terminalLastAuthority EXCEPT ![s] = authority]
|
||||||
|
/\ terminalLastAdministrativeAuthorityValid' =
|
||||||
|
[terminalLastAdministrativeAuthorityValid EXCEPT
|
||||||
|
![s] = administrativeAuthorityValid]
|
||||||
|
/\ terminalLastDisposition' =
|
||||||
|
[terminalLastDisposition EXCEPT ![s] = delivery.disposition]
|
||||||
|
/\ terminalLastDestination' =
|
||||||
|
[terminalLastDestination EXCEPT ![s] = delivery.destination]
|
||||||
|
/\ terminalLastTarget' =
|
||||||
|
[terminalLastTarget EXCEPT ![s] = delivery.target]
|
||||||
|
/\ terminalLastByteDeliveries' =
|
||||||
|
[terminalLastByteDeliveries EXCEPT ![s] = delivery.byteDeliveries]
|
||||||
|
/\ terminalLastSignalDeliveries' =
|
||||||
|
[terminalLastSignalDeliveries EXCEPT ![s] = delivery.signalDeliveries]
|
||||||
|
/\ terminalLastLocalDeliveries' =
|
||||||
|
[terminalLastLocalDeliveries EXCEPT ![s] = delivery.localDeliveries]
|
||||||
|
/\ terminalLastMetadataDeliveries' =
|
||||||
|
[terminalLastMetadataDeliveries EXCEPT ![s] = delivery.metadataDeliveries]
|
||||||
|
|
||||||
|
DeliverPtyTerminalEvent(s) ==
|
||||||
|
/\ TerminalInteractionAdmissible(s)
|
||||||
|
/\ TerminalEventAvailable(s)
|
||||||
|
/\ CurrentTerminalEvent(s) \in {
|
||||||
|
"Keyboard", "ExplicitSignal", "Resize", "Break"
|
||||||
|
}
|
||||||
|
/\ ~sessionClientSuspended[s]
|
||||||
|
/\ sessionTerminalTransportState[s] = "Ready"
|
||||||
|
/\ RecordTerminalEvent(s)
|
||||||
|
/\ UNCHANGED <<baseVars, terminalLifecycleVars, sessionClientSuspended,
|
||||||
|
sessionTerminalTransportState>>
|
||||||
|
|
||||||
|
SuspendLocalTerminalClient(s) ==
|
||||||
|
/\ TerminalInteractionAdmissible(s)
|
||||||
|
/\ TerminalEventAvailable(s)
|
||||||
|
/\ CurrentTerminalEvent(s) = "LocalSuspend"
|
||||||
|
/\ ~sessionClientSuspended[s]
|
||||||
|
/\ RecordTerminalEvent(s)
|
||||||
|
/\ sessionClientSuspended' =
|
||||||
|
[sessionClientSuspended EXCEPT ![s] = TRUE]
|
||||||
|
/\ UNCHANGED <<baseVars, terminalLifecycleVars,
|
||||||
|
sessionTerminalTransportState>>
|
||||||
|
|
||||||
|
ResumeLocalTerminalClient(s) ==
|
||||||
|
/\ TerminalInteractionAdmissible(s)
|
||||||
|
/\ TerminalEventAvailable(s)
|
||||||
|
/\ CurrentTerminalEvent(s) = "LocalResume"
|
||||||
|
/\ sessionClientSuspended[s]
|
||||||
|
/\ RecordTerminalEvent(s)
|
||||||
|
/\ sessionClientSuspended' =
|
||||||
|
[sessionClientSuspended EXCEPT ![s] = FALSE]
|
||||||
|
/\ UNCHANGED <<baseVars, terminalLifecycleVars,
|
||||||
|
sessionTerminalTransportState>>
|
||||||
|
|
||||||
|
DisconnectTerminalFromLocalAuthority(s, event) ==
|
||||||
|
/\ event \in {"LocalDisconnect", "HostSignal"}
|
||||||
|
/\ TerminalEventAvailable(s)
|
||||||
|
/\ CurrentTerminalEvent(s) = event
|
||||||
|
/\ sessionTerminalState[s] \in {"Intent", "Running"}
|
||||||
|
/\ \/ TerminalRoutingFault # "BlockedTransportPreventsLocalControl"
|
||||||
|
\/ sessionTerminalTransportState[s] = "Ready"
|
||||||
|
/\ DisconnectSession(s)
|
||||||
|
/\ sessionTerminalState' =
|
||||||
|
[sessionTerminalState EXCEPT ![s] = "ReleaseIntent"]
|
||||||
|
/\ RecordTerminalEvent(s)
|
||||||
|
/\ sessionClientSuspended' =
|
||||||
|
[sessionClientSuspended EXCEPT ![s] = FALSE]
|
||||||
|
/\ UNCHANGED <<sessionPtyOpen, sessionExecPresent, sessionGuestKnown,
|
||||||
|
sessionTerminalTransportState>>
|
||||||
|
|
||||||
|
BlockSessionTerminalTransport(s) ==
|
||||||
|
/\ TerminalInteractionAdmissible(s)
|
||||||
|
/\ sessionTerminalTransportState[s] = "Ready"
|
||||||
|
/\ sessionTerminalTransportState' =
|
||||||
|
[sessionTerminalTransportState EXCEPT ![s] = "Blocked"]
|
||||||
|
/\ UNCHANGED <<baseVars, terminalLifecycleVars, terminalEventRecordVars,
|
||||||
|
sessionClientSuspended>>
|
||||||
|
|
||||||
|
UnblockSessionTerminalTransport(s) ==
|
||||||
|
/\ sessionTerminalTransportState[s] = "Blocked"
|
||||||
|
/\ sessionTerminalTransportState' =
|
||||||
|
[sessionTerminalTransportState EXCEPT ![s] = "Ready"]
|
||||||
|
/\ UNCHANGED <<baseVars, terminalLifecycleVars, terminalEventRecordVars,
|
||||||
|
sessionClientSuspended>>
|
||||||
|
|
||||||
|
TerminalInteraction(s) ==
|
||||||
|
\/ DeliverPtyTerminalEvent(s)
|
||||||
|
\/ SuspendLocalTerminalClient(s)
|
||||||
|
\/ ResumeLocalTerminalClient(s)
|
||||||
|
\/ BlockSessionTerminalTransport(s)
|
||||||
|
\/ UnblockSessionTerminalTransport(s)
|
||||||
|
\/ (\E event \in {"LocalDisconnect", "HostSignal"} :
|
||||||
|
DisconnectTerminalFromLocalAuthority(s, event))
|
||||||
|
|
||||||
BeginTeardown(d) ==
|
BeginTeardown(d) ==
|
||||||
/\ domainPhase[d] = "Ready"
|
/\ domainPhase[d] = "Ready"
|
||||||
|
|
@ -2129,12 +2450,16 @@ Next ==
|
||||||
\/ /\ BaseNext
|
\/ /\ BaseNext
|
||||||
/\ UNCHANGED terminalVars
|
/\ UNCHANGED terminalVars
|
||||||
\/ (\E s \in Sessions : SessionTerminalProgress(s))
|
\/ (\E s \in Sessions : SessionTerminalProgress(s))
|
||||||
|
\/ (\E s \in Sessions : TerminalInteraction(s))
|
||||||
|
|
||||||
\* Resume transitions are enabled but not weakly fair: permanent stop is a
|
\* Resume transitions are enabled but not weakly fair: permanent stop is a
|
||||||
\* modeled stuck state for safety, not a guaranteed progress path.
|
\* modeled stuck state for safety, not a guaranteed progress path.
|
||||||
Spec ==
|
SafetySpec ==
|
||||||
/\ Init
|
/\ Init
|
||||||
/\ [][Next]_vars
|
/\ [][Next]_vars
|
||||||
|
|
||||||
|
Spec ==
|
||||||
|
/\ SafetySpec
|
||||||
/\ \A d \in Domains :
|
/\ \A d \in Domains :
|
||||||
WF_vars(DomainServiceProgress(d) /\ UNCHANGED terminalVars)
|
WF_vars(DomainServiceProgress(d) /\ UNCHANGED terminalVars)
|
||||||
/\ \A s \in Sessions :
|
/\ \A s \in Sessions :
|
||||||
|
|
@ -2148,6 +2473,15 @@ Safety properties
|
||||||
***************************************************************************)
|
***************************************************************************)
|
||||||
|
|
||||||
TypeOK ==
|
TypeOK ==
|
||||||
|
/\ TerminalEventPlan \in [Sessions -> Seq(TerminalEventKinds)]
|
||||||
|
/\ TerminalAuthorityPlan \in [Sessions -> Seq(TerminalAuthorities)]
|
||||||
|
/\ TerminalAdministrativeAuthorityValid \in [Sessions -> Seq(BOOLEAN)]
|
||||||
|
/\ \A s \in Sessions :
|
||||||
|
/\ Len(TerminalEventPlan[s]) = Len(TerminalAuthorityPlan[s])
|
||||||
|
/\ Len(TerminalEventPlan[s]) =
|
||||||
|
Len(TerminalAdministrativeAuthorityValid[s])
|
||||||
|
/\ TerminalRoutingFault \in TerminalRoutingFaults
|
||||||
|
/\ (TerminalRoutingFault = "CrossSession" => Cardinality(Sessions) > 1)
|
||||||
/\ domainPhase \in [Domains -> DomainPhases]
|
/\ domainPhase \in [Domains -> DomainPhases]
|
||||||
/\ stateAnchorState \in [Domains -> MountStates]
|
/\ stateAnchorState \in [Domains -> MountStates]
|
||||||
/\ sidecarState \in [Domains -> ResourceStates]
|
/\ sidecarState \in [Domains -> ResourceStates]
|
||||||
|
|
@ -2186,6 +2520,23 @@ TypeOK ==
|
||||||
/\ sessionPtyOpen \in [Sessions -> BOOLEAN]
|
/\ sessionPtyOpen \in [Sessions -> BOOLEAN]
|
||||||
/\ sessionExecPresent \in [Sessions -> BOOLEAN]
|
/\ sessionExecPresent \in [Sessions -> BOOLEAN]
|
||||||
/\ sessionGuestKnown \in [Sessions -> BOOLEAN]
|
/\ sessionGuestKnown \in [Sessions -> BOOLEAN]
|
||||||
|
/\ \A s \in Sessions :
|
||||||
|
terminalEventIndex[s] \in 1..(Len(TerminalEventPlan[s]) + 1)
|
||||||
|
/\ \A s \in Sessions :
|
||||||
|
terminalLastEventId[s] \in 0..Len(TerminalEventPlan[s])
|
||||||
|
/\ terminalLastEvent \in [Sessions -> TerminalEventKinds \cup {"None"}]
|
||||||
|
/\ terminalLastSourceSession \in [Sessions -> Sessions \cup {NoSession}]
|
||||||
|
/\ terminalLastAuthority \in [Sessions -> TerminalAuthorities]
|
||||||
|
/\ terminalLastAdministrativeAuthorityValid \in [Sessions -> BOOLEAN]
|
||||||
|
/\ terminalLastDisposition \in [Sessions -> TerminalDispositions]
|
||||||
|
/\ terminalLastDestination \in [Sessions -> Sessions \cup {NoSession}]
|
||||||
|
/\ terminalLastTarget \in [Sessions -> TerminalTargets]
|
||||||
|
/\ terminalLastByteDeliveries \in [Sessions -> 0..1]
|
||||||
|
/\ terminalLastSignalDeliveries \in [Sessions -> 0..1]
|
||||||
|
/\ terminalLastLocalDeliveries \in [Sessions -> 0..1]
|
||||||
|
/\ terminalLastMetadataDeliveries \in [Sessions -> 0..1]
|
||||||
|
/\ sessionClientSuspended \in [Sessions -> BOOLEAN]
|
||||||
|
/\ sessionTerminalTransportState \in [Sessions -> TerminalTransportStates]
|
||||||
|
|
||||||
SessionTerminalPhysicalConsistency ==
|
SessionTerminalPhysicalConsistency ==
|
||||||
\A s \in Sessions :
|
\A s \in Sessions :
|
||||||
|
|
@ -2375,6 +2726,38 @@ TerminalIsolation ==
|
||||||
\A s \in Sessions : sessionPhase[s] = "Prompting" =>
|
\A s \in Sessions : sessionPhase[s] = "Prompting" =>
|
||||||
terminalRoute[s] = "Prompt"
|
terminalRoute[s] = "Prompt"
|
||||||
|
|
||||||
|
ObservedTerminalDelivery(s) ==
|
||||||
|
TerminalDelivery(
|
||||||
|
terminalLastDisposition[s],
|
||||||
|
terminalLastDestination[s],
|
||||||
|
terminalLastTarget[s],
|
||||||
|
terminalLastByteDeliveries[s],
|
||||||
|
terminalLastSignalDeliveries[s],
|
||||||
|
terminalLastLocalDeliveries[s],
|
||||||
|
terminalLastMetadataDeliveries[s])
|
||||||
|
|
||||||
|
TerminalInteractionAuthoritySeparated ==
|
||||||
|
\A s \in Sessions :
|
||||||
|
/\ terminalEventIndex[s] = terminalLastEventId[s] + 1
|
||||||
|
/\ IF terminalLastEventId[s] = 0
|
||||||
|
THEN /\ terminalLastEvent[s] = "None"
|
||||||
|
/\ terminalLastSourceSession[s] = NoSession
|
||||||
|
/\ terminalLastAuthority[s] = "None"
|
||||||
|
/\ ~terminalLastAdministrativeAuthorityValid[s]
|
||||||
|
/\ ObservedTerminalDelivery(s) = NoTerminalDelivery
|
||||||
|
ELSE LET event == TerminalEventPlan[s][terminalLastEventId[s]]
|
||||||
|
authority == TerminalAuthorityPlan[s][terminalLastEventId[s]]
|
||||||
|
administrativeAuthorityValid ==
|
||||||
|
TerminalAdministrativeAuthorityValid[s][terminalLastEventId[s]]
|
||||||
|
IN /\ terminalLastEvent[s] = event
|
||||||
|
/\ terminalLastSourceSession[s] = s
|
||||||
|
/\ terminalLastAuthority[s] = authority
|
||||||
|
/\ terminalLastAdministrativeAuthorityValid[s] =
|
||||||
|
administrativeAuthorityValid
|
||||||
|
/\ ObservedTerminalDelivery(s) =
|
||||||
|
ExpectedTerminalDelivery(
|
||||||
|
s, event, authority, administrativeAuthorityValid)
|
||||||
|
|
||||||
NoOrphanHostProcess ==
|
NoOrphanHostProcess ==
|
||||||
\A r \in hostRunning :
|
\A r \in hostRunning :
|
||||||
LET s == ReqSession(r) IN
|
LET s == ReqSession(r) IN
|
||||||
|
|
@ -2544,6 +2927,7 @@ Safety ==
|
||||||
/\ HostExecutionAuthorized
|
/\ HostExecutionAuthorized
|
||||||
/\ AutoApprovalNoShell
|
/\ AutoApprovalNoShell
|
||||||
/\ TerminalIsolation
|
/\ TerminalIsolation
|
||||||
|
/\ TerminalInteractionAuthoritySeparated
|
||||||
/\ NoOrphanHostProcess
|
/\ NoOrphanHostProcess
|
||||||
/\ StateAnchorOwnership
|
/\ StateAnchorOwnership
|
||||||
/\ FailedDomainIsolation
|
/\ FailedDomainIsolation
|
||||||
|
|
@ -2551,6 +2935,65 @@ Safety ==
|
||||||
/\ ResultDeliveryStateConsistent
|
/\ ResultDeliveryStateConsistent
|
||||||
/\ NetworkReadinessBoundToSandbox
|
/\ NetworkReadinessBoundToSandbox
|
||||||
|
|
||||||
|
TerminalEventAdvanced(s) ==
|
||||||
|
/\ terminalLastEventId'[s] = terminalEventIndex[s]
|
||||||
|
/\ terminalEventIndex'[s] = terminalEventIndex[s] + 1
|
||||||
|
|
||||||
|
TerminalSessionProjection(s) == <<
|
||||||
|
sessionPhase[s], terminalRoute[s], connectionState[s], activeRequest[s],
|
||||||
|
sessionTerminalState[s], sessionPtyOpen[s], sessionExecPresent[s],
|
||||||
|
sessionGuestKnown[s], terminalEventIndex[s], terminalLastEventId[s],
|
||||||
|
terminalLastEvent[s], terminalLastSourceSession[s],
|
||||||
|
terminalLastAuthority[s], terminalLastAdministrativeAuthorityValid[s],
|
||||||
|
terminalLastDisposition[s],
|
||||||
|
terminalLastDestination[s], terminalLastTarget[s],
|
||||||
|
terminalLastByteDeliveries[s], terminalLastSignalDeliveries[s],
|
||||||
|
terminalLastLocalDeliveries[s], terminalLastMetadataDeliveries[s],
|
||||||
|
sessionClientSuspended[s], sessionTerminalTransportState[s]
|
||||||
|
>>
|
||||||
|
|
||||||
|
DomainRuntimeProjection(d) == <<
|
||||||
|
domainPhase[d], stateAnchorState[d], sidecarState[d], sandboxState[d],
|
||||||
|
trustReady[d], domainLockHeld[d], hostCoordinatorProc[d],
|
||||||
|
runtimeSupervisorProc[d], attachedRunscProc[d], runtimeCausalEdge[d],
|
||||||
|
supervisorLease[d], domainGeneration[d], durableDecision[d],
|
||||||
|
durableIntent[d], genCoordinatorId[d], genSidecarId[d], genSandboxId[d],
|
||||||
|
networkReady[d], preparedLowerLeased[d], helperProc[d]
|
||||||
|
>>
|
||||||
|
|
||||||
|
TerminalPeerIsolationAction ==
|
||||||
|
\A s \in Sessions :
|
||||||
|
TerminalEventAdvanced(s) =>
|
||||||
|
\A t \in Sessions \ {s} : UNCHANGED TerminalSessionProjection(t)
|
||||||
|
|
||||||
|
TerminalPeerIsolation ==
|
||||||
|
[][TerminalPeerIsolationAction]_vars
|
||||||
|
|
||||||
|
LocalTerminalControlKinds == {
|
||||||
|
"LocalSuspend", "LocalResume", "LocalDisconnect", "HostSignal"
|
||||||
|
}
|
||||||
|
|
||||||
|
TerminalLocalControlPreservesDomainAction ==
|
||||||
|
\A s \in Sessions :
|
||||||
|
/\ TerminalEventAdvanced(s)
|
||||||
|
/\ CurrentTerminalEvent(s) \in LocalTerminalControlKinds
|
||||||
|
/\ \E t \in Sessions \ {s} : connectionState[t] = "Connected"
|
||||||
|
=> UNCHANGED DomainRuntimeProjection(Dom(s))
|
||||||
|
|
||||||
|
TerminalLocalControlPreservesDomain ==
|
||||||
|
[][TerminalLocalControlPreservesDomainAction]_vars
|
||||||
|
|
||||||
|
LocalTerminationAvailableWhileTransportBlocked ==
|
||||||
|
\A s \in Sessions :
|
||||||
|
/\ sessionTerminalTransportState[s] = "Blocked"
|
||||||
|
/\ sessionPhase[s] = "Attached"
|
||||||
|
/\ connectionState[s] = "Connected"
|
||||||
|
/\ sessionTerminalState[s] \in {"Intent", "Running"}
|
||||||
|
/\ TerminalEventAvailable(s)
|
||||||
|
/\ CurrentTerminalEvent(s) \in {"LocalDisconnect", "HostSignal"}
|
||||||
|
=> ENABLED DisconnectTerminalFromLocalAuthority(
|
||||||
|
s, CurrentTerminalEvent(s))
|
||||||
|
|
||||||
(***************************************************************************
|
(***************************************************************************
|
||||||
Liveness properties.
|
Liveness properties.
|
||||||
|
|
||||||
|
|
|
||||||
67
docs/protocol/LazaretTerminalLocalControl.cfg
Normal file
67
docs/protocol/LazaretTerminalLocalControl.cfg
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
CONSTANTS
|
||||||
|
D1 = d1
|
||||||
|
S1 = s1
|
||||||
|
S2 = s2
|
||||||
|
R1 = r1
|
||||||
|
R2 = r2
|
||||||
|
R3 = r3
|
||||||
|
ExactCmd = exactCmd
|
||||||
|
PromptCmd = promptCmd
|
||||||
|
ShellCmd = shellCmd
|
||||||
|
EditedCmd = editedCmd
|
||||||
|
Identities <- IdentitiesFixture
|
||||||
|
SessionAnchors <- SessionAnchorsFixture
|
||||||
|
Domains <- DomainsFixture
|
||||||
|
Sessions <- SessionsFixture
|
||||||
|
Requests <- RequestsFixture
|
||||||
|
Commands <- CommandsFixture
|
||||||
|
NoSession = NoSession
|
||||||
|
NoRequest = NoRequest
|
||||||
|
NoCommand = NoCommand
|
||||||
|
NoApproval = NoApproval
|
||||||
|
SessionDomain <- SessionDomainFixture
|
||||||
|
SessionFingerprint <- SessionFingerprintFixture
|
||||||
|
DomainFingerprint <- DomainFingerprintFixture
|
||||||
|
DomainCoordinatorIdentity <- DomainCoordinatorIdentityFixture
|
||||||
|
DomainSidecarIdentity <- DomainSidecarIdentityFixture
|
||||||
|
DomainSandboxIdentity <- DomainSandboxIdentityFixture
|
||||||
|
SessionCliIdentity <- SessionCliIdentityFixture
|
||||||
|
SessionAnchorIdentity <- SessionAnchorIdentityFixture
|
||||||
|
CoordinatorCertificateValid <- CoordinatorCertificateValidFixture
|
||||||
|
SidecarCertificateValid <- SidecarCertificateValidFixture
|
||||||
|
SandboxCertificateValid <- SandboxCertificateValidFixture
|
||||||
|
CliCertificateValid <- CliCertificateValidFixture
|
||||||
|
ConfigSafe <- ConfigSafeFixture
|
||||||
|
SandboxIsolationSafe <- SandboxIsolationSafeFixture
|
||||||
|
RequestSession <- RequestSessionFixture
|
||||||
|
RequestCommand <- RequestCommandFixture
|
||||||
|
RequestSandboxIdentity <- RequestSandboxIdentityFixture
|
||||||
|
RequestCliIdentity <- RequestCliIdentityFixture
|
||||||
|
RequestSessionAnchor <- RequestSessionAnchorFixture
|
||||||
|
RequestCredentialValid <- RequestCredentialValidFixture
|
||||||
|
RequestSignatureValid <- RequestSignatureValidFixture
|
||||||
|
ApprovalCliIdentity <- ApprovalCliIdentityFixture
|
||||||
|
ApprovalSessionAnchor <- ApprovalSessionAnchorFixture
|
||||||
|
ApprovalSignatureValid <- ApprovalSignatureValidFixture
|
||||||
|
ApprovalCommand <- ApprovalCommandFixture
|
||||||
|
AutoRuleMatches <- AutoRuleMatchesFixture
|
||||||
|
CommandRequiresShell <- CommandRequiresShellFixture
|
||||||
|
CommandContentSafe <- CommandContentSafeFixture
|
||||||
|
TerminalEventPlan <- TerminalLocalControlEventPlanFixture
|
||||||
|
TerminalAuthorityPlan <- TerminalLocalControlAuthorityPlanFixture
|
||||||
|
TerminalAdministrativeAuthorityValid <-
|
||||||
|
TerminalLocalControlAdministrativeAuthorityValidFixture
|
||||||
|
TerminalRoutingFault = "Correct"
|
||||||
|
|
||||||
|
SPECIFICATION SafetySpec
|
||||||
|
CHECK_DEADLOCK FALSE
|
||||||
|
|
||||||
|
INVARIANTS
|
||||||
|
TypeOK
|
||||||
|
SessionTerminalPhysicalConsistency
|
||||||
|
TerminalInteractionAuthoritySeparated
|
||||||
|
LocalTerminationAvailableWhileTransportBlocked
|
||||||
|
|
||||||
|
PROPERTIES
|
||||||
|
TerminalPeerIsolation
|
||||||
|
TerminalLocalControlPreservesDomain
|
||||||
66
docs/protocol/LazaretTerminalPeerIsolation.cfg
Normal file
66
docs/protocol/LazaretTerminalPeerIsolation.cfg
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
CONSTANTS
|
||||||
|
D1 = d1
|
||||||
|
S1 = s1
|
||||||
|
S2 = s2
|
||||||
|
R1 = r1
|
||||||
|
R2 = r2
|
||||||
|
R3 = r3
|
||||||
|
ExactCmd = exactCmd
|
||||||
|
PromptCmd = promptCmd
|
||||||
|
ShellCmd = shellCmd
|
||||||
|
EditedCmd = editedCmd
|
||||||
|
Identities <- IdentitiesFixture
|
||||||
|
SessionAnchors <- SessionAnchorsFixture
|
||||||
|
Domains <- DomainsFixture
|
||||||
|
Sessions <- SessionsFixture
|
||||||
|
Requests <- RequestsFixture
|
||||||
|
Commands <- CommandsFixture
|
||||||
|
NoSession = NoSession
|
||||||
|
NoRequest = NoRequest
|
||||||
|
NoCommand = NoCommand
|
||||||
|
NoApproval = NoApproval
|
||||||
|
SessionDomain <- SessionDomainFixture
|
||||||
|
SessionFingerprint <- SessionFingerprintFixture
|
||||||
|
DomainFingerprint <- DomainFingerprintFixture
|
||||||
|
DomainCoordinatorIdentity <- DomainCoordinatorIdentityFixture
|
||||||
|
DomainSidecarIdentity <- DomainSidecarIdentityFixture
|
||||||
|
DomainSandboxIdentity <- DomainSandboxIdentityFixture
|
||||||
|
SessionCliIdentity <- SessionCliIdentityFixture
|
||||||
|
SessionAnchorIdentity <- SessionAnchorIdentityFixture
|
||||||
|
CoordinatorCertificateValid <- CoordinatorCertificateValidFixture
|
||||||
|
SidecarCertificateValid <- SidecarCertificateValidFixture
|
||||||
|
SandboxCertificateValid <- SandboxCertificateValidFixture
|
||||||
|
CliCertificateValid <- CliCertificateValidFixture
|
||||||
|
ConfigSafe <- ConfigSafeFixture
|
||||||
|
SandboxIsolationSafe <- SandboxIsolationSafeFixture
|
||||||
|
RequestSession <- RequestSessionFixture
|
||||||
|
RequestCommand <- RequestCommandFixture
|
||||||
|
RequestSandboxIdentity <- RequestSandboxIdentityFixture
|
||||||
|
RequestCliIdentity <- RequestCliIdentityFixture
|
||||||
|
RequestSessionAnchor <- RequestSessionAnchorFixture
|
||||||
|
RequestCredentialValid <- RequestCredentialValidFixture
|
||||||
|
RequestSignatureValid <- RequestSignatureValidFixture
|
||||||
|
ApprovalCliIdentity <- ApprovalCliIdentityFixture
|
||||||
|
ApprovalSessionAnchor <- ApprovalSessionAnchorFixture
|
||||||
|
ApprovalSignatureValid <- ApprovalSignatureValidFixture
|
||||||
|
ApprovalCommand <- ApprovalCommandFixture
|
||||||
|
AutoRuleMatches <- AutoRuleMatchesFixture
|
||||||
|
CommandRequiresShell <- CommandRequiresShellFixture
|
||||||
|
CommandContentSafe <- CommandContentSafeFixture
|
||||||
|
TerminalEventPlan <- TerminalRoutingEventPlanFixture
|
||||||
|
TerminalAuthorityPlan <- TerminalRoutingAuthorityPlanFixture
|
||||||
|
TerminalAdministrativeAuthorityValid <-
|
||||||
|
TerminalRoutingAdministrativeAuthorityValidFixture
|
||||||
|
TerminalRoutingFault = "Correct"
|
||||||
|
|
||||||
|
SPECIFICATION SafetySpec
|
||||||
|
CHECK_DEADLOCK FALSE
|
||||||
|
|
||||||
|
INVARIANTS
|
||||||
|
TypeOK
|
||||||
|
SessionTerminalPhysicalConsistency
|
||||||
|
TerminalInteractionAuthoritySeparated
|
||||||
|
LocalTerminationAvailableWhileTransportBlocked
|
||||||
|
|
||||||
|
PROPERTIES
|
||||||
|
TerminalPeerIsolation
|
||||||
105
docs/protocol/LazaretTerminalSafety.cfg
Normal file
105
docs/protocol/LazaretTerminalSafety.cfg
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
CONSTANTS
|
||||||
|
D1 = d1
|
||||||
|
S1 = s1
|
||||||
|
S2 = s2
|
||||||
|
R1 = r1
|
||||||
|
R2 = r2
|
||||||
|
R3 = r3
|
||||||
|
ExactCmd = exactCmd
|
||||||
|
PromptCmd = promptCmd
|
||||||
|
ShellCmd = shellCmd
|
||||||
|
EditedCmd = editedCmd
|
||||||
|
Identities <- IdentitiesFixture
|
||||||
|
SessionAnchors <- SessionAnchorsFixture
|
||||||
|
Domains <- DomainsFixture
|
||||||
|
Sessions <- SessionsFixture
|
||||||
|
Requests <- RequestsFixture
|
||||||
|
Commands <- CommandsFixture
|
||||||
|
NoSession = NoSession
|
||||||
|
NoRequest = NoRequest
|
||||||
|
NoCommand = NoCommand
|
||||||
|
NoApproval = NoApproval
|
||||||
|
SessionDomain <- SessionDomainFixture
|
||||||
|
SessionFingerprint <- SessionFingerprintFixture
|
||||||
|
DomainFingerprint <- DomainFingerprintFixture
|
||||||
|
DomainCoordinatorIdentity <- DomainCoordinatorIdentityFixture
|
||||||
|
DomainSidecarIdentity <- DomainSidecarIdentityFixture
|
||||||
|
DomainSandboxIdentity <- DomainSandboxIdentityFixture
|
||||||
|
SessionCliIdentity <- SessionCliIdentityFixture
|
||||||
|
SessionAnchorIdentity <- SessionAnchorIdentityFixture
|
||||||
|
CoordinatorCertificateValid <- CoordinatorCertificateValidFixture
|
||||||
|
SidecarCertificateValid <- SidecarCertificateValidFixture
|
||||||
|
SandboxCertificateValid <- SandboxCertificateValidFixture
|
||||||
|
CliCertificateValid <- CliCertificateValidFixture
|
||||||
|
ConfigSafe <- ConfigSafeFixture
|
||||||
|
SandboxIsolationSafe <- SandboxIsolationSafeFixture
|
||||||
|
RequestSession <- RequestSessionFixture
|
||||||
|
RequestCommand <- RequestCommandFixture
|
||||||
|
RequestSandboxIdentity <- RequestSandboxIdentityFixture
|
||||||
|
RequestCliIdentity <- RequestCliIdentityFixture
|
||||||
|
RequestSessionAnchor <- RequestSessionAnchorFixture
|
||||||
|
RequestCredentialValid <- RequestCredentialValidFixture
|
||||||
|
RequestSignatureValid <- RequestSignatureValidFixture
|
||||||
|
ApprovalCliIdentity <- ApprovalCliIdentityFixture
|
||||||
|
ApprovalSessionAnchor <- ApprovalSessionAnchorFixture
|
||||||
|
ApprovalSignatureValid <- ApprovalSignatureValidFixture
|
||||||
|
ApprovalCommand <- ApprovalCommandFixture
|
||||||
|
AutoRuleMatches <- AutoRuleMatchesFixture
|
||||||
|
CommandRequiresShell <- CommandRequiresShellFixture
|
||||||
|
CommandContentSafe <- CommandContentSafeFixture
|
||||||
|
TerminalEventPlan <- TerminalEventPlanFixture
|
||||||
|
TerminalAuthorityPlan <- TerminalAuthorityPlanFixture
|
||||||
|
TerminalAdministrativeAuthorityValid <-
|
||||||
|
TerminalAdministrativeAuthorityValidFixture
|
||||||
|
TerminalRoutingFault = "Correct"
|
||||||
|
|
||||||
|
SPECIFICATION SafetySpec
|
||||||
|
CHECK_DEADLOCK FALSE
|
||||||
|
|
||||||
|
INVARIANTS
|
||||||
|
TypeOK
|
||||||
|
SessionTerminalPhysicalConsistency
|
||||||
|
ConfigurationConfinement
|
||||||
|
SandboxNamespaceIsolation
|
||||||
|
OrderedNetworkStartup
|
||||||
|
PublishedDomainsReady
|
||||||
|
DomainLockLifetime
|
||||||
|
RuntimeCausalEdgeArmedBeforeSandbox
|
||||||
|
RuntimeCausalEdgeOwnerPresent
|
||||||
|
SandboxRunningImpliesCoordinatorPresent
|
||||||
|
PublishedRuntimeAuthorityPresent
|
||||||
|
SupervisorLeaseConsistency
|
||||||
|
RuntimeResourceOwnership
|
||||||
|
CoordinatorPhysicalConsistency
|
||||||
|
HostCoordinatorRequiresDomainOwnership
|
||||||
|
NoVanishPresentRuntime
|
||||||
|
OrderedLeaseTeardown
|
||||||
|
DomainGenerationBounds
|
||||||
|
DurableIntentBeforeSandboxReady
|
||||||
|
DurableDecisionPublicationConsistent
|
||||||
|
PathMismatchNotAdopted
|
||||||
|
ExclusiveBootstrapOwnership
|
||||||
|
TeardownNotJoinable
|
||||||
|
RegisteredSessionsConnected
|
||||||
|
AttachedSessionsValid
|
||||||
|
AuthenticatedRequestsOnly
|
||||||
|
RuntimeRoleIdentitySeparation
|
||||||
|
RegisteredSessionIdentityUniqueness
|
||||||
|
LiveRequestIdentityAuthorized
|
||||||
|
DeveloperApprovalAuthenticated
|
||||||
|
HostExecutionAuthorized
|
||||||
|
AutoApprovalNoShell
|
||||||
|
TerminalIsolation
|
||||||
|
TerminalInteractionAuthoritySeparated
|
||||||
|
LocalTerminationAvailableWhileTransportBlocked
|
||||||
|
NoOrphanHostProcess
|
||||||
|
StateAnchorOwnership
|
||||||
|
FailedDomainIsolation
|
||||||
|
OrderedFailureRecovery
|
||||||
|
ResultDeliveryStateConsistent
|
||||||
|
MultiRoleDurableIntent
|
||||||
|
NetworkReadinessBoundToSandbox
|
||||||
|
GenerationScopedIdentitiesDistinct
|
||||||
|
HelperUnderSupervisor
|
||||||
|
PreparedLowerLeaseBeforeMount
|
||||||
|
NetworkReadyBeforePublish
|
||||||
|
|
@ -703,18 +703,89 @@ class VerificationTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_model_paths_are_current_and_complete(self) -> None:
|
def test_model_paths_are_current_and_complete(self) -> None:
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{module.name for module, _ in VERIFY.MODEL_CONFIGURATIONS},
|
|
||||||
{
|
{
|
||||||
|
(module.name, config.name)
|
||||||
|
for module, config in VERIFY.MODEL_CONFIGURATIONS
|
||||||
|
},
|
||||||
|
{
|
||||||
|
(
|
||||||
"IgnoredWorkspaceHardlinkRouting.tla",
|
"IgnoredWorkspaceHardlinkRouting.tla",
|
||||||
"IgnoredWorkspaceRouting.tla",
|
"IgnoredWorkspaceHardlinkRouting.cfg",
|
||||||
"Lazaret.tla",
|
),
|
||||||
"PreparedLower.tla",
|
("IgnoredWorkspaceRouting.tla", "IgnoredWorkspaceRouting.cfg"),
|
||||||
|
("Lazaret.tla", "Lazaret.cfg"),
|
||||||
|
("Lazaret.tla", "LazaretTerminalLocalControl.cfg"),
|
||||||
|
("Lazaret.tla", "LazaretTerminalPeerIsolation.cfg"),
|
||||||
|
("Lazaret.tla", "LazaretTerminalSafety.cfg"),
|
||||||
|
("PreparedLower.tla", "PreparedLower.cfg"),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
for module, config in VERIFY.MODEL_CONFIGURATIONS:
|
for module, config in VERIFY.MODEL_CONFIGURATIONS:
|
||||||
self.assertTrue(module.is_file())
|
self.assertTrue(module.is_file())
|
||||||
self.assertTrue(config.is_file())
|
self.assertTrue(config.is_file())
|
||||||
|
|
||||||
|
def test_model_metadata_directories_are_unique_per_configuration(self) -> None:
|
||||||
|
commands = []
|
||||||
|
manager = mock.MagicMock()
|
||||||
|
manager.__enter__.return_value = "/verification"
|
||||||
|
manager.__exit__.return_value = False
|
||||||
|
with (
|
||||||
|
mock.patch.object(VERIFY.shutil, "which", return_value="/usr/bin/tlc"),
|
||||||
|
mock.patch.object(VERIFY, "temporary_directory", return_value=manager),
|
||||||
|
mock.patch.object(
|
||||||
|
VERIFY,
|
||||||
|
"run",
|
||||||
|
side_effect=lambda command, cwd: commands.append(command),
|
||||||
|
),
|
||||||
|
):
|
||||||
|
VERIFY.run_models()
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[
|
||||||
|
(
|
||||||
|
Path(command[-1]).name,
|
||||||
|
Path(command[command.index("-config") + 1]).name,
|
||||||
|
)
|
||||||
|
for command in commands
|
||||||
|
],
|
||||||
|
[
|
||||||
|
(module.name, config.name)
|
||||||
|
for module, config in VERIFY.MODEL_CONFIGURATIONS
|
||||||
|
],
|
||||||
|
)
|
||||||
|
metadata = [command[command.index("-metadir") + 1] for command in commands]
|
||||||
|
self.assertEqual(len(metadata), len(set(metadata)))
|
||||||
|
self.assertEqual(
|
||||||
|
[Path(path).name for path in metadata],
|
||||||
|
[
|
||||||
|
f"{module.stem}-{config.stem}"
|
||||||
|
for module, config in VERIFY.MODEL_CONFIGURATIONS
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_lazaret_terminal_configs_retain_common_constants(self) -> None:
|
||||||
|
configs = [
|
||||||
|
ROOT / "docs/protocol/Lazaret.cfg",
|
||||||
|
ROOT / "docs/protocol/LazaretTerminalSafety.cfg",
|
||||||
|
ROOT / "docs/protocol/LazaretTerminalPeerIsolation.cfg",
|
||||||
|
ROOT / "docs/protocol/LazaretTerminalLocalControl.cfg",
|
||||||
|
]
|
||||||
|
prefixes = {
|
||||||
|
config.read_text().partition(" TerminalEventPlan <-")[0]
|
||||||
|
for config in configs
|
||||||
|
}
|
||||||
|
self.assertEqual(len(prefixes), 1)
|
||||||
|
|
||||||
|
def test_lazaret_full_event_safety_retains_canonical_invariants(self) -> None:
|
||||||
|
def invariants(config: Path) -> tuple[str, ...]:
|
||||||
|
body = config.read_text().split("INVARIANTS\n", 1)[1]
|
||||||
|
return tuple(body.split("\n\n", 1)[0].split())
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
invariants(ROOT / "docs/protocol/LazaretTerminalSafety.cfg"),
|
||||||
|
invariants(ROOT / "docs/protocol/Lazaret.cfg"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,18 @@ MATERIALIZED_FUSER_MANIFEST = (
|
||||||
).resolve()
|
).resolve()
|
||||||
MODEL_CONFIGURATIONS = (
|
MODEL_CONFIGURATIONS = (
|
||||||
(ROOT / "docs/protocol/Lazaret.tla", ROOT / "docs/protocol/Lazaret.cfg"),
|
(ROOT / "docs/protocol/Lazaret.tla", ROOT / "docs/protocol/Lazaret.cfg"),
|
||||||
|
(
|
||||||
|
ROOT / "docs/protocol/Lazaret.tla",
|
||||||
|
ROOT / "docs/protocol/LazaretTerminalSafety.cfg",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ROOT / "docs/protocol/Lazaret.tla",
|
||||||
|
ROOT / "docs/protocol/LazaretTerminalPeerIsolation.cfg",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
ROOT / "docs/protocol/Lazaret.tla",
|
||||||
|
ROOT / "docs/protocol/LazaretTerminalLocalControl.cfg",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
ROOT / "docs/protocol/IgnoredWorkspaceRouting.tla",
|
ROOT / "docs/protocol/IgnoredWorkspaceRouting.tla",
|
||||||
ROOT / "docs/protocol/IgnoredWorkspaceRouting.cfg",
|
ROOT / "docs/protocol/IgnoredWorkspaceRouting.cfg",
|
||||||
|
|
@ -613,7 +625,7 @@ def run_models() -> None:
|
||||||
for module, config in MODEL_CONFIGURATIONS:
|
for module, config in MODEL_CONFIGURATIONS:
|
||||||
require(module.is_file(), f"missing model: {module.relative_to(ROOT)}")
|
require(module.is_file(), f"missing model: {module.relative_to(ROOT)}")
|
||||||
require(config.is_file(), f"missing model config: {config.relative_to(ROOT)}")
|
require(config.is_file(), f"missing model config: {config.relative_to(ROOT)}")
|
||||||
metadata = workdir / module.stem
|
metadata = workdir / f"{module.stem}-{config.stem}"
|
||||||
run(
|
run(
|
||||||
[
|
[
|
||||||
tlc,
|
tlc,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue