1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize)]
5pub enum AuditAction {
6 InstanceCreated,
7 InstanceStarted,
8 InstanceStopped,
9 InstanceWarmed,
10 InstanceSlept,
11 InstanceWoken,
12 InstanceDestroyed,
13 PoolCreated,
14 PoolBuilt,
15 PoolDestroyed,
16 TenantCreated,
17 TenantDestroyed,
18 QuotaExceeded,
19 SecretsRotated,
20 SnapshotCreated,
21 SnapshotRestored,
22 SnapshotDeleted,
23 TransitionDeferred,
24 MinRuntimeOverridden,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct AuditEntry {
30 pub timestamp: String,
31 pub tenant_id: String,
32 pub pool_id: Option<String>,
33 pub instance_id: Option<String>,
34 pub action: AuditAction,
35 pub detail: Option<String>,
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn test_audit_entry_serialization() {
44 let entry = AuditEntry {
45 timestamp: "2025-01-01T00:00:00Z".to_string(),
46 tenant_id: "acme".to_string(),
47 pool_id: Some("workers".to_string()),
48 instance_id: Some("i-abc123".to_string()),
49 action: AuditAction::InstanceStarted,
50 detail: Some("pid=12345".to_string()),
51 };
52
53 let json = serde_json::to_string(&entry).unwrap();
54 assert!(json.contains("\"tenant_id\":\"acme\""));
55 assert!(json.contains("\"InstanceStarted\""));
56 }
57
58 #[test]
59 fn test_audit_entry_no_optionals() {
60 let entry = AuditEntry {
61 timestamp: "2025-01-01T00:00:00Z".to_string(),
62 tenant_id: "acme".to_string(),
63 pool_id: None,
64 instance_id: None,
65 action: AuditAction::TenantCreated,
66 detail: None,
67 };
68
69 let json = serde_json::to_string(&entry).unwrap();
70 assert!(json.contains("\"pool_id\":null"));
71 }
72
73 #[test]
74 fn test_all_audit_actions_serialize() {
75 let actions = vec![
76 AuditAction::InstanceCreated,
77 AuditAction::InstanceStarted,
78 AuditAction::InstanceStopped,
79 AuditAction::InstanceWarmed,
80 AuditAction::InstanceSlept,
81 AuditAction::InstanceWoken,
82 AuditAction::InstanceDestroyed,
83 AuditAction::PoolCreated,
84 AuditAction::PoolBuilt,
85 AuditAction::PoolDestroyed,
86 AuditAction::TenantCreated,
87 AuditAction::TenantDestroyed,
88 AuditAction::QuotaExceeded,
89 AuditAction::SecretsRotated,
90 AuditAction::SnapshotCreated,
91 AuditAction::SnapshotRestored,
92 AuditAction::SnapshotDeleted,
93 AuditAction::TransitionDeferred,
94 AuditAction::MinRuntimeOverridden,
95 ];
96
97 for action in actions {
98 let json = serde_json::to_string(&action).unwrap();
99 assert!(!json.is_empty());
100 }
101 }
102}