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}