Skip to main content

oxios_kernel/
audit_persistence.rs

1//! StateStore-backed AuditPersistence for oxi-sdk's AuditTrail.
2//!
3//! Bridges the `oxi_sdk::observability::AuditPersistence` trait to oxios's
4//! filesystem-based `StateStore`. The trail JSON is written to
5//! `<base_path>/audit/trail.json`, matching the legacy layout used before
6//! the SDK migration (RFC-014 Phase F).
7//!
8//! See: <https://github.com/a7garden/oxios/blob/main/docs/rfc-014/phase-f-audit-trail.md>
9
10use anyhow::Result;
11use oxi_sdk::observability::{AuditPersistence, TrailEntry};
12
13use crate::state_store::StateStore;
14
15impl AuditPersistence for StateStore {
16    fn save(&self, entries: &[TrailEntry]) -> Result<()> {
17        let path = self.audit_path();
18        if let Some(parent) = path.parent() {
19            std::fs::create_dir_all(parent)?;
20        }
21        let json = serde_json::to_string_pretty(entries)?;
22        std::fs::write(&path, json)?;
23        Ok(())
24    }
25
26    fn load(&self) -> Result<Vec<TrailEntry>> {
27        let path = self.audit_path();
28        if !path.exists() {
29            return Ok(Vec::new());
30        }
31        let json = std::fs::read_to_string(&path)?;
32        let entries: Vec<TrailEntry> = serde_json::from_str(&json)?;
33        Ok(entries)
34    }
35}
36
37impl StateStore {
38    /// Path to the persisted audit trail file.
39    ///
40    /// Layout: `<base_path>/audit/trail.json`
41    fn audit_path(&self) -> std::path::PathBuf {
42        self.base_path.join("audit").join("trail.json")
43    }
44}