liminal_protocol/wire/authority/acks.rs
1//! Response authorities bound to `ClientRequest::ParticipantAck` (`0x0004`)
2//! and `ClientRequest::MarkerAck` (`0x0006`).
3//!
4//! Per the register's closing rule (contract lines 5699-5701), normal and
5//! marker acks never return `ObserverBackpressure`,
6//! `MarkerClosureCapacityExceeded`, or `ConversationOrderExhausted`: they
7//! append no record, allocate no major, and may relieve retention pressure.
8//! `ConversationSequenceExhausted` is excluded separately by the register's
9//! reachability rule (contract lines 5691-5696): that outcome remains
10//! reachable only for optional enrollment, attach, supersession, ordinary,
11//! or floor-triggering candidates. No constructor for any of those outcomes
12//! exists here.
13
14use super::super::{
15 AckCommitted, AckGap, AckNoOp, AckRegression, ConnectionConversationCapacityExceeded,
16 MarkerAckCommitted, MarkerAckEnvelope, MarkerMismatch, MarkerNotDelivered, NoBinding,
17 ParticipantAckEnvelope, ParticipantUnknown, ResponseEnvelope, Retired, ServerDiscriminant,
18 ServerValue, StaleAuthority,
19};
20
21/// Server response bound to one continuous cumulative acknowledgement.
22///
23/// Constructors exist only for the outcomes the frozen R-D1 register admits
24/// for normal ack; every other pairing is a compile error by construction.
25#[derive(Clone, Debug, PartialEq, Eq)]
26pub struct ParticipantAckResponse {
27 value: ServerValue,
28}
29
30impl ParticipantAckResponse {
31 /// First decoded semantic operation for an untracked conversation
32 /// exceeded the connection-conversation limit (register row 5641).
33 #[must_use]
34 pub const fn connection_conversation_capacity_exceeded(
35 request: ParticipantAckEnvelope,
36 limit: u64,
37 ) -> Self {
38 Self {
39 value: ServerValue::ConnectionConversationCapacityExceeded(
40 ConnectionConversationCapacityExceeded::SemanticRequest {
41 request: ResponseEnvelope::ParticipantAck(request),
42 limit,
43 },
44 ),
45 }
46 }
47
48 /// Presented participant is unknown (register row 5645).
49 ///
50 /// The payload is minted only by `lookup_binding_required` for this
51 /// exact request.
52 pub(crate) const fn from_participant_unknown(value: ParticipantUnknown) -> Self {
53 Self {
54 value: ServerValue::ParticipantUnknown(value),
55 }
56 }
57
58 /// Exact-binding lookup missed (register row 5646).
59 ///
60 /// The payload is minted only by `lookup_binding_required` for this
61 /// exact request.
62 pub(crate) const fn from_no_binding(value: NoBinding) -> Self {
63 Self {
64 value: ServerValue::NoBinding(value),
65 }
66 }
67
68 /// Live generation authority is stale (register row 5647).
69 ///
70 /// The payload is minted only by `lookup_binding_required` for this
71 /// exact request.
72 pub(crate) const fn from_stale_authority(value: StaleAuthority) -> Self {
73 Self {
74 value: ServerValue::StaleAuthority(value),
75 }
76 }
77
78 /// Presented id has a tombstone (register row 5677).
79 ///
80 /// The payload is minted only by `lookup_binding_required` for this
81 /// exact request.
82 pub(crate) const fn from_retired(value: Retired) -> Self {
83 Self {
84 value: ServerValue::Retired(value),
85 }
86 }
87
88 /// The acknowledgement advanced the cursor (register row 5674).
89 #[must_use]
90 pub const fn ack_committed(value: AckCommitted) -> Self {
91 Self {
92 value: ServerValue::AckCommitted(value),
93 }
94 }
95
96 /// Idempotent confirmation at the unchanged cursor (register row 5675).
97 #[must_use]
98 pub const fn ack_no_op(request: ParticipantAckEnvelope) -> Self {
99 Self {
100 value: ServerValue::AckNoOp(AckNoOp::participant_ack(request)),
101 }
102 }
103
104 /// Idempotent confirmation minted by the nonzero-debt cumulative-ack
105 /// episode selector for this exact request (register row 5675).
106 pub(crate) const fn from_ack_no_op(value: AckNoOp) -> Self {
107 Self {
108 value: ServerValue::AckNoOp(value),
109 }
110 }
111
112 /// The requested boundary crossed a gap (register row 5676).
113 #[must_use]
114 pub const fn ack_gap(value: AckGap) -> Self {
115 Self {
116 value: ServerValue::AckGap(value),
117 }
118 }
119
120 /// The requested boundary regressed below the cursor (register row 5676).
121 #[must_use]
122 pub const fn ack_regression(value: AckRegression) -> Self {
123 Self {
124 value: ServerValue::AckRegression(value),
125 }
126 }
127
128 /// Borrows the bound wire value for encoding or inspection.
129 #[must_use]
130 pub const fn server_value(&self) -> &ServerValue {
131 &self.value
132 }
133
134 /// Returns the bound value's exact wire discriminant.
135 #[must_use]
136 pub const fn discriminant(&self) -> ServerDiscriminant {
137 self.value.discriminant()
138 }
139
140 /// Moves the bound wire value out for transmission.
141 #[must_use]
142 pub fn into_server_value(self) -> ServerValue {
143 self.value
144 }
145}
146
147/// Server response bound to one explicit marker acknowledgement.
148///
149/// Constructors exist only for the outcomes the frozen R-D1 register admits
150/// for marker ack; every other pairing is a compile error by construction.
151#[derive(Clone, Debug, PartialEq, Eq)]
152pub struct MarkerAckResponse {
153 value: ServerValue,
154}
155
156impl MarkerAckResponse {
157 /// First decoded semantic operation for an untracked conversation
158 /// exceeded the connection-conversation limit (register row 5641).
159 #[must_use]
160 pub const fn connection_conversation_capacity_exceeded(
161 request: MarkerAckEnvelope,
162 limit: u64,
163 ) -> Self {
164 Self {
165 value: ServerValue::ConnectionConversationCapacityExceeded(
166 ConnectionConversationCapacityExceeded::SemanticRequest {
167 request: ResponseEnvelope::MarkerAck(request),
168 limit,
169 },
170 ),
171 }
172 }
173
174 /// Presented participant is unknown (register row 5645).
175 ///
176 /// The payload is minted only by `lookup_binding_required` for this
177 /// exact request.
178 pub(crate) const fn from_participant_unknown(value: ParticipantUnknown) -> Self {
179 Self {
180 value: ServerValue::ParticipantUnknown(value),
181 }
182 }
183
184 /// Exact-binding lookup missed (register row 5646).
185 ///
186 /// The payload is minted only by `lookup_binding_required` for this
187 /// exact request.
188 pub(crate) const fn from_no_binding(value: NoBinding) -> Self {
189 Self {
190 value: ServerValue::NoBinding(value),
191 }
192 }
193
194 /// Live generation authority is stale (register row 5647).
195 ///
196 /// The payload is minted only by `lookup_binding_required` for this
197 /// exact request.
198 pub(crate) const fn from_stale_authority(value: StaleAuthority) -> Self {
199 Self {
200 value: ServerValue::StaleAuthority(value),
201 }
202 }
203
204 /// Presented id has a tombstone (register row 5684).
205 ///
206 /// The payload is minted only by `lookup_binding_required` for this
207 /// exact request.
208 pub(crate) const fn from_retired(value: Retired) -> Self {
209 Self {
210 value: ServerValue::Retired(value),
211 }
212 }
213
214 /// The marker acknowledgement advanced the cursor (register row 5682).
215 #[must_use]
216 pub const fn marker_ack_committed(value: MarkerAckCommitted) -> Self {
217 Self {
218 value: ServerValue::MarkerAckCommitted(value),
219 }
220 }
221
222 /// Idempotent confirmation at the unchanged marker cursor (register row
223 /// 5682).
224 ///
225 /// The payload is minted only by the shared marker-proof selector
226 /// invoked with this request's own proof fields.
227 pub(crate) const fn from_ack_no_op(value: AckNoOp) -> Self {
228 Self {
229 value: ServerValue::AckNoOp(value),
230 }
231 }
232
233 /// The named marker was not delivered to the proof epoch (register row
234 /// 5683).
235 ///
236 /// The payload is minted only by the shared marker-proof selector
237 /// invoked with this request's own proof fields.
238 pub(crate) const fn from_marker_not_delivered(value: MarkerNotDelivered) -> Self {
239 Self {
240 value: ServerValue::MarkerNotDelivered(value),
241 }
242 }
243
244 /// The named marker mismatches current marker state (register row 5683).
245 ///
246 /// The payload is minted only by the shared marker-proof selector
247 /// invoked with this request's own proof fields.
248 pub(crate) const fn from_marker_mismatch(value: MarkerMismatch) -> Self {
249 Self {
250 value: ServerValue::MarkerMismatch(value),
251 }
252 }
253
254 /// Borrows the bound wire value for encoding or inspection.
255 #[must_use]
256 pub const fn server_value(&self) -> &ServerValue {
257 &self.value
258 }
259
260 /// Returns the bound value's exact wire discriminant.
261 #[must_use]
262 pub const fn discriminant(&self) -> ServerDiscriminant {
263 self.value.discriminant()
264 }
265
266 /// Moves the bound wire value out for transmission.
267 #[must_use]
268 pub fn into_server_value(self) -> ServerValue {
269 self.value
270 }
271}