1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//! Session durable-config authority — shell adapter over the canonical
//! [`crate::generated::session_document::SessionDocumentMachineAuthority`].
//!
//! Every SEMANTIC admission decision for durable session config lives in the
//! canonical machine's durable-config region (folded from the retired
//! `SessionDurableConfigAuthorityMachine` under LUC-524, P0 Dogma Invariant 1):
//!
//! - metadata-persist admission (`schema_version > 0 && model_present`),
//! - build-state-persist consistency admission (mob-tool authority context
//! must be absent or generated-authority),
//! - build-state restore authorization (the recovery half of the same fact).
//!
//! This module performs only the MECHANICAL work the DSL cannot express: it
//! extracts the typed facts the machine's verdict actually reads from the bulky
//! [`SessionMetadata`] and [`SessionBuildState`] records, feeds exactly those
//! facts to the machine, then mirrors the machine's admit/reject
//! verdict. It NEVER decides admission itself, and it passes the original typed
//! value through unchanged on admit — no fact is pre-reduced before the machine
//! sees it. The shell does not mirror the full record into machine inputs: a
//! field the verdict never branches on is not an authority input.
use crate::generated::session_document::{self, SessionDocumentEffect, SessionDocumentError};
use crate::{SessionBuildState, SessionMetadata};
/// Error surfaced when the canonical machine rejects a durable-config request.
///
/// Carries the rejection message produced by the canonical
/// [`crate::generated::session_document::SessionDocumentMachineAuthority`], so callers
/// keep a stable durable-config error type while the underlying authority is
/// the canonical session-document machine.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SessionDurableConfigAuthorityError {
message: String,
}
impl std::fmt::Display for SessionDurableConfigAuthorityError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.message)
}
}
impl std::error::Error for SessionDurableConfigAuthorityError {}
impl From<SessionDocumentError> for SessionDurableConfigAuthorityError {
fn from(inner: SessionDocumentError) -> Self {
Self {
message: inner.to_string(),
}
}
}
/// Metadata whose persist the canonical machine has authorized.
#[derive(Debug, Clone)]
pub struct AuthorizedSessionMetadata {
metadata: SessionMetadata,
}
impl AuthorizedSessionMetadata {
#[must_use]
pub fn into_metadata(self) -> SessionMetadata {
self.metadata
}
}
/// Build state whose persist the canonical machine has authorized.
#[derive(Debug, Clone)]
pub struct AuthorizedSessionBuildState {
state: SessionBuildState,
}
impl AuthorizedSessionBuildState {
#[must_use]
pub fn into_state(self) -> SessionBuildState {
self.state
}
}
fn document_authority() -> session_document::SessionDocumentMachineAuthority {
session_document::SessionDocumentMachineAuthority::new()
}
/// Drive the metadata-persist admission transition. Mirrors the machine verdict.
fn drive_metadata_persist(
metadata: &SessionMetadata,
) -> Result<(), SessionDurableConfigAuthorityError> {
let mut authority = document_authority();
let effects = authority.authorize_session_metadata_persist(
u64::from(metadata.schema_version),
!metadata.model.trim().is_empty(),
)?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SessionMetadataPersistAuthorized
)
})
}
/// Drive the build-state-persist admission transition.
fn drive_build_state_persist(
state: &SessionBuildState,
) -> Result<(), SessionDurableConfigAuthorityError> {
let mob_tool_authority_context_present = state.mob_tool_authority_context.is_some();
let mob_tool_authority_context_generated = state
.mob_tool_authority_context
.as_ref()
.is_some_and(|context| context.is_generated_authority_context());
let mut authority = document_authority();
let effects = authority.authorize_session_build_state_persist(
mob_tool_authority_context_present,
mob_tool_authority_context_generated,
)?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SessionBuildStatePersistAuthorized
)
})
}
/// Drive the build-state restore authorization transition. The machine's
/// restore guard is `Ready`-only — it reads no build-state facts — so this
/// drives the transition without threading the (shell-retained) snapshot.
fn drive_build_state_restore() -> Result<(), SessionDurableConfigAuthorityError> {
let mut authority = document_authority();
let effects = authority.restore_session_build_state()?;
expect_effect(&effects, |effect| {
matches!(
effect,
SessionDocumentEffect::SessionBuildStateRestoreAuthorized
)
})
}
/// Confirm the machine emitted the expected authorization effect.
///
/// A rejected request matched no transition and already surfaced as `Err`
/// above; this guards against an emitter that drove a different effect.
fn expect_effect(
effects: &[SessionDocumentEffect],
matches_expected: impl Fn(&SessionDocumentEffect) -> bool,
) -> Result<(), SessionDurableConfigAuthorityError> {
if !effects.is_empty() && effects.iter().all(matches_expected) {
Ok(())
} else {
Err(SessionDurableConfigAuthorityError {
message:
"generated session document authority emitted no durable-config authorization effect"
.to_string(),
})
}
}
/// Authorize a session-metadata persist through the canonical machine,
/// stamping the current schema version first.
pub fn authorize_session_metadata_persist(
mut metadata: SessionMetadata,
) -> Result<AuthorizedSessionMetadata, SessionDurableConfigAuthorityError> {
metadata.schema_version = crate::session_metadata_schema_version();
drive_metadata_persist(&metadata)?;
Ok(AuthorizedSessionMetadata { metadata })
}
/// Authorize restore of persisted session metadata through the canonical
/// machine (same admission contract as persist).
pub fn restore_session_metadata(
metadata: SessionMetadata,
) -> Result<SessionMetadata, SessionDurableConfigAuthorityError> {
drive_metadata_persist(&metadata)?;
Ok(metadata)
}
/// Authorize a session-build-state persist through the canonical machine.
pub fn authorize_session_build_state_persist(
state: SessionBuildState,
) -> Result<AuthorizedSessionBuildState, SessionDurableConfigAuthorityError> {
drive_build_state_persist(&state)?;
Ok(AuthorizedSessionBuildState { state })
}
/// Authorize restore of persisted session build state through the canonical
/// machine.
pub fn restore_session_build_state(
state: SessionBuildState,
) -> Result<SessionBuildState, SessionDurableConfigAuthorityError> {
drive_build_state_restore()?;
Ok(state)
}