use serde_json::Value; use sqlx::{Postgres, Transaction}; /// Return the current OS user as the audit actor (falls back to empty string). pub fn current_actor() -> String { std::env::var("USER").unwrap_or_default() } /// Write an audit entry within an existing transaction. pub async fn log_tx( tx: &mut Transaction<'_, Postgres>, action: &str, namespace: &str, kind: &str, name: &str, detail: Value, ) { let actor = current_actor(); let result: Result<_, sqlx::Error> = sqlx::query( "INSERT INTO audit_log (action, namespace, kind, name, detail, actor) \ VALUES ($1, $2, $3, $4, $5, $6)", ) .bind(action) .bind(namespace) .bind(kind) .bind(name) .bind(&detail) .bind(&actor) .execute(&mut **tx) .await; if let Err(e) = result { tracing::warn!(error = %e, "failed to write audit log"); } else { tracing::debug!(action, namespace, kind, name, actor, "audit logged"); } }