use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PiiScannerConfig {
#[serde(default = "default_detect")]
pub detect: Vec<PiiPattern>,
#[serde(default)]
pub mode: PiiScanMode,
}
fn default_detect() -> Vec<PiiPattern> {
vec![PiiPattern::Ssn, PiiPattern::CreditCard]
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum PiiPattern {
Ssn,
CreditCard,
Email,
Custom { name: String, regex: String },
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum PiiScanMode {
#[default]
Deny,
Redact,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn defaults() {
let cfg: PiiScannerConfig = serde_json::from_value(json!({})).unwrap();
assert_eq!(cfg.detect.len(), 2);
assert!(matches!(cfg.mode, PiiScanMode::Deny));
}
#[test]
fn parse_full_config() {
let raw = json!({
"detect": [
{ "kind": "ssn" },
{ "kind": "custom", "name": "internal_id", "regex": "^INT-[A-Z0-9]{10}$" }
],
"mode": "redact",
});
let cfg: PiiScannerConfig = serde_json::from_value(raw).unwrap();
assert_eq!(cfg.detect.len(), 2);
assert!(matches!(cfg.mode, PiiScanMode::Redact));
}
}