use debugbundle::privacy::Privacy;
use serde_json::{json, Value};
#[test]
fn shared_privacy_corpus_is_preserved_exactly() {
let corpus: Value =
serde_json::from_str(include_str!("fixtures/privacy-conformance.json")).unwrap();
let privacy = Privacy::new(&[]).unwrap();
for case in corpus["cases"].as_array().unwrap() {
assert_eq!(
privacy.protect(&case["input"]),
Some(case["expected"].clone()),
"{}",
case["id"]
);
}
}
#[test]
fn custom_fields_extend_mandatory_rules_and_keys_are_segment_aware() {
let privacy = Privacy::new(&["tenant_pin".into()]).unwrap();
assert_eq!(
privacy.protect(
&json!({"password":"x", "tenant_pin":"y", "tokenizer":"safe", "myAccessToken":42})
),
Some(
json!({"password":"[REDACTED]", "tenant_pin":"[REDACTED]", "tokenizer":"safe", "myAccessToken":"[REDACTED]"})
)
);
}
#[test]
fn malformed_encoded_credentials_stay_private_when_a_later_pass_withholds_more_context() {
let privacy = Privacy::new(&[]).unwrap();
let input = json!({"body":"{signal\"password\":\"SYNTHETIC_SECRET\",\"route\":\"/checkout\"}"});
let first = privacy.protect(&input).unwrap();
assert_eq!(
first,
json!({"body":"{signal\"password\":[REDACTED],\"route\":\"/checkout\"}"})
);
assert!(!serde_json::to_string(&first)
.unwrap()
.contains("SYNTHETIC_SECRET"));
assert_eq!(privacy.protect(&first), Some(json!({"body":"[REDACTED]"})));
}
#[test]
fn budgets_withhold_oversized_names_and_values() {
let privacy = Privacy::new(&[]).unwrap();
assert_eq!(
privacy.protect(&json!({"message":"x".repeat(17000)})),
Some(json!({"message":"[REDACTED]"}))
);
assert_eq!(
privacy.protect(&json!({"k".repeat(129):"sensitive"})),
Some(json!({}))
);
assert!(Privacy::new(&["".into()]).is_none());
}
#[test]
fn public_key_matcher_rejects_oversized_names_before_segment_work() {
let privacy = Privacy::new(&[]).unwrap();
assert!(!privacy.sensitive_key(&"x".repeat(128)));
assert!(privacy.sensitive_key(&"x".repeat(129)));
assert!(privacy.sensitive_key(&"x_".repeat(100_000)));
}
#[test]
fn unified_arbitrary_precision_numbers_cannot_escape_native_value_budgets() {
let privacy = Privacy::new(&[]).unwrap();
let number: Value = serde_json::from_str(&format!("1{}", "0".repeat(100_000))).unwrap();
assert!(privacy.protect(&number).is_none());
assert!(debugbundle::wire::canonical_size(&number).is_none());
assert_eq!(privacy.protect(&json!(12345)), Some(json!(12345)));
}