//! In-memory log capture, used by the audit tests to assert that //! `tracing` output contains no secret material (SS-AUD-003). //! //! Production code will use the redaction policy defined in //! `docs/security/diagnostic-redaction-audit-report.md` and the //! `chanora_diagnostics` crate. This PoC is intentionally simpler: //! it captures *all* log output verbatim and lets the test grep it. use std::io::{self, Write}; use std::sync::{Arc, Mutex}; #[derive(Clone, Default)] pub struct CapturedLog { buf: Arc>>, } impl CapturedLog { pub fn new() -> Self { Self::default() } /// Snapshot the captured bytes as a UTF-8 string (lossy if there's /// any non-UTF-8 — we never expect non-UTF-8 from `tracing`). pub fn snapshot(&self) -> String { let buf = self.buf.lock().unwrap(); String::from_utf8_lossy(&buf).into_owned() } pub fn writer(&self) -> CapturedLogWriter { CapturedLogWriter { buf: self.buf.clone() } } } pub struct CapturedLogWriter { buf: Arc>>, } impl Write for CapturedLogWriter { fn write(&mut self, buf: &[u8]) -> io::Result { let mut g = self.buf.lock().unwrap(); g.extend_from_slice(buf); Ok(buf.len()) } fn flush(&mut self) -> io::Result<()> { Ok(()) } } impl<'a> tracing_subscriber::fmt::MakeWriter<'a> for CapturedLog { type Writer = CapturedLogWriter; fn make_writer(&'a self) -> Self::Writer { self.writer() } }