Skip to main content

rust_supervisor/dashboard/
model.rs

1//! Shared dashboard data model.
2//!
3//! These structs are the JSON contract shared by target IPC, relay, and the
4//! dashboard UI. They intentionally use owned values so callers can serialize,
5//! clone, and test messages without borrowing runtime internals.
6
7use schemars::JsonSchema;
8use serde::{Deserialize, Serialize};
9use serde_json::Value;
10use std::collections::BTreeMap;
11
12/// Supported command metadata sent to the relay.
13#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
14pub struct SupportedCommand {
15    /// Wire command name.
16    pub name: String,
17    /// Whether the command can be retried with the same command identifier.
18    pub idempotent: bool,
19    /// Command timeout in seconds.
20    pub timeout_seconds: u64,
21}
22
23/// Target process registration payload sent to the relay.
24#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
25pub struct TargetProcessRegistration {
26    /// Stable target process identifier.
27    pub target_id: String,
28    /// Human-readable display name.
29    pub display_name: String,
30    /// Local Unix domain socket path exposed by the target.
31    pub ipc_path: String,
32    /// Lease duration in seconds.
33    pub lease_seconds: u64,
34    /// Commands supported by this target.
35    pub supported_commands: Vec<SupportedCommand>,
36}
37
38/// Current registration state for a target process.
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
40#[serde(rename_all = "snake_case")]
41pub enum RegistrationState {
42    /// Registration was accepted and is visible.
43    Active,
44    /// Registration was rejected.
45    Rejected,
46    /// Registration lease expired.
47    Expired,
48}
49
50/// Current relay connection state for a target process.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
52#[serde(rename_all = "snake_case")]
53pub enum TargetConnectionState {
54    /// Target is registered but no session has bound it.
55    Registered,
56    /// Relay is connecting to target IPC.
57    Connecting,
58    /// Relay is connected to target IPC.
59    Connected,
60    /// Relay is reconnecting to target IPC.
61    Reconnecting,
62    /// Target IPC is unavailable.
63    Unavailable,
64    /// Registration lease expired.
65    Expired,
66}
67
68/// Target identity shown in dashboard state payloads and target lists.
69#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
70pub struct TargetProcessIdentity {
71    /// Stable target process identifier.
72    pub target_id: String,
73    /// Human-readable display name.
74    pub display_name: String,
75    /// Current registration state.
76    pub registration_state: RegistrationState,
77    /// Current relay connection state.
78    pub connection_state: TargetConnectionState,
79}
80
81/// Complete dashboard state returned when a target is opened or reconnected.
82#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
83pub struct DashboardState {
84    /// Target process identity.
85    pub target: TargetProcessIdentity,
86    /// Supervisor topology.
87    pub topology: SupervisorTopology,
88    /// Runtime state rows indexed by child path.
89    pub runtime_state: Vec<RuntimeState>,
90    /// Recent events retained by the target.
91    pub recent_events: Vec<EventRecord>,
92    /// Recent logs retained by the target.
93    pub recent_logs: Vec<LogRecord>,
94    /// Number of dropped events.
95    pub dropped_event_count: u64,
96    /// Number of dropped logs.
97    pub dropped_log_count: u64,
98    /// Configuration version string.
99    pub config_version: String,
100    /// Generated time as Unix nanoseconds.
101    pub generated_at_unix_nanos: u128,
102    /// Monotonic state generation for this target.
103    pub state_generation: u64,
104}
105
106/// Supervisor graph for dashboard rendering.
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
108pub struct SupervisorTopology {
109    /// Root supervisor node.
110    pub root: SupervisorNode,
111    /// All visible nodes including the root.
112    pub nodes: Vec<SupervisorNode>,
113    /// Parent-child and dependency edges.
114    pub edges: Vec<SupervisorEdge>,
115    /// Node paths in declaration order.
116    pub declaration_order: Vec<String>,
117}
118
119/// Node kind visible in the topology.
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
121#[serde(rename_all = "snake_case")]
122pub enum SupervisorNodeKind {
123    /// Root supervisor node.
124    RootSupervisor,
125    /// Child task node.
126    ChildTask,
127}
128
129/// Criticality shown by dashboard nodes.
130#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
131#[serde(rename_all = "snake_case")]
132pub enum DashboardCriticality {
133    /// Critical child.
134    Critical,
135    /// Standard child.
136    Standard,
137    /// Best-effort child.
138    BestEffort,
139}
140
141/// Node displayed in the supervisor topology.
142#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
143pub struct SupervisorNode {
144    /// Stable node identifier.
145    pub node_id: String,
146    /// Optional child identifier.
147    pub child_id: Option<String>,
148    /// Absolute child path.
149    pub path: String,
150    /// Human-readable node name.
151    pub name: String,
152    /// Node kind.
153    pub kind: SupervisorNodeKind,
154    /// Low-cardinality tags.
155    pub tags: Vec<String>,
156    /// Node criticality.
157    pub criticality: DashboardCriticality,
158    /// Current state summary.
159    pub state_summary: String,
160    /// Key diagnostic fields.
161    pub diagnostics: BTreeMap<String, String>,
162}
163
164/// Edge kind visible in the topology.
165#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
166#[serde(rename_all = "snake_case")]
167pub enum SupervisorEdgeKind {
168    /// Parent-child edge.
169    ParentChild,
170    /// Dependency edge.
171    Dependency,
172}
173
174/// Edge displayed in the supervisor topology.
175#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
176pub struct SupervisorEdge {
177    /// Stable edge identifier.
178    pub edge_id: String,
179    /// Source node path.
180    pub source_path: String,
181    /// Target node path.
182    pub target_path: String,
183    /// Edge kind.
184    pub kind: SupervisorEdgeKind,
185    /// Declaration or dependency order.
186    pub order: usize,
187}
188
189/// Runtime state shown for one child.
190#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
191pub struct RuntimeState {
192    /// Child path.
193    pub child_path: String,
194    /// Lifecycle state label.
195    pub lifecycle_state: String,
196    /// Health status label.
197    pub health: String,
198    /// Readiness status label.
199    pub readiness: String,
200    /// Child generation.
201    pub generation: u64,
202    /// Child attempt.
203    pub attempt: u64,
204    /// Restart count.
205    pub restart_count: u64,
206    /// Optional last failure summary.
207    pub last_failure: Option<String>,
208    /// Optional last policy decision summary.
209    pub last_policy_decision: Option<String>,
210    /// Supervisor shutdown state label.
211    pub shutdown_state: String,
212}
213
214/// Event record streamed from a target process.
215#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
216pub struct EventRecord {
217    /// Target process identifier.
218    pub target_id: String,
219    /// Target-local monotonic sequence.
220    pub sequence: u64,
221    /// Correlation identifier.
222    pub correlation_id: String,
223    /// Event type label.
224    pub event_type: String,
225    /// Severity label.
226    pub severity: String,
227    /// Target path.
228    pub target_path: String,
229    /// Optional child identifier.
230    pub child_id: Option<String>,
231    /// Occurred time as Unix nanoseconds.
232    pub occurred_at_unix_nanos: u128,
233    /// Configuration version.
234    pub config_version: String,
235    /// Event payload.
236    pub payload: Value,
237}
238
239/// Log record streamed from a target process.
240#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
241pub struct LogRecord {
242    /// Target process identifier.
243    pub target_id: String,
244    /// Optional target-local sequence.
245    pub sequence: Option<u64>,
246    /// Optional correlation identifier.
247    pub correlation_id: Option<String>,
248    /// Severity label.
249    pub severity: String,
250    /// Log message.
251    pub message: String,
252    /// Structured log fields.
253    pub fields: BTreeMap<String, String>,
254    /// Occurred time as Unix nanoseconds.
255    pub occurred_at_unix_nanos: u128,
256}
257
258/// Supported control command names.
259#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
260#[serde(rename_all = "snake_case")]
261pub enum ControlCommandKind {
262    /// Restart a child.
263    RestartChild,
264    /// Pause a child.
265    PauseChild,
266    /// Resume a child.
267    ResumeChild,
268    /// Quarantine a child.
269    QuarantineChild,
270    /// Remove a child.
271    RemoveChild,
272    /// Add a child.
273    AddChild,
274    /// Shut down the whole tree.
275    ShutdownTree,
276}
277
278/// Target selector for a control command.
279#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
280pub struct ControlCommandTarget {
281    /// Optional child path for child-scoped commands.
282    pub child_path: Option<String>,
283    /// Optional child manifest for add-child commands.
284    pub child_manifest: Option<String>,
285}
286
287/// Control command request forwarded by relay to target IPC.
288#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
289pub struct ControlCommandRequest {
290    /// Command identifier.
291    pub command_id: String,
292    /// Target process identifier.
293    pub target_id: String,
294    /// Command kind.
295    pub command: ControlCommandKind,
296    /// Command target.
297    pub target: ControlCommandTarget,
298    /// Non-empty reason.
299    pub reason: String,
300    /// Authenticated requester derived by relay.
301    pub requested_by: String,
302    /// Whether dangerous command confirmation is present.
303    pub confirmed: bool,
304    /// Request time as Unix nanoseconds.
305    pub requested_at_unix_nanos: u128,
306}
307
308/// Control command result returned by target IPC.
309#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
310pub struct ControlCommandResult {
311    /// Command identifier.
312    pub command_id: String,
313    /// Target process identifier.
314    pub target_id: String,
315    /// Whether target accepted the command.
316    pub accepted: bool,
317    /// Status label.
318    pub status: String,
319    /// Optional structured error.
320    pub error: Option<crate::dashboard::error::DashboardError>,
321    /// Optional state delta.
322    pub state_delta: Option<Value>,
323    /// Completion time as Unix nanoseconds.
324    pub completed_at_unix_nanos: Option<u128>,
325}
326
327/// Audit event emitted for accepted, rejected, and completed commands.
328#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
329pub struct AuditEvent {
330    /// Audit event identifier.
331    pub audit_id: String,
332    /// Remote identity summary.
333    pub identity: String,
334    /// Target process identifier.
335    pub target_id: String,
336    /// Command identifier.
337    pub command_id: String,
338    /// Command kind.
339    pub command: ControlCommandKind,
340    /// Command target.
341    pub target: ControlCommandTarget,
342    /// Operator-provided reason.
343    pub reason: String,
344    /// Result summary.
345    pub result: String,
346    /// Occurred time as Unix nanoseconds.
347    pub occurred_at_unix_nanos: u128,
348}