use std::fs::OpenOptions; use std::io::Write; use std::path::PathBuf; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::error::AppResult; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AuditEntry { pub id: Uuid, pub timestamp: DateTime, pub action_type: String, pub affected_paths: Vec, pub list_file_changes: Vec, pub outcome: String, pub preview_id: Option, } #[derive(Clone)] pub struct AuditLog { path: PathBuf, } impl AuditLog { pub fn new(path: PathBuf) -> Self { Self { path } } pub fn append(&self, entry: &AuditEntry) -> AppResult<()> { let mut file = OpenOptions::new() .create(true) .append(true) .open(&self.path)?; let line = serde_json::to_string(entry)?; writeln!(file, "{line}")?; Ok(()) } pub fn append_mutation( &self, action_type: &str, affected_paths: Vec, list_file_changes: Vec, outcome: &str, preview_id: Option, ) -> AppResult { let entry = AuditEntry { id: Uuid::new_v4(), timestamp: Utc::now(), action_type: action_type.to_string(), affected_paths, list_file_changes, outcome: outcome.to_string(), preview_id, }; self.append(&entry)?; Ok(entry) } }