gregg_protocol/lib.rs
1//! `gregg-protocol` defines the versioned JSON wire contract shared by the
2//! `greggd` daemon and the `gregg` client.
3//!
4//! The crate is intentionally dependency-light (only `serde`, `serde_json`, and
5//! `thiserror`) so it can be consumed by collectors, the HTTP server, the
6//! polling engine, and tests without dragging in larger stacks.
7//!
8//! # Schema version 1
9//!
10//! Every snapshot carries an explicit
11//! [`SCHEMA_VERSION_V1`](constant.SCHEMA_VERSION_V1) so clients can reject
12//! incompatible payloads per host without terminating the whole TUI.
13//!
14//! Numeric values are transported as raw units — bytes for memory and swap,
15//! percentages in the closed interval `0.0..=100.0` for utilization, and
16//! milliseconds since the Unix epoch for timestamps. No human-formatted
17//! strings cross the wire.
18//!
19//! # Compatibility policy
20//!
21//! Within schema version 1:
22//!
23//! - Unknown additive JSON fields are ignored by default.
24//! - Required version-1 fields remain required unless explicitly changed to
25//! optional under an additive compatibility decision.
26//! - Capability flags control interpretation of optional metrics. A `None`
27//! value paired with a `false` capability is expected; a `None` value
28//! paired with a `true` capability indicates a missing or still-warming
29//! sample.
30//!
31//! # Examples
32//!
33//! ```
34//! use gregg_protocol::{StatusSnapshot, HealthResponse, ReadinessState, SCHEMA_VERSION_V1};
35//!
36//! let json = format!(r#"{{
37//! "schema_version": {sv},
38//! "observed_at_unix_ms": 1,
39//! "sample_interval_ms": 1000,
40//! "capabilities": {{ "cpu_iowait": false }},
41//! "system": {{
42//! "name": "mac-mini",
43//! "hostname": "mac-mini.local",
44//! "os_name": "macos",
45//! "os_version": "15.0",
46//! "kernel_name": "Darwin",
47//! "kernel_release": "24.0.0",
48//! "architecture": "arm64"
49//! }},
50//! "cpu": {{ "logical_cores": 8, "usage_pct": 12.5, "iowait_pct": null }},
51//! "load": {{ "one": 1.1, "five": 0.9, "fifteen": 0.6 }},
52//! "memory": {{ "used_bytes": 1, "total_bytes": 2, "usage_pct": 50.0 }},
53//! "swap": {{ "used_bytes": 0, "total_bytes": 0, "usage_pct": 0.0 }}
54//! }}"#, sv = SCHEMA_VERSION_V1);
55//!
56//! let snap: StatusSnapshot = serde_json::from_str(&json).expect("valid snapshot");
57//! snap.validate().expect("snapshot validates");
58//!
59//! let health = HealthResponse::warming();
60//! assert_eq!(health.state, ReadinessState::Warming);
61//! ```
62
63#![forbid(unsafe_code)]
64
65mod health;
66mod snapshot;
67mod validate;
68
69#[cfg(feature = "test_support")]
70pub mod test_support;
71
72pub use health::{HealthCategory, HealthResponse, ReadinessState};
73pub use snapshot::{
74 CpuMetrics, LoadAverage, MemoryMetrics, MetricCapabilities, StatusSnapshot, SwapMetrics,
75 SystemIdentity,
76};
77pub use validate::{ValidationViolation, ViolationKind};
78
79/// Schema major version implemented by this crate.
80///
81/// Wire payloads whose `schema_version` does not match this value are
82/// rejected by [`StatusSnapshot::validate`]. Additive changes within version 1
83/// are allowed by the compatibility policy; breaking changes require a new
84/// schema major and explicit migration handling.
85pub const SCHEMA_VERSION_V1: u16 = 1;