Skip to main content

app_facade_api/
system.rs

1//! Space-owned runtime instances, Client sessions, and Hub-vantage Host inventory
2//! and management. The Hub acts as the current Space member against LAN Hosts.
3use core_api::host::management::HostRuntimeRequest;
4use core_api::host::HostInfo;
5use serde::{Deserialize, Serialize};
6pub const INSTANCES_TARGET: &str = "/app/system/instances/get";
7pub const CLIENTS_TARGET: &str = "/app/system/clients/get";
8pub const HOSTS_TARGET: &str = "/app/system/hosts/get";
9pub const HOSTS_RUNTIME_TARGET: &str = "/app/system/hosts/runtime";
10pub const HOSTS_CLAIM_TARGET: &str = "/app/system/hosts/claim";
11pub const INSTANCES_CONTRACT: &str = "mhome.system.instances.v1";
12pub const CLIENTS_CONTRACT: &str = "mhome.system.clients.v1";
13pub const HOSTS_CONTRACT: &str = "mhome.system.hosts.v1";
14pub const HOSTS_RUNTIME_CONTRACT: &str = "mhome.system.hosts.runtime.v1";
15pub const HOSTS_CLAIM_CONTRACT: &str = "mhome.system.hosts.claim.v1";
16pub type HostsRuntimeRequest = HostRuntimeRequest<String>;
17#[derive(Debug, Default, Deserialize)]
18#[serde(deny_unknown_fields)]
19pub struct InstancesRequest {}
20/// Query success and data freshness are independent; failed refreshes retain the last observation.
21#[derive(Debug, Clone, Serialize, Deserialize)]
22#[serde(rename_all = "camelCase")]
23pub struct Observation<T> {
24    pub status: ObservationStatus,
25    pub data: Option<T>,
26    pub observed_at_ms: Option<i64>,
27    pub last_attempt_at_ms: Option<i64>,
28    pub stale: bool,
29    pub error_code: Option<String>,
30}
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub enum ObservationStatus {
34    Ok,
35    Unavailable,
36    Unsupported,
37    NotQueried,
38}
39impl<T> Default for Observation<T> {
40    fn default() -> Self {
41        Self {
42            status: ObservationStatus::NotQueried,
43            data: None,
44            observed_at_ms: None,
45            last_attempt_at_ms: None,
46            stale: false,
47            error_code: None,
48        }
49    }
50}
51impl<T> Observation<T> {
52    pub fn success(&mut self, data: T, observed: i64, attempted: i64) {
53        self.status = ObservationStatus::Ok;
54        self.data = Some(data);
55        self.observed_at_ms = Some(observed);
56        self.last_attempt_at_ms = Some(attempted);
57        self.stale = false;
58        self.error_code = None;
59    }
60    pub fn failed(&mut self, status: ObservationStatus, code: &str, attempted: i64) {
61        self.status = status;
62        self.last_attempt_at_ms = Some(attempted);
63        self.stale = self.data.is_some();
64        self.error_code = Some(code.into());
65    }
66}
67#[derive(Debug, Clone, Serialize, Deserialize)]
68#[serde(rename_all = "camelCase")]
69pub struct Instance {
70    pub id: String,
71    pub kind: String,
72    pub host_id: String,
73    pub service_id: String,
74    pub display_name: String,
75    pub node_type: Option<String>,
76    pub hub_id: String,
77    pub commissioned: bool,
78    pub lifecycle: Option<String>,
79    pub hub_connection: Option<String>,
80    pub cloud_connection: Option<String>,
81    pub health: Observation<String>,
82}
83#[derive(Debug, Serialize, Deserialize)]
84#[serde(rename_all = "camelCase")]
85pub struct Instances {
86    pub contract: String,
87    pub scope_id: String,
88    pub observed_at_ms: i64,
89    pub instances: Vec<Instance>,
90}
91#[derive(Debug, Serialize, Deserialize)]
92#[serde(rename_all = "camelCase")]
93pub struct ClientSession {
94    pub app_client_id: String,
95    pub session_id: String,
96    pub source: String,
97    pub device_type: String,
98    pub is_current: bool,
99    pub route_kind: Option<String>,
100}
101#[derive(Debug, Serialize, Deserialize)]
102#[serde(rename_all = "camelCase")]
103pub struct Clients {
104    pub contract: String,
105    pub scope_id: String,
106    pub observed_at_ms: i64,
107    pub sessions: Vec<ClientSession>,
108}
109/// Hub-vantage machine observation. `source` is `local` for the Hub host or `mdns`
110/// for other LAN records. `/info` is signed LAN for every reachable Host.
111/// `claimable` is Host ACL empty; it is not an `/info` error.
112#[derive(Debug, Clone, Serialize, Deserialize)]
113#[serde(rename_all = "camelCase")]
114pub struct Host {
115    pub host_id: String,
116    pub host_name: String,
117    pub host_type: String,
118    pub source: String,
119    pub reachable: bool,
120    #[serde(default)]
121    pub claimable: bool,
122    pub info: Observation<HostInfo>,
123}
124#[derive(Debug, Serialize, Deserialize)]
125#[serde(rename_all = "camelCase")]
126pub struct Hosts {
127    pub contract: String,
128    pub scope_id: String,
129    pub observed_at_ms: i64,
130    pub hosts: Vec<Host>,
131}
132/// Hub-vantage Host management. `result` is the native Host runtime payload
133/// (`HostRuntimeResponse.data` or metrics).
134#[derive(Debug, Serialize, Deserialize)]
135#[serde(rename_all = "camelCase")]
136pub struct HostsRuntime {
137    pub contract: String,
138    pub scope_id: String,
139    pub host_id: String,
140    pub result: serde_json::Value,
141}
142#[derive(Debug, Deserialize)]
143#[serde(rename_all = "camelCase", deny_unknown_fields)]
144pub struct HostsClaimRequest {
145    pub host_id: String,
146    /// Required for the first claim of a Host provisioned over BLE.
147    #[serde(default)]
148    pub claim_token: Option<String>,
149}
150/// Hub-vantage first-claim of an unused LAN Host for the current Space member.
151#[derive(Debug, Serialize, Deserialize)]
152#[serde(rename_all = "camelCase")]
153pub struct HostsClaim {
154    pub contract: String,
155    pub scope_id: String,
156    pub host_id: String,
157    pub claimed: bool,
158}