1use crate::types::{Ack, MessageId};
2use serde::{Deserialize, Serialize};
3use serde_json::Value as JsonValue;
4use std::collections::BTreeMap;
5
6#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
7pub struct TopicId(pub String);
8
9#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
10pub struct TopicPath(pub String);
11
12#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
13pub struct TopicCreateRequest {
14 pub topic_path: Option<TopicPath>,
15 #[serde(default)]
16 pub metadata: BTreeMap<String, JsonValue>,
17 #[serde(default)]
18 pub extensions: BTreeMap<String, JsonValue>,
19}
20
21#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
22pub struct TopicRecord {
23 pub topic_id: TopicId,
24 pub topic_path: Option<TopicPath>,
25 pub created_ts_ms: u64,
26 #[serde(default)]
27 pub metadata: BTreeMap<String, JsonValue>,
28 #[serde(default)]
29 pub extensions: BTreeMap<String, JsonValue>,
30}
31
32#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
33pub struct TopicPublishRequest {
34 pub topic_id: TopicId,
35 pub payload: JsonValue,
36 pub correlation_id: Option<String>,
37 #[serde(default)]
38 pub extensions: BTreeMap<String, JsonValue>,
39}
40
41#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
42pub struct TopicListRequest {
43 pub cursor: Option<String>,
44 pub limit: Option<usize>,
45 #[serde(default)]
46 pub extensions: BTreeMap<String, JsonValue>,
47}
48
49#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
50pub struct TopicListResult {
51 pub topics: Vec<TopicRecord>,
52 pub next_cursor: Option<String>,
53}
54
55#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
56pub struct TopicSubscriptionRequest {
57 pub topic_id: TopicId,
58 pub cursor: Option<String>,
59 #[serde(default)]
60 pub extensions: BTreeMap<String, JsonValue>,
61}
62
63#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
64pub struct TelemetryQuery {
65 pub peer_id: Option<String>,
66 pub topic_id: Option<TopicId>,
67 pub from_ts_ms: Option<u64>,
68 pub to_ts_ms: Option<u64>,
69 pub limit: Option<usize>,
70 #[serde(default)]
71 pub extensions: BTreeMap<String, JsonValue>,
72}
73
74#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
75pub struct TelemetryPoint {
76 pub ts_ms: u64,
77 pub key: String,
78 pub value: JsonValue,
79 pub unit: Option<String>,
80 #[serde(default)]
81 pub tags: BTreeMap<String, String>,
82 #[serde(default)]
83 pub extensions: BTreeMap<String, JsonValue>,
84}
85
86#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
87pub struct AttachmentId(pub String);
88
89#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
90pub struct AttachmentStoreRequest {
91 pub name: String,
92 pub content_type: String,
93 pub bytes_base64: String,
94 pub expires_ts_ms: Option<u64>,
95 #[serde(default)]
96 pub topic_ids: Vec<TopicId>,
97 #[serde(default)]
98 pub extensions: BTreeMap<String, JsonValue>,
99}
100
101#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
102pub struct AttachmentMeta {
103 pub attachment_id: AttachmentId,
104 pub name: String,
105 pub content_type: String,
106 pub byte_len: u64,
107 pub checksum_sha256: String,
108 pub created_ts_ms: u64,
109 pub expires_ts_ms: Option<u64>,
110 #[serde(default)]
111 pub topic_ids: Vec<TopicId>,
112 #[serde(default)]
113 pub extensions: BTreeMap<String, JsonValue>,
114}
115
116#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
117pub struct AttachmentListRequest {
118 pub topic_id: Option<TopicId>,
119 pub cursor: Option<String>,
120 pub limit: Option<usize>,
121 #[serde(default)]
122 pub extensions: BTreeMap<String, JsonValue>,
123}
124
125#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
126pub struct AttachmentListResult {
127 pub attachments: Vec<AttachmentMeta>,
128 pub next_cursor: Option<String>,
129}
130
131#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
132pub struct AttachmentUploadId(pub String);
133
134#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
135pub struct AttachmentUploadStartRequest {
136 pub name: String,
137 pub content_type: String,
138 pub total_size: u64,
139 pub checksum_sha256: String,
140 pub expires_ts_ms: Option<u64>,
141 #[serde(default)]
142 pub topic_ids: Vec<TopicId>,
143 #[serde(default)]
144 pub extensions: BTreeMap<String, JsonValue>,
145}
146
147#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
148pub struct AttachmentUploadSession {
149 pub upload_id: AttachmentUploadId,
150 pub attachment_id: AttachmentId,
151 pub chunk_size_hint: usize,
152 pub next_offset: u64,
153}
154
155#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
156pub struct AttachmentUploadChunkRequest {
157 pub upload_id: AttachmentUploadId,
158 pub offset: u64,
159 pub bytes_base64: String,
160 #[serde(default)]
161 pub extensions: BTreeMap<String, JsonValue>,
162}
163
164#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
165pub struct AttachmentUploadChunkAck {
166 pub accepted: bool,
167 pub next_offset: u64,
168 pub complete: bool,
169}
170
171#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
172pub struct AttachmentUploadCommitRequest {
173 pub upload_id: AttachmentUploadId,
174 #[serde(default)]
175 pub extensions: BTreeMap<String, JsonValue>,
176}
177
178#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
179pub struct AttachmentDownloadChunkRequest {
180 pub attachment_id: AttachmentId,
181 pub offset: u64,
182 pub max_bytes: usize,
183 #[serde(default)]
184 pub extensions: BTreeMap<String, JsonValue>,
185}
186
187#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
188pub struct AttachmentDownloadChunk {
189 pub attachment_id: AttachmentId,
190 pub offset: u64,
191 pub next_offset: u64,
192 pub total_size: u64,
193 pub done: bool,
194 pub checksum_sha256: String,
195 pub bytes_base64: String,
196}
197
198#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
199pub struct MarkerId(pub String);
200
201#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
202pub struct GeoPoint {
203 pub lat: f64,
204 pub lon: f64,
205 pub alt_m: Option<f64>,
206}
207
208#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
209pub struct MarkerCreateRequest {
210 pub label: String,
211 pub position: GeoPoint,
212 pub topic_id: Option<TopicId>,
213 #[serde(default)]
214 pub extensions: BTreeMap<String, JsonValue>,
215}
216
217#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
218pub struct MarkerUpdatePositionRequest {
219 pub marker_id: MarkerId,
220 pub expected_revision: u64,
221 pub position: GeoPoint,
222 #[serde(default)]
223 pub extensions: BTreeMap<String, JsonValue>,
224}
225
226#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
227pub struct MarkerDeleteRequest {
228 pub marker_id: MarkerId,
229 pub expected_revision: u64,
230 #[serde(default)]
231 pub extensions: BTreeMap<String, JsonValue>,
232}
233
234#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
235pub struct MarkerRecord {
236 pub marker_id: MarkerId,
237 pub label: String,
238 pub position: GeoPoint,
239 pub topic_id: Option<TopicId>,
240 pub revision: u64,
241 pub updated_ts_ms: u64,
242 #[serde(default)]
243 pub extensions: BTreeMap<String, JsonValue>,
244}
245
246#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
247pub struct MarkerListRequest {
248 pub topic_id: Option<TopicId>,
249 pub cursor: Option<String>,
250 pub limit: Option<usize>,
251 #[serde(default)]
252 pub extensions: BTreeMap<String, JsonValue>,
253}
254
255#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
256pub struct MarkerListResult {
257 pub markers: Vec<MarkerRecord>,
258 pub next_cursor: Option<String>,
259}
260
261#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
262pub struct IdentityRef(pub String);
263
264#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
265pub struct IdentityBundle {
266 pub identity: IdentityRef,
267 pub public_key: String,
268 pub display_name: Option<String>,
269 #[serde(default)]
270 pub capabilities: Vec<String>,
271 #[serde(default)]
272 pub extensions: BTreeMap<String, JsonValue>,
273}
274
275#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
276pub struct IdentityImportRequest {
277 pub bundle_base64: String,
278 pub passphrase: Option<String>,
279 #[serde(default)]
280 pub extensions: BTreeMap<String, JsonValue>,
281}
282
283#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
284pub struct IdentityResolveRequest {
285 pub hash: String,
286 #[serde(default)]
287 pub extensions: BTreeMap<String, JsonValue>,
288}
289
290#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
291#[serde(rename_all = "snake_case")]
292pub enum TrustLevel {
293 Unknown,
294 Untrusted,
295 Trusted,
296 Blocked,
297}
298
299#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
300pub struct ContactUpdateRequest {
301 pub identity: IdentityRef,
302 pub display_name: Option<String>,
303 pub trust_level: Option<TrustLevel>,
304 pub bootstrap: Option<bool>,
305 #[serde(default)]
306 pub metadata: BTreeMap<String, JsonValue>,
307 #[serde(default)]
308 pub extensions: BTreeMap<String, JsonValue>,
309}
310
311#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
312pub struct ContactRecord {
313 pub identity: IdentityRef,
314 pub display_name: Option<String>,
315 pub trust_level: TrustLevel,
316 pub bootstrap: bool,
317 pub updated_ts_ms: u64,
318 #[serde(default)]
319 pub metadata: BTreeMap<String, JsonValue>,
320 #[serde(default)]
321 pub extensions: BTreeMap<String, JsonValue>,
322}
323
324#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
325pub struct ContactListRequest {
326 pub cursor: Option<String>,
327 pub limit: Option<usize>,
328 #[serde(default)]
329 pub extensions: BTreeMap<String, JsonValue>,
330}
331
332#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
333pub struct ContactListResult {
334 pub contacts: Vec<ContactRecord>,
335 pub next_cursor: Option<String>,
336}
337
338#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
339pub struct PresenceListRequest {
340 pub cursor: Option<String>,
341 pub limit: Option<usize>,
342 #[serde(default)]
343 pub extensions: BTreeMap<String, JsonValue>,
344}
345
346#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
347pub struct PresenceRecord {
348 pub peer_id: String,
349 pub last_seen_ts_ms: i64,
350 pub first_seen_ts_ms: i64,
351 pub seen_count: u64,
352 pub name: Option<String>,
353 pub name_source: Option<String>,
354 pub trust_level: Option<TrustLevel>,
355 pub bootstrap: Option<bool>,
356 #[serde(default)]
357 pub extensions: BTreeMap<String, JsonValue>,
358}
359
360#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
361pub struct PresenceListResult {
362 pub peers: Vec<PresenceRecord>,
363 pub next_cursor: Option<String>,
364}
365
366#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
367pub struct IdentityBootstrapRequest {
368 pub identity: IdentityRef,
369 #[serde(default = "default_auto_sync")]
370 pub auto_sync: bool,
371 #[serde(default)]
372 pub extensions: BTreeMap<String, JsonValue>,
373}
374
375fn default_auto_sync() -> bool {
376 true
377}
378
379#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
380pub struct PaperMessageEnvelope {
381 pub uri: String,
382 pub transient_id: Option<String>,
383 pub destination_hint: Option<String>,
384 #[serde(default)]
385 pub extensions: BTreeMap<String, JsonValue>,
386}
387
388#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
389pub struct RemoteCommandRequest {
390 pub command: String,
391 pub target: Option<String>,
392 pub payload: JsonValue,
393 pub timeout_ms: Option<u64>,
394 #[serde(default)]
395 pub extensions: BTreeMap<String, JsonValue>,
396}
397
398#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
399pub struct RemoteCommandResponse {
400 pub accepted: bool,
401 pub payload: JsonValue,
402 #[serde(default)]
403 pub extensions: BTreeMap<String, JsonValue>,
404}
405
406#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
407#[serde(rename_all = "snake_case")]
408pub enum RemoteCommandState {
409 Dispatched,
410 ReceiptAcknowledged,
411 Processing,
412 Completed,
413 Failed,
414 #[serde(other)]
415 Unknown,
416}
417
418#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
419pub struct RemoteCommandSession {
420 pub command_id: String,
421 pub correlation_id: String,
422 pub command: String,
423 pub target: Option<String>,
424 pub timeout_ms: Option<u64>,
425 pub delivery_state: Option<String>,
426 pub command_state: RemoteCommandState,
427 pub created_at_ms: u64,
428 pub updated_at_ms: u64,
429 pub request_payload: JsonValue,
430 pub response_payload: Option<JsonValue>,
431 pub accepted: Option<bool>,
432 #[serde(default)]
433 pub extensions: BTreeMap<String, JsonValue>,
434}
435
436#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
437pub struct RemoteCommandSessionListRequest {
438 pub cursor: Option<String>,
439 pub limit: Option<usize>,
440 #[serde(default)]
441 pub extensions: BTreeMap<String, JsonValue>,
442}
443
444#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
445pub struct RemoteCommandSessionListResult {
446 pub sessions: Vec<RemoteCommandSession>,
447 pub next_cursor: Option<String>,
448}
449
450#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
451pub struct VoiceSessionId(pub String);
452
453#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
454#[serde(rename_all = "snake_case")]
455pub enum VoiceSessionState {
456 New,
457 Ringing,
458 Active,
459 Holding,
460 Closed,
461 Failed,
462 #[serde(other)]
463 Unknown,
464}
465
466#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
467pub struct VoiceSessionOpenRequest {
468 pub peer_id: String,
469 pub codec_hint: Option<String>,
470 #[serde(default)]
471 pub extensions: BTreeMap<String, JsonValue>,
472}
473
474#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
475pub struct VoiceSessionUpdateRequest {
476 pub session_id: VoiceSessionId,
477 pub state: VoiceSessionState,
478 #[serde(default)]
479 pub extensions: BTreeMap<String, JsonValue>,
480}
481
482#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
483pub struct WorkflowPeerReadyRequest {
484 pub identity: IdentityRef,
485 pub display_name: Option<String>,
486 pub trust_level: Option<TrustLevel>,
487 pub bootstrap: Option<bool>,
488 pub announce: Option<bool>,
489 #[serde(default)]
490 pub metadata: BTreeMap<String, JsonValue>,
491 #[serde(default)]
492 pub extensions: BTreeMap<String, JsonValue>,
493}
494
495#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
496pub struct WorkflowPeerReadyResult {
497 pub identity: IdentityRef,
498 pub contact: ContactRecord,
499 pub was_created: bool,
500 pub announced: bool,
501}
502
503#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
504pub struct WorkflowTopicSyncRequest {
505 pub topic_path: TopicPath,
506 #[serde(default)]
507 pub metadata: BTreeMap<String, JsonValue>,
508 pub telemetry_limit: Option<usize>,
509 #[serde(default)]
510 pub extensions: BTreeMap<String, JsonValue>,
511}
512
513#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
514pub struct WorkflowTopicSyncResult {
515 pub topic: TopicRecord,
516 pub was_created: bool,
517 pub subscribed: bool,
518 pub telemetry: Vec<TelemetryPoint>,
519}
520
521#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
522pub struct WorkflowAttachmentDraft {
523 pub name: String,
524 pub content_type: String,
525 pub bytes_base64: String,
526}
527
528#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
529pub struct WorkflowAttachmentReportRequest {
530 pub topic_path: TopicPath,
531 pub attachment: WorkflowAttachmentDraft,
532 pub summary_payload: Option<JsonValue>,
533 pub correlation_id: Option<String>,
534 #[serde(default)]
535 pub topic_metadata: BTreeMap<String, JsonValue>,
536 #[serde(default)]
537 pub extensions: BTreeMap<String, JsonValue>,
538}
539
540#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
541pub struct WorkflowAttachmentReportResult {
542 pub topic: TopicRecord,
543 pub attachment: AttachmentMeta,
544 pub published: Ack,
545}
546
547#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
548pub struct WorkflowMissionUpdateRequest {
549 pub peer_identity: IdentityRef,
550 pub content: String,
551 pub topic_path: Option<TopicPath>,
552 #[serde(default)]
553 pub attachments: Vec<WorkflowAttachmentDraft>,
554 #[serde(default)]
555 pub metadata: BTreeMap<String, JsonValue>,
556 pub correlation_id: Option<String>,
557 pub idempotency_key: Option<String>,
558 pub display_name: Option<String>,
559 pub trust_level: Option<TrustLevel>,
560 pub bootstrap: Option<bool>,
561 pub announce: Option<bool>,
562 #[serde(default)]
563 pub extensions: BTreeMap<String, JsonValue>,
564}
565
566#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
567pub struct WorkflowMissionUpdateResult {
568 pub peer: WorkflowPeerReadyResult,
569 pub message_id: MessageId,
570 pub topic: Option<TopicRecord>,
571 pub attachments: Vec<AttachmentMeta>,
572}
573
574#[cfg(test)]
575mod tests {
576 use super::VoiceSessionState;
577
578 #[test]
579 fn voice_session_state_deserializes_unknown_variant() {
580 let value = serde_json::json!("paused_by_gateway");
581 let state: VoiceSessionState =
582 serde_json::from_value(value).expect("unknown voice state should map to Unknown");
583 assert_eq!(state, VoiceSessionState::Unknown);
584 }
585}