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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
//! The State plane's transport adapter.
//!
//! One crate sits between the wire and the kernel, and nothing else in the
//! workspace touches a generated State type (INV-24). A Container composes
//! this crate's server glue; a caller uses its clients; both speak only the
//! vocabulary `polyc_state` defines — commands, receipts, cursors, bounded
//! pages, and typed outcomes.
//!
//! # What lives here
//!
//! - [`wire`] maps the kernel's types onto their encoding and back, one
//! explicit conversion per type, every field named.
//! - [`error`] carries a typed outcome across the wire as a Connect error
//! detail, so the variant a module refused with is the variant its caller
//! reads — never one inferred from a status code.
//! - [`admission`] holds the checks the transport boundary makes before a call
//! reaches a module: version, audience, the caller's proven identity,
//! transport budget, and the listener's own lifecycle. Each is a pure
//! function returning the kernel's typed outcome, so a handler branches on
//! nothing itself. It also names the plane's audience once
//! ([`STATE_AUDIENCE`]), for both the caller that declares it and the
//! listener that serves it.
//! - [`trace`] carries one trace across the hop, so a commit and the decision
//! that caused it land in the same trace tree.
//! - [`journal`] is the partition journal's client and server glue — the first
//! authority surface this plane serves.
//! - [`feed`] is the durable commit feed's, including the resumable server
//! stream a projector tails a partition through.
//! - [`conformance`] serves and dials the conformance kit's synthetic family,
//! the test surface the authenticated shell proves itself against.
//!
//! # What does not live here
//!
//! Policy. Every decision belongs to `polyc_state` or to an
//! [`admission`] function whose whole body is one comparison; a handler that
//! reached its own conclusion would be a State module hiding inside a
//! transport. Durability, too: a receipt is minted by the module that
//! committed, and this crate only carries it (INV-22).
//!
//! See "Inter-plane protocol and transport",
//! `docs/proposals/separated-planes.md`.
/// The largest message this protocol accepts on the wire, in bytes.
///
/// A method-specific body bound is part of the contract, not a deployment
/// knob: a caller knows before it dials what it may send, and a listener
/// refuses anything larger before a handler runs. Deliberately far below the
/// transport library's own multi-megabyte default — State commands are
/// metadata plus a bounded payload, and a listener that would accept a
/// megabyte is a listener that can be made to allocate one.
///
/// Both halves read it: [`conformance::ConformanceClient`] bounds its
/// responses by it, and a listener configures its request bound from it.
///
/// This is the bound every family gets except a family whose semantic command
/// contract explicitly accepts the Versioned State payload ceiling. Those
/// exceptions are the partition journal and credential bootstrap; see
/// [`MAX_JOURNAL_WIRE_MESSAGE_BYTES`] and [`MAX_CREDENTIAL_WIRE_MESSAGE_BYTES`].
pub const MAX_WIRE_MESSAGE_BYTES: usize = 64 * 1024;
/// Largest durable-ingress request accepted on the wire.
///
/// The kernel independently accepts a durable payload and a content-identity
/// representation up to [`polyc_state::ingress::MAX_PAYLOAD_BYTES`] each. The
/// latter is omitted on the wire when it equals the durable payload. The
/// generic allowance covers signed identity, command metadata, and bounded
/// durable-feed drafts.
pub const MAX_INGRESS_WIRE_MESSAGE_BYTES: usize =
2 * MAX_PAYLOAD_BYTES as usize + MAX_WIRE_MESSAGE_BYTES;
/// Largest work-claim request accepted on the wire.
///
/// A command may carry the kernel's entire bounded change payload. The generic
/// allowance covers identities, metadata, record framing, status, and the
/// attempt history whose count is independently capped at eight.
pub const MAX_CLAIMS_WIRE_MESSAGE_BYTES: usize =
MAX_CHANGE_PAYLOAD_BYTES as usize + MAX_WIRE_MESSAGE_BYTES;
/// Largest query-audit request or reply accepted on the wire.
///
/// A point read can return one intent and one completion, each bounded by the
/// kernel's semantic command limit. An unmatched listing has the tighter
/// [`polyc_state::query_audit::MAX_AUDIT_PAGE_BYTES`] budget and always allows
/// one individually legal intent. The generic allowance covers Buffa framing,
/// call context, page metadata, and cursors.
pub const MAX_QUERY_AUDIT_WIRE_MESSAGE_BYTES: usize =
2 * MAX_AUDIT_PAYLOAD_BYTES as usize + MAX_WIRE_MESSAGE_BYTES;
const _: = ;
// The task family keeps a read inside the bound above by filling a list page
// against `polyc_state::tasks::MAX_PAGE_BYTES` rather than by counting rows,
// and it always carries at least one record however large that record is. So
// the largest page it can build is the budget or one whole record, whichever
// is larger, and the reply adds a cursor, two revisions, and Buffa's tags and
// length prefixes on top of it. A quarter of the bound is reserved for that
// framing. Raising either task bound past what this leaves fails to compile
// here instead of failing a list at run time.
const _: = ;
/// The largest message the partition-journal family accepts on the wire, in
/// bytes.
///
/// The journal is the one family whose contract already names a payload size,
/// and it names a big one:
/// [`MAX_BATCH_PAYLOAD_BYTES`](polyc_state::journal::MAX_BATCH_PAYLOAD_BYTES)
/// is what the kernel accepts in one atomic batch. A transport bound below it
/// would make that contract false — a caller could be refused a batch the
/// module would have committed — so this family gets a bound that carries the
/// batch the kernel promised, and every other family keeps the tight bound
/// above, which stays a real denial-of-service control rather than a knob.
///
/// Derived, never restated: the kernel's payload and variable-metadata bounds,
/// plus one [`MAX_WIRE_MESSAGE_BYTES`] of headroom for Buffa tags, length
/// prefixes, fixed command fields, and per-record framing neither semantic
/// bound counts. Raising any source bound moves this one with it, so the
/// kernel and transport cannot drift apart through a hand-copied number.
///
/// It bounds both directions, because a read must fit under it too: a journal
/// page is truncated at
/// [`MAX_BATCH_PAYLOAD_BYTES`](polyc_state::journal::MAX_BATCH_PAYLOAD_BYTES)
/// of record payload for exactly that reason.
// `cast_possible_truncation`: the sum is 4 MiB + 64 KiB, which fits a 32-bit
// `usize` with three orders of magnitude to spare. The cast is here rather than
// the constant being written in `usize` because the kernel's bound is the one
// that must be tracked, and it is a `u64`.
pub const MAX_JOURNAL_WIRE_MESSAGE_BYTES: usize =
as usize
+ MAX_WIRE_MESSAGE_BYTES;
/// Largest commit-feed request or stream item accepted on the wire.
///
/// The kernel bounds the chunk's payload plus variable metadata. One additional
/// generic allowance covers Buffa's fixed fields and length framing without
/// permitting the count bound to amplify 4 MiB commits into a 128 MiB message.
pub const MAX_FEED_WIRE_MESSAGE_BYTES: usize =
MAX_CHUNK_CONTENT_BYTES as usize + MAX_WIRE_MESSAGE_BYTES;
/// Largest credential-family request or reply accepted on the wire.
///
/// Bootstrap atomically carries several complete verifier records and the
/// family intentionally derives its resource envelope from Versioned State's
/// payload ceiling. Giving it the generic 64 KiB transport bound would make a
/// valid kernel command unreachable. The extra generic-bound headroom covers
/// Buffa framing and command metadata that the semantic payload count excludes.
pub const MAX_CREDENTIAL_WIRE_MESSAGE_BYTES: usize =
MAX_TRANSACTION_PAYLOAD_BYTES as usize + MAX_WIRE_MESSAGE_BYTES;
/// Largest persona-memory snapshot request or reply accepted on the wire.
///
/// A snapshot is one versioned entry the kernel bounds at
/// [`MAX_SNAPSHOT_BYTES`](polyc_state::persona_memory::MAX_SNAPSHOT_BYTES), and
/// that bound is asserted against the entry ceiling at compile time. Giving
/// this family the generic 64 KiB transport bound would make a snapshot the
/// kernel says fits unsendable — a refusal a caller could do nothing about,
/// because the record's size is a function of how much a persona remembers.
/// The extra generic-bound headroom covers Buffa framing and the call context
/// the record travels beside.
pub const MAX_PERSONA_MEMORY_WIRE_MESSAGE_BYTES: usize =
MAX_SNAPSHOT_BYTES + MAX_WIRE_MESSAGE_BYTES;
/// Bound for one authoritative persona-memory journal request or page.
// The kernel bound is 4 MiB and therefore fits every supported `usize`.
pub const MAX_PERSONA_MEMORY_JOURNAL_WIRE_MESSAGE_BYTES: usize =
MAX_PAYLOAD_BYTES as usize + MAX_WIRE_MESSAGE_BYTES;
/// How many HTTP/2 streams one connection to a State listener may have open at
/// once.
///
/// `SETTINGS_MAX_CONCURRENT_STREAMS` as State's listener advertises it, which is
/// hyper's server default: the listener serves through
/// `connectrpc::axum::serve_tls`, and that path configures a timer on the
/// HTTP/2 builder and nothing else — the setting is reachable only from
/// `connectrpc::Server`, which serves a Connect router rather than the axum one
/// State composes. So this is an observed ceiling, not a chosen one, and it
/// moves only when the listener stops going through that path.
///
/// A caller has to spend it deliberately, because past it nothing pushes back.
/// The h2 client returns `Pending` from its `poll_ready` while a connection is
/// at its stream limit, hyper's HTTP/2 client task then stops draining its
/// dispatch channel, and the unbounded sender feeding that channel keeps
/// accepting: hyper's own `SendRequest::poll_ready` reports whether the
/// connection is closed, never whether it has stream capacity. A request past
/// the ceiling is therefore queued rather than refused — no error, no timeout,
/// and, on a call whose deadline never expires, no end. That is the same
/// failure shape [`feed::MAX_CONCURRENT_SUBSCRIPTIONS`] exists to keep off the
/// listener's blocking pool, one layer down.
///
/// A client that opens long-lived streams therefore bounds its fan-out against
/// this and leaves room for the ordinary calls sharing the connection —
/// `polyc_control_plane::commit_feed`'s `MAX_FOLLOWERS` is derived from it.
pub const MAX_CONCURRENT_STREAMS_PER_CONNECTION: usize = 200;
pub use ;
pub use ;
pub use ;
pub use ;