Skip to main content

relay_core_runtime/
audit.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::str::FromStr;
4use std::time::{SystemTime, UNIX_EPOCH};
5use uuid::Uuid;
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
8#[serde(rename_all = "snake_case")]
9pub enum AuditActor {
10    Runtime,
11    Tauri,
12    Http,
13    Probe,
14    Cli,
15}
16
17impl AuditActor {
18    pub fn as_str(&self) -> &'static str {
19        match self {
20            Self::Runtime => "runtime",
21            Self::Tauri => "tauri",
22            Self::Http => "http",
23            Self::Probe => "probe",
24            Self::Cli => "cli",
25        }
26    }
27
28}
29
30impl FromStr for AuditActor {
31    type Err = ();
32
33    fn from_str(value: &str) -> Result<Self, Self::Err> {
34        match value {
35            "runtime" => Ok(Self::Runtime),
36            "tauri" => Ok(Self::Tauri),
37            "http" => Ok(Self::Http),
38            "probe" => Ok(Self::Probe),
39            "cli" => Ok(Self::Cli),
40            _ => Err(()),
41        }
42    }
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
46#[serde(rename_all = "snake_case")]
47pub enum AuditEventKind {
48    RuleChanged,
49    InterceptResolved,
50    ScriptReloaded,
51    PolicyUpdated,
52}
53
54impl AuditEventKind {
55    pub fn as_str(&self) -> &'static str {
56        match self {
57            Self::RuleChanged => "rule_changed",
58            Self::InterceptResolved => "intercept_resolved",
59            Self::ScriptReloaded => "script_reloaded",
60            Self::PolicyUpdated => "policy_updated",
61        }
62    }
63
64}
65
66impl FromStr for AuditEventKind {
67    type Err = ();
68
69    fn from_str(value: &str) -> Result<Self, Self::Err> {
70        match value {
71            "rule_changed" => Ok(Self::RuleChanged),
72            "intercept_resolved" => Ok(Self::InterceptResolved),
73            "script_reloaded" => Ok(Self::ScriptReloaded),
74            "policy_updated" => Ok(Self::PolicyUpdated),
75            _ => Err(()),
76        }
77    }
78}
79
80#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
81#[serde(rename_all = "snake_case")]
82pub enum AuditOutcome {
83    Success,
84    Failed,
85}
86
87impl AuditOutcome {
88    pub fn as_str(&self) -> &'static str {
89        match self {
90            Self::Success => "success",
91            Self::Failed => "failed",
92        }
93    }
94
95}
96
97impl FromStr for AuditOutcome {
98    type Err = ();
99
100    fn from_str(value: &str) -> Result<Self, Self::Err> {
101        match value {
102            "success" => Ok(Self::Success),
103            "failed" => Ok(Self::Failed),
104            _ => Err(()),
105        }
106    }
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
110pub struct AuditEvent {
111    pub id: String,
112    pub timestamp_ms: u64,
113    pub actor: AuditActor,
114    pub kind: AuditEventKind,
115    pub target: String,
116    pub outcome: AuditOutcome,
117    pub details: Value,
118}
119
120impl AuditEvent {
121    pub fn new(
122        actor: AuditActor,
123        kind: AuditEventKind,
124        target: impl Into<String>,
125        outcome: AuditOutcome,
126        details: Value,
127    ) -> Self {
128        let timestamp_ms = SystemTime::now()
129            .duration_since(UNIX_EPOCH)
130            .unwrap_or_default()
131            .as_millis() as u64;
132
133        Self {
134            id: Uuid::new_v4().to_string(),
135            timestamp_ms,
136            actor,
137            kind,
138            target: target.into(),
139            outcome,
140            details,
141        }
142    }
143}