Skip to main content

kanade_shared/ipc/
method.rs

1//! Method-name string constants for the KLP v1 namespace (SPEC §2.12.5).
2//!
3//! Centralised so the agent dispatcher and client call sites refer
4//! to the same string literal — a typo on either side becomes a
5//! compile error instead of a silent `MethodNotFound` at runtime.
6//!
7//! The constants intentionally mirror the SPEC table 1:1; future
8//! v2 method additions add a new entry here, never edit an existing
9//! one (the protocol-version handshake in §2.12.6 is the
10//! deprecation path).
11
12// ---- system.* ----
13
14/// Handshake — every connection's first request. SPEC §2.12.6.
15pub const SYSTEM_HANDSHAKE: &str = "system.handshake";
16/// Liveness check. No params, no return value beyond ack.
17pub const SYSTEM_PING: &str = "system.ping";
18/// Returns the agent's binary version + git rev.
19pub const SYSTEM_VERSION: &str = "system.version";
20/// Last N lines of `agent.log` for support handoff (SPEC §2.12.5).
21pub const SYSTEM_LOG_TAIL: &str = "system.log_tail";
22
23// ---- state.* ----
24
25/// One-shot bundle of health + inventory + compliance checks.
26pub const STATE_SNAPSHOT: &str = "state.snapshot";
27/// Start streaming `state.changed` pushes for this connection.
28pub const STATE_SUBSCRIBE: &str = "state.subscribe";
29/// Stop streaming `state.changed` pushes (the matching unsubscribe).
30pub const STATE_UNSUBSCRIBE: &str = "state.unsubscribe";
31/// Push (Agent → Client) when health / version etc. flips.
32pub const STATE_CHANGED: &str = "state.changed";
33
34// ---- notifications.* ----
35
36/// Paginated past-notifications listing (filter: unread/all).
37pub const NOTIFICATIONS_LIST: &str = "notifications.list";
38/// Start streaming `notifications.new` pushes for this connection.
39pub const NOTIFICATIONS_SUBSCRIBE: &str = "notifications.subscribe";
40/// Stop streaming `notifications.new` pushes.
41pub const NOTIFICATIONS_UNSUBSCRIBE: &str = "notifications.unsubscribe";
42/// Push (Agent → Client) carrying a new notification.
43pub const NOTIFICATIONS_NEW: &str = "notifications.new";
44/// Mark a notification read for this user — agent publishes
45/// `events.notifications.acked.>` on NATS with the OS-derived SID.
46pub const NOTIFICATIONS_ACK: &str = "notifications.ack";
47/// Undo a prior ack (read↔unread toggle) for this user — agent deletes
48/// the `notifications_read` KV entry and publishes
49/// `events.notifications.unacked.>` so the backend records the revoke
50/// as an audit event and flips the SPA roster back to "未確認". The
51/// `notification_ack_events` log keeps the original ack, so the operator
52/// can still see the user *had* confirmed before retracting.
53pub const NOTIFICATIONS_UNACK: &str = "notifications.unack";
54/// Push (Agent → Client) carrying a post-send amendment to a notification
55/// the client may be showing — currently a recall (delete it from screen).
56pub const NOTIFICATIONS_AMENDED: &str = "notifications.amended";
57
58// ---- jobs.* ----
59
60/// List manifests with `user_invokable: true` (filter: category).
61pub const JOBS_LIST: &str = "jobs.list";
62/// Execute one of the listed jobs. Returns the synthesised `run_id`.
63pub const JOBS_EXECUTE: &str = "jobs.execute";
64/// Start streaming `jobs.progress` pushes for this connection.
65pub const JOBS_SUBSCRIBE: &str = "jobs.subscribe";
66/// Stop streaming `jobs.progress` pushes.
67pub const JOBS_UNSUBSCRIBE: &str = "jobs.unsubscribe";
68/// Push (Agent → Client) with stdout/stderr chunks + status changes.
69pub const JOBS_PROGRESS: &str = "jobs.progress";
70/// Kill a run started via `jobs.execute` on THIS connection (SPEC
71/// §2.12.4 — cross-connection kill is `Unauthorized`).
72pub const JOBS_KILL: &str = "jobs.kill";
73
74// ---- support.* ----
75
76/// Bundle recent inventory + log tail + agent state, upload to the
77/// JetStream Object Store, return the resulting ticket / object id.
78pub const SUPPORT_UPLOAD_DIAGNOSTICS: &str = "support.upload_diagnostics";
79
80// ---- maintenance.* ----
81
82/// List the next N days' scheduled jobs targeted at this PC.
83pub const MAINTENANCE_LIST: &str = "maintenance.list";
84/// User-initiated reboot-deferral (15m / 30m / 1h per SPEC §2.1).
85pub const MAINTENANCE_DEFER: &str = "maintenance.defer";
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn method_names_are_stable_strings() {
93        // Pin the wire spellings so a careless rename can't drift
94        // them away from SPEC §2.12.5's table. New methods → new
95        // const + new assert here.
96        assert_eq!(SYSTEM_HANDSHAKE, "system.handshake");
97        assert_eq!(SYSTEM_PING, "system.ping");
98        assert_eq!(SYSTEM_VERSION, "system.version");
99        assert_eq!(SYSTEM_LOG_TAIL, "system.log_tail");
100
101        assert_eq!(STATE_SNAPSHOT, "state.snapshot");
102        assert_eq!(STATE_SUBSCRIBE, "state.subscribe");
103        assert_eq!(STATE_UNSUBSCRIBE, "state.unsubscribe");
104        assert_eq!(STATE_CHANGED, "state.changed");
105
106        assert_eq!(NOTIFICATIONS_LIST, "notifications.list");
107        assert_eq!(NOTIFICATIONS_SUBSCRIBE, "notifications.subscribe");
108        assert_eq!(NOTIFICATIONS_UNSUBSCRIBE, "notifications.unsubscribe");
109        assert_eq!(NOTIFICATIONS_NEW, "notifications.new");
110        assert_eq!(NOTIFICATIONS_ACK, "notifications.ack");
111        assert_eq!(NOTIFICATIONS_UNACK, "notifications.unack");
112        assert_eq!(NOTIFICATIONS_AMENDED, "notifications.amended");
113
114        assert_eq!(JOBS_LIST, "jobs.list");
115        assert_eq!(JOBS_EXECUTE, "jobs.execute");
116        assert_eq!(JOBS_SUBSCRIBE, "jobs.subscribe");
117        assert_eq!(JOBS_UNSUBSCRIBE, "jobs.unsubscribe");
118        assert_eq!(JOBS_PROGRESS, "jobs.progress");
119        assert_eq!(JOBS_KILL, "jobs.kill");
120
121        assert_eq!(SUPPORT_UPLOAD_DIAGNOSTICS, "support.upload_diagnostics");
122
123        assert_eq!(MAINTENANCE_LIST, "maintenance.list");
124        assert_eq!(MAINTENANCE_DEFER, "maintenance.defer");
125    }
126}