1use std::borrow::Cow;
2
3#[derive(Debug, Clone, Copy, Default)]
4pub struct RedactionPolicy {
5 pub redact_prompts: bool,
6}
7
8impl RedactionPolicy {
9 pub fn new(redact_prompts: bool) -> Self {
10 Self { redact_prompts }
11 }
12
13 pub fn redact_prompt<'a>(&self, s: &'a str) -> Cow<'a, str> {
14 if self.redact_prompts {
15 "[REDACTED]".into()
16 } else {
17 s.into()
18 }
19 }
20
21 pub fn redact_judge_metadata(&self, meta: &mut serde_json::Value) {
22 if !self.redact_prompts {
23 return;
24 }
25
26 if let Some(obj) = meta
27 .pointer_mut("/assay/judge")
28 .and_then(|v| v.as_object_mut())
29 {
30 for (_, v) in obj.iter_mut() {
31 if let Some(inner) = v.as_object_mut() {
32 if inner.contains_key("rationale") {
33 inner.insert("rationale".to_string(), serde_json::json!("[REDACTED]"));
34 }
35 }
36 }
37 }
38
39 if let Some(metrics) = meta.pointer_mut("/metrics").and_then(|v| v.as_object_mut()) {
41 for (_, metric_res) in metrics.iter_mut() {
42 if let Some(details) = metric_res
43 .get_mut("details")
44 .and_then(|v| v.as_object_mut())
45 {
46 if details.contains_key("rationale") {
47 details.insert("rationale".to_string(), serde_json::json!("[REDACTED]"));
48 }
49 }
50 }
51 }
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn test_redaction_on() {
61 let policy = RedactionPolicy::new(true);
62 assert_eq!(policy.redact_prompt("my secret prompt"), "[REDACTED]");
63 }
64
65 #[test]
66 fn test_redaction_off() {
67 let policy = RedactionPolicy::new(false);
68 assert_eq!(policy.redact_prompt("safe prompt"), "safe prompt");
69 }
70}