running_process/broker/protocol/registry.rs
1//! Single authoritative registry of v1 broker wire-protocol constants
2//! (#375).
3//!
4//! Every payload-protocol ID multiplexed over the frozen v1 `Frame`
5//! envelope, plus the negotiated protocol version, is defined HERE and
6//! only here. Subsystem modules `pub use` these constants (the old
7//! public paths remain valid re-export shims) so the public API surface
8//! is unchanged while the values have exactly one definition site.
9//!
10//! These values are part of the FROZEN-FOREVER v1 wire contract — see
11//! `proto/broker_v1_envelope.proto` and #228. Never change an existing
12//! value; only append new IDs (and keep them pairwise distinct — the
13//! unit test below enforces this).
14//!
15//! # Payload-protocol ID registry
16//!
17//! | ID | Constant | Purpose | Payload proto message |
18//! |----------|--------------------------------------------|------------------------------------------------|----------------------------------|
19//! | `0x0000` | [`CONTROL_PAYLOAD_PROTOCOL`] | Control plane: client Hello / broker HelloReply | `Hello` / `HelloReply` |
20//! | `0xAD01` | [`ADMIN_PAYLOAD_PROTOCOL`] | Admin verbs over the broker control socket | `AdminRequest` / `AdminReply` |
21//! | `0xB232` | [`BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL`] | `BackendHandle` endpoint identity probes | raw nonce / nonce + `DaemonProcess` |
22//! | `0xD0FF` | [`HANDOFF_PAYLOAD_PROTOCOL`] | Connection handoff offer/ACK and client relay | `HandoffOffer` / `HandoffAck` |
23//!
24//! # Consumer payload-protocol IDs (#412)
25//!
26//! Consumer daemons that multiplex their own request/response payloads
27//! over the v1 `Frame` envelope (the "opaque Frame lane" pattern — see
28//! `docs/INTEGRATE.md`) pick an ID from the registered-consumer range
29//! and record it in the table below via a running-process PR. IDs are
30//! first-come-first-served and frozen once registered.
31//!
32//! | Range | Use |
33//! |---------------------|---------------------------------------------------------|
34//! | `0x0000`–`0x6FFF` | Reserved for first-party running-process subsystems |
35//! | `0x7000`–`0x7EFF` | Registered consumer IDs (table below) |
36//! | `0x7F00`–`0xEFFF` | Reserved for future expansion — do not use |
37//! | `0xF000`–`0xFFFF` | Private use — never registered, never collision-checked |
38//!
39//! (`0xAD01`, `0xB232`, and `0xD0FF` predate the range split and are
40//! grandfathered first-party IDs; [`is_first_party`] knows about them.)
41//!
42//! | ID | Constant | Consumer |
43//! |----------|------------------------------|------------------------------------------------------------------|
44//! | `0x7A63` | [`ZCCACHE_PAYLOAD_PROTOCOL`] | zccache (`"zc"` in ASCII; zccache FrameV1 request/response lane) |
45//! | `0x7C4C` | [`CLUD_PAYLOAD_PROTOCOL`] | clud (`0x7C4C` = `"|L"`; clud daemon Frame v1 request/response lane) |
46//!
47//! Use [`crate::register_payload_protocol!`] in consumer crates to pin
48//! the chosen ID with compile-time range and collision checks.
49
50/// Negotiated v1 broker protocol version.
51///
52/// This is the value carried in `Frame.envelope_version` (a u32 protobuf
53/// field) and in the `Hello`/`Refused`/`Negotiated` protocol-range fields
54/// (`client_min_protocol`, `daemon_max_protocol`, `negotiated_protocol`,
55/// ...).
56///
57/// NOT to be confused with [`crate::broker::FRAMING_VERSION_V1`]: that is
58/// the single raw `u8` framing byte written before every length-prefixed
59/// frame body on the wire. Both happen to be `1` in v1, but they are
60/// conceptually distinct version axes (outer framing layout vs negotiated
61/// protocol schema) and MUST stay separate named constants.
62pub const PROTOCOL_VERSION: u32 = 1;
63
64/// Outer framing byte for every v1 broker connection (re-exported here so
65/// the registry names both version axes side by side).
66///
67/// Distinct from [`PROTOCOL_VERSION`]: this `u8` prefixes the raw wire
68/// layout `[u8 framing_version][u32 LE body_length][prost body]`, while
69/// `PROTOCOL_VERSION` is the negotiated protocol schema version carried
70/// inside the decoded `Frame`. Both are `1` in v1 by coincidence — do not
71/// collapse them. Canonical definition: [`crate::broker::FRAMING_VERSION_V1`].
72pub use crate::broker::FRAMING_VERSION_V1;
73
74/// Payload protocol for v1 control-plane frames (Hello / HelloReply).
75pub const CONTROL_PAYLOAD_PROTOCOL: u32 = 0x00;
76
77/// Payload protocol value for v1 admin request/reply frames.
78pub const ADMIN_PAYLOAD_PROTOCOL: u32 = 0xAD01;
79
80/// Payload protocol reserved for `BackendHandle` endpoint identity probes.
81pub const BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL: u32 = 0xB232;
82
83/// Payload protocol reserved for broker↔backend handoff offer/ACK frames
84/// and the broker→client handoff-ready relay.
85pub const HANDOFF_PAYLOAD_PROTOCOL: u32 = 0xD0FF;
86
87/// Inclusive lower bound of the registered-consumer payload-protocol range.
88pub const CONSUMER_PAYLOAD_PROTOCOL_MIN: u32 = 0x7000;
89
90/// Inclusive upper bound of the registered-consumer payload-protocol range.
91pub const CONSUMER_PAYLOAD_PROTOCOL_MAX: u32 = 0x7EFF;
92
93/// Inclusive lower bound of the private-use payload-protocol range.
94///
95/// Private-use IDs are never registered here and never collision-checked
96/// against other consumers — suitable for tests and closed deployments only.
97pub const PRIVATE_USE_PAYLOAD_PROTOCOL_MIN: u32 = 0xF000;
98
99/// Inclusive upper bound of the private-use payload-protocol range.
100pub const PRIVATE_USE_PAYLOAD_PROTOCOL_MAX: u32 = 0xFFFF;
101
102/// Registered consumer ID: zccache's opaque FrameV1 request/response lane
103/// (`0x7A63` = ASCII `"zc"`). zccache pins this value on its side with
104/// [`crate::register_payload_protocol!`]-style compile-time asserts; the
105/// authoritative registration lives here.
106pub const ZCCACHE_PAYLOAD_PROTOCOL: u32 = 0x7A63;
107
108/// Registered consumer ID: clud's opaque Frame v1 request/response lane
109/// (zackees/clud daemon control plane; zackees/running-process#385).
110/// clud pins this value on its side with
111/// [`crate::register_payload_protocol!`]-style compile-time asserts; the
112/// authoritative registration lives here.
113pub const CLUD_PAYLOAD_PROTOCOL: u32 = 0x7C4C;
114
115/// All first-party payload-protocol IDs, in registry-table order.
116///
117/// Used by [`is_first_party`] and the consumer-side collision checks
118/// emitted by [`crate::register_payload_protocol!`].
119pub const FIRST_PARTY_PAYLOAD_PROTOCOLS: [u32; 4] = [
120 CONTROL_PAYLOAD_PROTOCOL,
121 ADMIN_PAYLOAD_PROTOCOL,
122 BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL,
123 HANDOFF_PAYLOAD_PROTOCOL,
124];
125
126/// True when `id` is a first-party running-process payload-protocol ID.
127///
128/// Consumer payload protocols must never collide with these; the
129/// [`crate::register_payload_protocol!`] macro enforces that at compile
130/// time.
131pub const fn is_first_party(id: u32) -> bool {
132 let mut index = 0;
133 while index < FIRST_PARTY_PAYLOAD_PROTOCOLS.len() {
134 if FIRST_PARTY_PAYLOAD_PROTOCOLS[index] == id {
135 return true;
136 }
137 index += 1;
138 }
139 false
140}
141
142/// True when `id` falls inside the registered-consumer range
143/// (`0x7000..=0x7EFF`).
144pub const fn is_registered_consumer_id(id: u32) -> bool {
145 id >= CONSUMER_PAYLOAD_PROTOCOL_MIN && id <= CONSUMER_PAYLOAD_PROTOCOL_MAX
146}
147
148/// True when `id` falls inside the private-use range (`0xF000..=0xFFFF`).
149pub const fn is_private_use_id(id: u32) -> bool {
150 id >= PRIVATE_USE_PAYLOAD_PROTOCOL_MIN && id <= PRIVATE_USE_PAYLOAD_PROTOCOL_MAX
151}
152
153/// Define a consumer payload-protocol constant with compile-time checks.
154///
155/// Expands to a `pub const` plus const asserts that the value:
156///
157/// 1. does not collide with any first-party running-process payload
158/// protocol ([`registry::is_first_party`](is_first_party)), and
159/// 2. lies inside the registered-consumer range (`0x7000..=0x7EFF`) or
160/// the private-use range (`0xF000..=0xFFFF`).
161///
162/// ```
163/// running_process::register_payload_protocol! {
164/// /// My daemon's opaque Frame lane.
165/// pub const MY_PAYLOAD_PROTOCOL: u32 = 0x7A63;
166/// }
167/// assert_eq!(MY_PAYLOAD_PROTOCOL, 0x7A63);
168/// ```
169#[macro_export]
170macro_rules! register_payload_protocol {
171 ($(#[$meta:meta])* $vis:vis const $name:ident: u32 = $value:expr;) => {
172 $(#[$meta])*
173 $vis const $name: u32 = $value;
174
175 const _: () = {
176 assert!(
177 !$crate::broker::protocol::registry::is_first_party($name),
178 concat!(
179 stringify!($name),
180 " collides with a first-party running-process payload protocol",
181 ),
182 );
183 assert!(
184 $crate::broker::protocol::registry::is_registered_consumer_id($name)
185 || $crate::broker::protocol::registry::is_private_use_id($name),
186 concat!(
187 stringify!($name),
188 " must lie in the registered-consumer range (0x7000..=0x7EFF) \
189 or the private-use range (0xF000..=0xFFFF)",
190 ),
191 );
192 };
193 };
194}
195
196#[cfg(test)]
197mod tests {
198 use super::{
199 ADMIN_PAYLOAD_PROTOCOL, BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL, CONTROL_PAYLOAD_PROTOCOL,
200 HANDOFF_PAYLOAD_PROTOCOL, PROTOCOL_VERSION,
201 };
202
203 /// Every registered payload-protocol ID must be pairwise distinct —
204 /// they multiplex independent subsystems over one frame envelope.
205 #[test]
206 fn payload_protocol_ids_are_pairwise_distinct() {
207 let registered: [(u32, &str); 4] = [
208 (CONTROL_PAYLOAD_PROTOCOL, "CONTROL_PAYLOAD_PROTOCOL"),
209 (ADMIN_PAYLOAD_PROTOCOL, "ADMIN_PAYLOAD_PROTOCOL"),
210 (
211 BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL,
212 "BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL",
213 ),
214 (HANDOFF_PAYLOAD_PROTOCOL, "HANDOFF_PAYLOAD_PROTOCOL"),
215 ];
216 for (left_index, (left_id, left_name)) in registered.iter().enumerate() {
217 for (right_id, right_name) in ®istered[left_index + 1..] {
218 assert_ne!(
219 left_id, right_id,
220 "{left_name} and {right_name} share payload-protocol id {left_id:#06X}"
221 );
222 }
223 }
224 }
225
226 /// Frozen v1 wire values — changing any of these breaks the v1 contract.
227 #[test]
228 fn frozen_v1_wire_values() {
229 assert_eq!(PROTOCOL_VERSION, 1);
230 assert_eq!(CONTROL_PAYLOAD_PROTOCOL, 0x00);
231 assert_eq!(ADMIN_PAYLOAD_PROTOCOL, 0xAD01);
232 assert_eq!(BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL, 0xB232);
233 assert_eq!(HANDOFF_PAYLOAD_PROTOCOL, 0xD0FF);
234 assert_eq!(u32::from(crate::broker::FRAMING_VERSION_V1), 1);
235 }
236
237 /// Frozen consumer registrations and range boundaries (#412).
238 #[test]
239 fn frozen_consumer_registry_values() {
240 use super::{
241 is_first_party, is_private_use_id, is_registered_consumer_id, CLUD_PAYLOAD_PROTOCOL,
242 CONSUMER_PAYLOAD_PROTOCOL_MAX, CONSUMER_PAYLOAD_PROTOCOL_MIN,
243 PRIVATE_USE_PAYLOAD_PROTOCOL_MAX, PRIVATE_USE_PAYLOAD_PROTOCOL_MIN,
244 ZCCACHE_PAYLOAD_PROTOCOL,
245 };
246
247 assert_eq!(CONSUMER_PAYLOAD_PROTOCOL_MIN, 0x7000);
248 assert_eq!(CONSUMER_PAYLOAD_PROTOCOL_MAX, 0x7EFF);
249 assert_eq!(PRIVATE_USE_PAYLOAD_PROTOCOL_MIN, 0xF000);
250 assert_eq!(PRIVATE_USE_PAYLOAD_PROTOCOL_MAX, 0xFFFF);
251 assert_eq!(ZCCACHE_PAYLOAD_PROTOCOL, 0x7A63);
252 assert_eq!(CLUD_PAYLOAD_PROTOCOL, 0x7C4C);
253 assert_ne!(CLUD_PAYLOAD_PROTOCOL, ZCCACHE_PAYLOAD_PROTOCOL);
254
255 assert!(is_registered_consumer_id(ZCCACHE_PAYLOAD_PROTOCOL));
256 assert!(!is_first_party(ZCCACHE_PAYLOAD_PROTOCOL));
257 assert!(!is_private_use_id(ZCCACHE_PAYLOAD_PROTOCOL));
258
259 assert!(is_registered_consumer_id(CLUD_PAYLOAD_PROTOCOL));
260 assert!(!is_first_party(CLUD_PAYLOAD_PROTOCOL));
261 assert!(!is_private_use_id(CLUD_PAYLOAD_PROTOCOL));
262
263 // First-party IDs must never drift into the consumer range.
264 for id in super::FIRST_PARTY_PAYLOAD_PROTOCOLS {
265 assert!(is_first_party(id));
266 assert!(!is_registered_consumer_id(id));
267 assert!(!is_private_use_id(id));
268 }
269 }
270
271 // The macro must compile for both allowed ranges.
272 crate::register_payload_protocol! {
273 /// Registered-consumer-range example (compile-time check).
274 const MACRO_CONSUMER_RANGE_EXAMPLE: u32 = 0x7001;
275 }
276 crate::register_payload_protocol! {
277 /// Private-use-range example (compile-time check).
278 const MACRO_PRIVATE_RANGE_EXAMPLE: u32 = 0xF00D;
279 }
280
281 #[test]
282 fn register_macro_defines_usable_constants() {
283 assert_eq!(MACRO_CONSUMER_RANGE_EXAMPLE, 0x7001);
284 assert_eq!(MACRO_PRIVATE_RANGE_EXAMPLE, 0xF00D);
285 }
286}