use regex::Regex;
use std::sync::OnceLock;
fn patterns() -> &'static [Regex] {
static P: OnceLock<Vec<Regex>> = OnceLock::new();
P.get_or_init(|| {
vec![
Regex::new(r"AKIA[0-9A-Z]{16}").unwrap(), Regex::new(r"ghp_[A-Za-z0-9]{36}").unwrap(), Regex::new(r"eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}").unwrap(), Regex::new(r"-----BEGIN [A-Z ]*PRIVATE KEY-----").unwrap(), ]
})
}
pub fn redact(text: &str) -> String {
let mut out = text.to_string();
for re in patterns() {
out = re.replace_all(&out, "[REDACTED]").into_owned();
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn redacts_aws_and_jwt() {
let s = "key=AKIAIOSFODNN7EXAMPLE tok=eyJhbGciOi.JzdWIiOiI.SflKxwRJ";
let r = redact(s);
assert!(!r.contains("AKIAIOSFODNN7EXAMPLE"));
assert!(r.contains("[REDACTED]"));
}
}