nodedb_types/sync/wire/session.rs
1// SPDX-License-Identifier: Apache-2.0
2
3//! Session lifecycle messages: handshake, token refresh, keepalive.
4
5use std::collections::HashMap;
6
7use serde::{Deserialize, Serialize};
8
9/// Handshake message (client → server, 0x01).
10#[derive(
11 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
12)]
13pub struct HandshakeMsg {
14 /// JWT bearer token for authentication.
15 pub jwt_token: String,
16 /// Client's vector clock: `{ collection: { doc_id: lamport_ts } }`.
17 pub vector_clock: HashMap<String, HashMap<String, u64>>,
18 /// Shape IDs the client is subscribed to.
19 pub subscribed_shapes: Vec<String>,
20 /// Client version string.
21 pub client_version: String,
22 /// Lite instance identity (UUID v7). Default empty for non-Lite peers.
23 #[serde(default)]
24 pub lite_id: String,
25 /// Monotonic epoch counter (incremented on every open). Default 0 for non-Lite peers.
26 #[serde(default)]
27 pub epoch: u64,
28 /// Wire format version. Server rejects connections with incompatible versions.
29 /// Missing field deserializes to 0 and is rejected by the server explicitly.
30 #[serde(default)]
31 pub wire_version: u16,
32}
33
34/// Handshake acknowledgment (server → client, 0x02).
35#[derive(
36 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
37)]
38pub struct HandshakeAckMsg {
39 /// Whether the handshake succeeded.
40 pub success: bool,
41 /// Session ID assigned by the server.
42 pub session_id: String,
43 /// Server's vector clock (for initial sync).
44 pub server_clock: HashMap<String, u64>,
45 /// Error message (if !success).
46 pub error: Option<String>,
47 /// Fork detection: if true, client must regenerate LiteId and reconnect.
48 #[serde(default)]
49 pub fork_detected: bool,
50 /// Server's wire format version (for client-side compatibility check).
51 #[serde(default)]
52 pub server_wire_version: u16,
53 /// Server-assigned producer ID for this session. 0 if not yet assigned.
54 #[serde(default)]
55 pub producer_id: u64,
56 /// Server's current accepted epoch for this producer. 0 if not yet tracked.
57 #[serde(default)]
58 pub accepted_epoch: u64,
59}
60
61/// Token refresh request (client → server, 0x60).
62///
63/// Sent by Lite before the current JWT expires. The client provides
64/// a fresh token obtained from the application's auth layer.
65/// Origin validates the new token and either upgrades the session
66/// or disconnects if the token is invalid.
67#[derive(
68 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
69)]
70pub struct TokenRefreshMsg {
71 /// New JWT bearer token.
72 pub new_token: String,
73}
74
75/// Token refresh acknowledgment (server → client, 0x61).
76#[derive(
77 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
78)]
79pub struct TokenRefreshAckMsg {
80 /// Whether the token refresh succeeded.
81 pub success: bool,
82 /// Error message (if !success).
83 pub error: Option<String>,
84 /// Seconds until this new token expires (so Lite can schedule next refresh).
85 #[serde(default)]
86 pub expires_in_secs: u64,
87}
88
89/// Ping/Pong keepalive (0xFF).
90#[derive(
91 Debug, Clone, Serialize, Deserialize, zerompk::ToMessagePack, zerompk::FromMessagePack,
92)]
93pub struct PingPongMsg {
94 /// Timestamp (epoch milliseconds) for RTT measurement.
95 pub timestamp_ms: u64,
96 /// Whether this is a pong (response to ping).
97 pub is_pong: bool,
98}