Skip to main content

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//! | `0x7EB1` | [`FBUILD_PAYLOAD_PROTOCOL`]  | fbuild (FastLED/fbuild daemon Frame v1 request/response lane) |
47//!
48//! Use [`crate::register_payload_protocol!`] in consumer crates to pin
49//! the chosen ID with compile-time range and collision checks.
50
51/// Negotiated v1 broker protocol version.
52///
53/// This is the value carried in `Frame.envelope_version` (a u32 protobuf
54/// field) and in the `Hello`/`Refused`/`Negotiated` protocol-range fields
55/// (`client_min_protocol`, `daemon_max_protocol`, `negotiated_protocol`,
56/// ...).
57///
58/// NOT to be confused with [`crate::broker::FRAMING_VERSION_V1`]: that is
59/// the single raw `u8` framing byte written before every length-prefixed
60/// frame body on the wire. Both happen to be `1` in v1, but they are
61/// conceptually distinct version axes (outer framing layout vs negotiated
62/// protocol schema) and MUST stay separate named constants.
63pub const PROTOCOL_VERSION: u32 = 1;
64
65/// Outer framing byte for every v1 broker connection (re-exported here so
66/// the registry names both version axes side by side).
67///
68/// Distinct from [`PROTOCOL_VERSION`]: this `u8` prefixes the raw wire
69/// layout `[u8 framing_version][u32 LE body_length][prost body]`, while
70/// `PROTOCOL_VERSION` is the negotiated protocol schema version carried
71/// inside the decoded `Frame`. Both are `1` in v1 by coincidence — do not
72/// collapse them. Canonical definition: [`crate::broker::FRAMING_VERSION_V1`].
73pub use crate::broker::FRAMING_VERSION_V1;
74
75/// Payload protocol for v1 control-plane frames (Hello / HelloReply).
76pub const CONTROL_PAYLOAD_PROTOCOL: u32 = 0x00;
77
78/// Payload protocol value for v1 admin request/reply frames.
79pub const ADMIN_PAYLOAD_PROTOCOL: u32 = 0xAD01;
80
81/// Payload protocol reserved for `BackendHandle` endpoint identity probes.
82pub const BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL: u32 = 0xB232;
83
84/// Payload protocol reserved for broker↔backend handoff offer/ACK frames
85/// and the broker→client handoff-ready relay.
86pub const HANDOFF_PAYLOAD_PROTOCOL: u32 = 0xD0FF;
87
88/// Inclusive lower bound of the registered-consumer payload-protocol range.
89pub const CONSUMER_PAYLOAD_PROTOCOL_MIN: u32 = 0x7000;
90
91/// Inclusive upper bound of the registered-consumer payload-protocol range.
92pub const CONSUMER_PAYLOAD_PROTOCOL_MAX: u32 = 0x7EFF;
93
94/// Inclusive lower bound of the private-use payload-protocol range.
95///
96/// Private-use IDs are never registered here and never collision-checked
97/// against other consumers — suitable for tests and closed deployments only.
98pub const PRIVATE_USE_PAYLOAD_PROTOCOL_MIN: u32 = 0xF000;
99
100/// Inclusive upper bound of the private-use payload-protocol range.
101pub const PRIVATE_USE_PAYLOAD_PROTOCOL_MAX: u32 = 0xFFFF;
102
103/// Registered consumer ID: zccache's opaque FrameV1 request/response lane
104/// (`0x7A63` = ASCII `"zc"`). zccache pins this value on its side with
105/// [`crate::register_payload_protocol!`]-style compile-time asserts; the
106/// authoritative registration lives here.
107pub const ZCCACHE_PAYLOAD_PROTOCOL: u32 = 0x7A63;
108
109/// Registered consumer ID: clud's opaque Frame v1 request/response lane
110/// (zackees/clud daemon control plane; zackees/running-process#385).
111/// clud pins this value on its side with
112/// [`crate::register_payload_protocol!`]-style compile-time asserts; the
113/// authoritative registration lives here.
114pub const CLUD_PAYLOAD_PROTOCOL: u32 = 0x7C4C;
115
116/// Registered consumer ID: fbuild's opaque Frame v1 request/response lane
117/// (FastLED/fbuild daemon control plane; zackees/running-process#437). fbuild
118/// pins this value on its side with [`crate::register_payload_protocol!`]; the
119/// authoritative registration lives here.
120pub const FBUILD_PAYLOAD_PROTOCOL: u32 = 0x7EB1;
121
122/// All first-party payload-protocol IDs, in registry-table order.
123///
124/// Used by [`is_first_party`] and the consumer-side collision checks
125/// emitted by [`crate::register_payload_protocol!`].
126pub const FIRST_PARTY_PAYLOAD_PROTOCOLS: [u32; 4] = [
127    CONTROL_PAYLOAD_PROTOCOL,
128    ADMIN_PAYLOAD_PROTOCOL,
129    BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL,
130    HANDOFF_PAYLOAD_PROTOCOL,
131];
132
133/// True when `id` is a first-party running-process payload-protocol ID.
134///
135/// Consumer payload protocols must never collide with these; the
136/// [`crate::register_payload_protocol!`] macro enforces that at compile
137/// time.
138pub const fn is_first_party(id: u32) -> bool {
139    let mut index = 0;
140    while index < FIRST_PARTY_PAYLOAD_PROTOCOLS.len() {
141        if FIRST_PARTY_PAYLOAD_PROTOCOLS[index] == id {
142            return true;
143        }
144        index += 1;
145    }
146    false
147}
148
149/// True when `id` falls inside the registered-consumer range
150/// (`0x7000..=0x7EFF`).
151pub const fn is_registered_consumer_id(id: u32) -> bool {
152    id >= CONSUMER_PAYLOAD_PROTOCOL_MIN && id <= CONSUMER_PAYLOAD_PROTOCOL_MAX
153}
154
155/// True when `id` falls inside the private-use range (`0xF000..=0xFFFF`).
156pub const fn is_private_use_id(id: u32) -> bool {
157    id >= PRIVATE_USE_PAYLOAD_PROTOCOL_MIN && id <= PRIVATE_USE_PAYLOAD_PROTOCOL_MAX
158}
159
160/// Define a consumer payload-protocol constant with compile-time checks.
161///
162/// Expands to a `pub const` plus const asserts that the value:
163///
164/// 1. does not collide with any first-party running-process payload
165///    protocol ([`registry::is_first_party`](is_first_party)), and
166/// 2. lies inside the registered-consumer range (`0x7000..=0x7EFF`) or
167///    the private-use range (`0xF000..=0xFFFF`).
168///
169/// ```
170/// running_process::register_payload_protocol! {
171///     /// My daemon's opaque Frame lane.
172///     pub const MY_PAYLOAD_PROTOCOL: u32 = 0x7A63;
173/// }
174/// assert_eq!(MY_PAYLOAD_PROTOCOL, 0x7A63);
175/// ```
176#[macro_export]
177macro_rules! register_payload_protocol {
178    ($(#[$meta:meta])* $vis:vis const $name:ident: u32 = $value:expr;) => {
179        $(#[$meta])*
180        $vis const $name: u32 = $value;
181
182        const _: () = {
183            assert!(
184                !$crate::broker::protocol::registry::is_first_party($name),
185                concat!(
186                    stringify!($name),
187                    " collides with a first-party running-process payload protocol",
188                ),
189            );
190            assert!(
191                $crate::broker::protocol::registry::is_registered_consumer_id($name)
192                    || $crate::broker::protocol::registry::is_private_use_id($name),
193                concat!(
194                    stringify!($name),
195                    " must lie in the registered-consumer range (0x7000..=0x7EFF) \
196                     or the private-use range (0xF000..=0xFFFF)",
197                ),
198            );
199        };
200    };
201}
202
203#[cfg(test)]
204mod tests {
205    use super::{
206        ADMIN_PAYLOAD_PROTOCOL, BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL, CONTROL_PAYLOAD_PROTOCOL,
207        HANDOFF_PAYLOAD_PROTOCOL, PROTOCOL_VERSION,
208    };
209
210    /// Every registered payload-protocol ID must be pairwise distinct —
211    /// they multiplex independent subsystems over one frame envelope.
212    #[test]
213    fn payload_protocol_ids_are_pairwise_distinct() {
214        let registered: [(u32, &str); 4] = [
215            (CONTROL_PAYLOAD_PROTOCOL, "CONTROL_PAYLOAD_PROTOCOL"),
216            (ADMIN_PAYLOAD_PROTOCOL, "ADMIN_PAYLOAD_PROTOCOL"),
217            (
218                BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL,
219                "BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL",
220            ),
221            (HANDOFF_PAYLOAD_PROTOCOL, "HANDOFF_PAYLOAD_PROTOCOL"),
222        ];
223        for (left_index, (left_id, left_name)) in registered.iter().enumerate() {
224            for (right_id, right_name) in &registered[left_index + 1..] {
225                assert_ne!(
226                    left_id, right_id,
227                    "{left_name} and {right_name} share payload-protocol id {left_id:#06X}"
228                );
229            }
230        }
231    }
232
233    /// Frozen v1 wire values — changing any of these breaks the v1 contract.
234    #[test]
235    fn frozen_v1_wire_values() {
236        assert_eq!(PROTOCOL_VERSION, 1);
237        assert_eq!(CONTROL_PAYLOAD_PROTOCOL, 0x00);
238        assert_eq!(ADMIN_PAYLOAD_PROTOCOL, 0xAD01);
239        assert_eq!(BACKEND_HANDLE_PROBE_PAYLOAD_PROTOCOL, 0xB232);
240        assert_eq!(HANDOFF_PAYLOAD_PROTOCOL, 0xD0FF);
241        assert_eq!(u32::from(crate::broker::FRAMING_VERSION_V1), 1);
242    }
243
244    /// Frozen consumer registrations and range boundaries (#412).
245    #[test]
246    fn frozen_consumer_registry_values() {
247        use super::{
248            is_first_party, is_private_use_id, is_registered_consumer_id, CLUD_PAYLOAD_PROTOCOL,
249            CONSUMER_PAYLOAD_PROTOCOL_MAX, CONSUMER_PAYLOAD_PROTOCOL_MIN, FBUILD_PAYLOAD_PROTOCOL,
250            PRIVATE_USE_PAYLOAD_PROTOCOL_MAX, PRIVATE_USE_PAYLOAD_PROTOCOL_MIN,
251            ZCCACHE_PAYLOAD_PROTOCOL,
252        };
253
254        assert_eq!(CONSUMER_PAYLOAD_PROTOCOL_MIN, 0x7000);
255        assert_eq!(CONSUMER_PAYLOAD_PROTOCOL_MAX, 0x7EFF);
256        assert_eq!(PRIVATE_USE_PAYLOAD_PROTOCOL_MIN, 0xF000);
257        assert_eq!(PRIVATE_USE_PAYLOAD_PROTOCOL_MAX, 0xFFFF);
258        assert_eq!(ZCCACHE_PAYLOAD_PROTOCOL, 0x7A63);
259        assert_eq!(CLUD_PAYLOAD_PROTOCOL, 0x7C4C);
260        assert_eq!(FBUILD_PAYLOAD_PROTOCOL, 0x7EB1);
261        assert_ne!(CLUD_PAYLOAD_PROTOCOL, ZCCACHE_PAYLOAD_PROTOCOL);
262        assert_ne!(FBUILD_PAYLOAD_PROTOCOL, ZCCACHE_PAYLOAD_PROTOCOL);
263        assert_ne!(FBUILD_PAYLOAD_PROTOCOL, CLUD_PAYLOAD_PROTOCOL);
264
265        assert!(is_registered_consumer_id(ZCCACHE_PAYLOAD_PROTOCOL));
266        assert!(!is_first_party(ZCCACHE_PAYLOAD_PROTOCOL));
267        assert!(!is_private_use_id(ZCCACHE_PAYLOAD_PROTOCOL));
268
269        assert!(is_registered_consumer_id(CLUD_PAYLOAD_PROTOCOL));
270        assert!(!is_first_party(CLUD_PAYLOAD_PROTOCOL));
271        assert!(!is_private_use_id(CLUD_PAYLOAD_PROTOCOL));
272
273        assert!(is_registered_consumer_id(FBUILD_PAYLOAD_PROTOCOL));
274        assert!(!is_first_party(FBUILD_PAYLOAD_PROTOCOL));
275        assert!(!is_private_use_id(FBUILD_PAYLOAD_PROTOCOL));
276
277        // First-party IDs must never drift into the consumer range.
278        for id in super::FIRST_PARTY_PAYLOAD_PROTOCOLS {
279            assert!(is_first_party(id));
280            assert!(!is_registered_consumer_id(id));
281            assert!(!is_private_use_id(id));
282        }
283    }
284
285    // The macro must compile for both allowed ranges.
286    crate::register_payload_protocol! {
287        /// Registered-consumer-range example (compile-time check).
288        const MACRO_CONSUMER_RANGE_EXAMPLE: u32 = 0x7001;
289    }
290    crate::register_payload_protocol! {
291        /// Private-use-range example (compile-time check).
292        const MACRO_PRIVATE_RANGE_EXAMPLE: u32 = 0xF00D;
293    }
294
295    #[test]
296    fn register_macro_defines_usable_constants() {
297        assert_eq!(MACRO_CONSUMER_RANGE_EXAMPLE, 0x7001);
298        assert_eq!(MACRO_PRIVATE_RANGE_EXAMPLE, 0xF00D);
299    }
300}