1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
use serde::{Deserialize, Serialize};
/// Key under which a governance directive is placed in a `ChannelEvent.payload`.
pub const COMMANDER_DIRECTIVE_KEY: &str = "commander_directive";
/// A cryptographically-signed instruction from the Commander governance plane.
///
/// Serialised as a JSON object and placed under [`COMMANDER_DIRECTIVE_KEY`]
/// in a `ChannelEvent.payload` appended to the `fleet-<name>` channel. The
/// signing layer lives in `mur-core`; this crate only owns the payload shape.
/// Cross-network A2A-envelope delivery is Phase 2.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CommanderDirective {
/// Directive kind, e.g. `"kill"`, `"budget_ceiling"`.
pub kind: String,
/// Target fleet name.
pub fleet: String,
/// Optional budget ceiling in USD; `>=0` is honoured, `<0`/`NaN` ignored.
pub budget_usd: Option<f64>,
/// Replay-prevention nonce (UUID v4 recommended).
pub nonce: String,
/// Wall-clock milliseconds since Unix epoch when the directive was issued.
pub issued_at_ms: u64,
}
/// Derived governance state for a running fleet loop.
///
/// Built by reducing the stream of [`CommanderDirective`]s received so far.
#[derive(Debug, Clone, Default, PartialEq)]
pub struct GovernanceState {
/// If `true`, the loop must stop immediately.
pub killed: bool,
/// Active budget ceiling (USD), if any has been applied.
pub budget_ceiling: Option<f64>,
/// Nonce of the directive that produced `killed == true` (audit binding).
/// `None` when not killed, or after a resume clears the kill.
pub kill_nonce: Option<String>,
/// Nonce of the directive that set `budget_ceiling` (audit binding).
pub budget_nonce: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn directive_roundtrips_under_the_marker_key() {
let d = CommanderDirective {
kind: "kill".into(),
fleet: "dev".into(),
budget_usd: None,
nonce: "n1".into(),
issued_at_ms: 1_750_000_000_000,
};
let wrapped = serde_json::json!({ COMMANDER_DIRECTIVE_KEY: &d });
let got: CommanderDirective =
serde_json::from_value(wrapped[COMMANDER_DIRECTIVE_KEY].clone()).unwrap();
assert_eq!(got.kind, "kill");
assert_eq!(got.fleet, "dev");
assert_eq!(got.issued_at_ms, 1_750_000_000_000);
}
#[test]
fn governance_state_default_is_inert() {
let g = GovernanceState::default();
assert!(!g.killed && g.budget_ceiling.is_none());
}
}