Skip to main content

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}