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}