1use crate::{
2 ConformanceVector, InstanceId, LawAxis, MaxDiagnostic, PolicyState, Receipt, RepairAction,
3 SnapshotId,
4};
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize, Default)]
8pub struct HookDescriptor {
9 pub hook_id: String,
10 pub name: String,
11 pub description: String,
12 pub axes: Vec<LawAxis>,
13 pub trigger_law: LawAxis,
14 pub input_type: String,
15 pub output_type: String,
16 pub failure_mode: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize, Default)]
20pub struct HookGraphNode {
21 pub node_id: String,
22 pub hook: HookDescriptor,
23 pub predecessors: Vec<String>,
24 pub successors: Vec<String>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize, Default)]
28pub struct ChainDescriptor {
29 pub chain_id: String,
30 pub nodes: Vec<HookGraphNode>,
31 pub law_axis: LawAxis,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize, Default)]
35pub struct PropagationResult {
36 pub propagation_id: String,
37 pub affected_nodes: Vec<String>,
38 pub receipts: Vec<Receipt>,
39 pub success: bool,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize, Default)]
43pub struct AutonomicLoopStatus {
44 pub loop_id: String,
45 pub active: bool,
46 pub iteration_count: u64,
47 pub last_receipt: Option<Receipt>,
48}
49
50#[derive(Debug, Clone, Serialize, Deserialize)]
51pub struct ManifoldSnapshot {
52 pub snapshot_id: SnapshotId,
53 pub conformance: ConformanceVector,
54 pub hooks: Vec<HookDescriptor>,
55 pub chains: Vec<ChainDescriptor>,
56 pub receipts: Vec<Receipt>,
57}
58
59impl Default for ManifoldSnapshot {
60 fn default() -> Self {
61 Self {
62 snapshot_id: SnapshotId(String::new()),
63 conformance: ConformanceVector::default(),
64 hooks: Vec::new(),
65 chains: Vec::new(),
66 receipts: Vec::new(),
67 }
68 }
69}
70
71#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)]
73pub enum AdmissionDecision {
74 Admitted,
75 Refused,
76 #[default]
77 Unknown,
78}
79
80impl From<bool> for AdmissionDecision {
81 fn from(b: bool) -> Self {
82 if b {
83 AdmissionDecision::Admitted
84 } else {
85 AdmissionDecision::Refused
86 }
87 }
88}
89
90impl From<AdmissionDecision> for bool {
91 fn from(d: AdmissionDecision) -> bool {
92 matches!(d, AdmissionDecision::Admitted)
93 }
94}
95
96impl std::fmt::Display for AdmissionDecision {
97 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98 write!(f, "{:?}", self)
99 }
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize, Default)]
103pub struct AdmissionResult {
104 pub decision: AdmissionDecision,
105 pub law_axis: LawAxis,
106 pub rationale: String,
107 pub receipt: Option<Receipt>,
108}
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct RefusalResult {
112 pub law_axis: LawAxis,
113 pub rationale: String,
114 pub receipt: Receipt,
115 pub repair_actions: Vec<RepairAction>,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize, Default)]
119pub struct LawfulTransitionResult {
120 pub from_phase: String,
121 pub to_phase: String,
122 pub lawful: bool,
123 pub violated_laws: Vec<LawAxis>,
124 pub receipt: Option<Receipt>,
125}
126
127#[derive(Debug, Clone, Serialize, Deserialize, Default)]
128pub struct ReplayResult {
129 pub replay_id: String,
130 pub events_replayed: u64,
131 pub conformance: ConformanceVector,
132 pub receipts: Vec<Receipt>,
133}
134
135#[derive(Debug, Clone, Serialize, Deserialize, Default)]
136pub struct ReleaseActuationResult {
137 pub released: bool,
138 pub conformance: ConformanceVector,
139 pub blocking_axes: Vec<LawAxis>,
140 pub receipt: Option<Receipt>,
141}
142
143#[derive(Debug, Clone, Serialize, Deserialize)]
144pub enum HookEvent {
145 StateTransition {
146 instance_id: InstanceId,
147 from_phase: String,
148 to_phase: String,
149 },
150 DiagnosticEmitted {
151 instance_id: InstanceId,
152 diagnostic: Box<MaxDiagnostic>,
153 },
154 DiagnosticCleared {
155 instance_id: InstanceId,
156 diagnostic_id: String,
157 },
158 ReceiptEmitted {
159 instance_id: InstanceId,
160 receipt: Receipt,
161 },
162 PolicyStateChanged {
163 instance_id: InstanceId,
164 from_state: PolicyState,
165 to_state: PolicyState,
166 },
167 BoundedActionExecuted {
168 instance_id: InstanceId,
169 action_id: String,
170 description: String,
171 },
172 InstanceReset {
173 instance_id: InstanceId,
174 },
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn admission_decision_from_bool() {
183 assert_eq!(AdmissionDecision::from(true), AdmissionDecision::Admitted);
184 assert_eq!(AdmissionDecision::from(false), AdmissionDecision::Refused);
185 }
186
187 #[test]
188 fn admission_decision_into_bool() {
189 assert!(bool::from(AdmissionDecision::Admitted));
190 assert!(!bool::from(AdmissionDecision::Refused));
191 assert!(!bool::from(AdmissionDecision::Unknown));
192 }
193}