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