Skip to main content

liminal_protocol/wire/authority/
records.rs

1//! Response authorities bound to `ClientRequest::RecordAdmission` (`0x0007`)
2//! and `ClientRequest::ObserverRecovery` (`0x0008`).
3
4use alloc::boxed::Box;
5
6use super::super::{
7    ConnectionConversationCapacityExceeded, ConversationId, ConversationOrderExhausted,
8    ConversationSequenceExhausted, InvalidObserverEpoch, InvalidObserverEpochList,
9    MarkerClosureCapacityExceeded, NoBinding, ObserverBackpressure, ObserverRecoveryAccepted,
10    ParticipantUnknown, RecordAdmissionEnvelope, RecordCommitted, RecordTooLarge, ResponseEnvelope,
11    Retired, ServerDiscriminant, ServerValue, StaleAuthority,
12};
13
14/// Server response bound to one ordinary record admission.
15///
16/// Constructors exist only for the outcomes the frozen R-D1 register admits
17/// for ordinary admission; every other pairing is a compile error by
18/// construction.
19#[derive(Clone, Debug, PartialEq, Eq)]
20pub struct RecordAdmissionResponse {
21    value: ServerValue,
22}
23
24impl RecordAdmissionResponse {
25    /// First decoded semantic operation for an untracked conversation
26    /// exceeded the connection-conversation limit (register row 5641).
27    #[must_use]
28    pub const fn connection_conversation_capacity_exceeded(
29        request: RecordAdmissionEnvelope,
30        limit: u64,
31    ) -> Self {
32        Self {
33            value: ServerValue::ConnectionConversationCapacityExceeded(
34                ConnectionConversationCapacityExceeded::SemanticRequest {
35                    request: ResponseEnvelope::RecordAdmission(request),
36                    limit,
37                },
38            ),
39        }
40    }
41
42    /// Ordinary admission required an unreserved `transaction_order` major
43    /// and the conversation order is exhausted (register row 5644).
44    ///
45    /// The payload is minted only by the shared order allocator invoked with
46    /// this request's own envelope.
47    pub(crate) const fn from_conversation_order_exhausted(
48        value: Box<ConversationOrderExhausted>,
49    ) -> Self {
50        Self {
51            value: ServerValue::ConversationOrderExhausted(value),
52        }
53    }
54
55    /// Presented participant is unknown (register row 5645).
56    ///
57    /// The payload is minted only by `lookup_binding_required` for this
58    /// exact request.
59    pub(crate) const fn from_participant_unknown(value: ParticipantUnknown) -> Self {
60        Self {
61            value: ServerValue::ParticipantUnknown(value),
62        }
63    }
64
65    /// Exact-binding lookup missed (register row 5646).
66    ///
67    /// The payload is minted only by `lookup_binding_required` for this
68    /// exact request.
69    pub(crate) const fn from_no_binding(value: NoBinding) -> Self {
70        Self {
71            value: ServerValue::NoBinding(value),
72        }
73    }
74
75    /// Live generation authority is stale (register row 5647).
76    ///
77    /// The payload is minted only by `lookup_binding_required` for this
78    /// exact request.
79    pub(crate) const fn from_stale_authority(value: StaleAuthority) -> Self {
80        Self {
81            value: ServerValue::StaleAuthority(value),
82        }
83    }
84
85    /// Presented id has a tombstone (register row 5648).
86    ///
87    /// The payload is minted only by `lookup_binding_required` for this
88    /// exact request.
89    pub(crate) const fn from_retired(value: Retired) -> Self {
90        Self {
91            value: ServerValue::Retired(value),
92        }
93    }
94
95    /// Closure-checked ordinary admission exceeded marker-closure capacity
96    /// (register rows 5649, 5686).
97    ///
98    /// The payload is minted only by the shared remaining-closure selector
99    /// invoked with this request's own envelope.
100    pub(crate) const fn from_marker_closure_capacity_exceeded(
101        value: Box<MarkerClosureCapacityExceeded>,
102    ) -> Self {
103        Self {
104            value: ServerValue::MarkerClosureCapacityExceeded(value),
105        }
106    }
107
108    /// The ordinary record committed (register row 5685).
109    #[must_use]
110    pub const fn record_committed(value: RecordCommitted) -> Self {
111        Self {
112            value: ServerValue::RecordCommitted(value),
113        }
114    }
115
116    /// The record exceeds the configured entry or byte maximum (register row
117    /// 5686).
118    #[must_use]
119    pub const fn record_too_large(value: RecordTooLarge) -> Self {
120        Self {
121            value: ServerValue::RecordTooLarge(value),
122        }
123    }
124
125    /// Canonical resulting sequence-reserve check failed (register row 5686).
126    ///
127    /// The payload is minted only by the shared sequence allocator invoked
128    /// with this request's own envelope.
129    pub(crate) const fn from_conversation_sequence_exhausted(
130        value: Box<ConversationSequenceExhausted>,
131    ) -> Self {
132        Self {
133            value: ServerValue::ConversationSequenceExhausted(value),
134        }
135    }
136
137    /// Hard-observer retention refused the ordinary append (register row
138    /// 5687).
139    ///
140    /// The payload is minted only by the shared observer-floor selector
141    /// invoked with this request's own envelope.
142    pub(crate) const fn from_observer_backpressure(value: ObserverBackpressure) -> Self {
143        Self {
144            value: ServerValue::ObserverBackpressure(value),
145        }
146    }
147
148    /// Borrows the bound wire value for encoding or inspection.
149    #[must_use]
150    pub const fn server_value(&self) -> &ServerValue {
151        &self.value
152    }
153
154    /// Returns the bound value's exact wire discriminant.
155    #[must_use]
156    pub const fn discriminant(&self) -> ServerDiscriminant {
157        self.value.discriminant()
158    }
159
160    /// Moves the bound wire value out for transmission.
161    #[must_use]
162    pub fn into_server_value(self) -> ServerValue {
163        self.value
164    }
165}
166
167/// Server response bound to one observer-recovery handshake batch.
168///
169/// The register admits exactly four outcomes for the one-shot recovery batch
170/// (rows 5642, 5688, 5689); the contract's routing rule (lines 5780-5782)
171/// marks all four as already request-specific, so they carry no
172/// `originating_request` echo. Every other pairing is a compile error by
173/// construction.
174#[derive(Clone, Debug, PartialEq, Eq)]
175pub struct ObserverRecoveryResponse {
176    value: ServerValue,
177}
178
179impl ObserverRecoveryResponse {
180    /// Batch preflight found an untracked conversation that would exceed the
181    /// signed connection-conversation limit (register row 5642, wire
182    /// `0x0124`).
183    #[must_use]
184    pub const fn connection_capacity_exceeded(conversation_id: ConversationId, limit: u64) -> Self {
185        Self {
186            value: ServerValue::ConnectionConversationCapacityExceeded(
187                ConnectionConversationCapacityExceeded::ObserverRecovery {
188                    conversation_id,
189                    limit,
190                },
191            ),
192        }
193    }
194
195    /// Whole-batch success with request-ordered statuses (register row 5688).
196    #[must_use]
197    pub const fn accepted(value: ObserverRecoveryAccepted) -> Self {
198        Self {
199            value: ServerValue::ObserverRecoveryAccepted(value),
200        }
201    }
202
203    /// Whole-batch unknown-conversation or ahead-epoch refusal (register row
204    /// 5689).
205    #[must_use]
206    pub const fn invalid_observer_epoch(value: InvalidObserverEpoch) -> Self {
207        Self {
208            value: ServerValue::InvalidObserverEpoch(value),
209        }
210    }
211
212    /// Whole-batch list-shape refusal (register row 5689).
213    #[must_use]
214    pub const fn invalid_observer_epoch_list(value: InvalidObserverEpochList) -> Self {
215        Self {
216            value: ServerValue::InvalidObserverEpochList(value),
217        }
218    }
219
220    /// Borrows the bound wire value for encoding or inspection.
221    #[must_use]
222    pub const fn server_value(&self) -> &ServerValue {
223        &self.value
224    }
225
226    /// Returns the bound value's exact wire discriminant.
227    #[must_use]
228    pub const fn discriminant(&self) -> ServerDiscriminant {
229        self.value.discriminant()
230    }
231
232    /// Moves the bound wire value out for transmission.
233    #[must_use]
234    pub fn into_server_value(self) -> ServerValue {
235        self.value
236    }
237}