Skip to main content

core_api/node/contracts/
audiobridge.rs

1use serde::{Deserialize, Serialize};
2
3pub const VERSION: &str = crate::node::V1;
4pub const NODE_TYPE: &str = "audiobridge";
5pub const RUNTIME_TARGET_PREFIX: &str = "/audiobridge/app/";
6pub const DEVICE_SNAPSHOT: &str = "device/snapshot";
7pub const DEVICE_REFRESH: &str = "device/refresh";
8pub const DEVICE_PAIR: &str = "device/pair";
9pub const DEVICE_UNPAIR: &str = "device/unpair";
10pub const DEVICE_TEST: &str = "device/test";
11
12#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13#[serde(rename_all = "camelCase", deny_unknown_fields)]
14pub struct EmptyRequest {}
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17#[serde(rename_all = "camelCase", deny_unknown_fields)]
18pub struct DeviceRequest {
19    pub device_id: String,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
23#[serde(rename_all = "camelCase")]
24pub struct AudioBridgeDevice {
25    pub device_id: String,
26    pub display_name: String,
27    pub transport: String,
28    pub online: bool,
29}
30
31#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
32#[serde(rename_all = "camelCase")]
33pub struct AudioBridgeCandidate {
34    pub device_id: String,
35    pub display_name: String,
36    pub transport: String,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40#[serde(rename_all = "camelCase")]
41pub struct DeviceSnapshot {
42    #[serde(default)]
43    pub devices: Vec<AudioBridgeDevice>,
44    #[serde(default)]
45    pub candidates: Vec<AudioBridgeCandidate>,
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(rename_all = "camelCase")]
50pub struct PairingResponse {
51    pub changed: bool,
52    pub device: AudioBridgeDevice,
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn public_contract_does_not_expose_platform_identity() {
61        let value = serde_json::to_value(AudioBridgeDevice {
62            device_id: "device-1".to_string(),
63            display_name: "Living Room Speaker".to_string(),
64            transport: "bluetooth".to_string(),
65            online: true,
66        })
67        .expect("serialize device");
68        assert!(value.get("platformKey").is_none());
69        assert!(value.get("endpointId").is_none());
70    }
71
72    #[test]
73    fn device_snapshot_is_the_direct_response_payload() {
74        let value = serde_json::to_value(DeviceSnapshot {
75            devices: Vec::new(),
76            candidates: Vec::new(),
77        })
78        .expect("serialize device snapshot");
79        assert!(value.get("devices").is_some());
80        assert!(value.get("candidates").is_some());
81        assert!(value.get("snapshot").is_none());
82    }
83}