diff --git a/crates/miroir-proxy/src/main.rs b/crates/miroir-proxy/src/main.rs index 39a5c93..8b4b0f8 100644 --- a/crates/miroir-proxy/src/main.rs +++ b/crates/miroir-proxy/src/main.rs @@ -163,6 +163,7 @@ async fn main() -> anyhow::Result<()> { if let Some(otel_layer) = otel::init_otel_layer(&config) { let json_layer = tracing_subscriber::fmt::layer() .json() + .flatten_event(true) .with_target(true) .with_current_span(true) .with_span_list(false); @@ -175,6 +176,7 @@ async fn main() -> anyhow::Result<()> { } else { let json_layer = tracing_subscriber::fmt::layer() .json() + .flatten_event(true) .with_target(true) .with_current_span(true) .with_span_list(false); diff --git a/crates/miroir-proxy/src/routes/search.rs b/crates/miroir-proxy/src/routes/search.rs index 3de3d53..4071f0e 100644 --- a/crates/miroir-proxy/src/routes/search.rs +++ b/crates/miroir-proxy/src/routes/search.rs @@ -262,3 +262,35 @@ pub fn strip_internal_fields(hit: &mut Value, client_requested_score: bool) { } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_search_request_debug_redaction() { + let body = SearchRequestBody { + q: Some("sensitive user query about private data".to_string()), + offset: Some(0), + limit: Some(20), + filter: Some(serde_json::json!({"email": "user@example.com"})), + facets: Some(vec!["category".to_string()]), + ranking_score: Some(false), + rest: serde_json::json!({}), + }; + let debug_output = format!("{:?}", body); + + assert!( + !debug_output.contains("sensitive"), + "Debug output should not contain raw query text" + ); + assert!( + !debug_output.contains("user@example.com"), + "Debug output should not contain filter values" + ); + assert!( + debug_output.contains("[redacted]"), + "Debug output should show [redacted] for sensitive fields" + ); + } +} diff --git a/crates/miroir-proxy/tests/p7_5_structured_logging.rs b/crates/miroir-proxy/tests/p7_5_structured_logging.rs index 4c2d5a0..a2f27a3 100644 --- a/crates/miroir-proxy/tests/p7_5_structured_logging.rs +++ b/crates/miroir-proxy/tests/p7_5_structured_logging.rs @@ -291,15 +291,9 @@ fn test_log_levels_correct() { #[test] fn test_search_request_debug_redaction() { - // This test verifies that the Debug impl for SearchRequestBody - // redacts the query string to prevent PII leaks in logs - // - // The actual struct is in routes/search.rs and has: - // field("q", &"[redacted]") - // field("filter", &"[redacted]") - // - // We verify the behavior through the integration test that - // actually makes search requests and checks logs. + // Verified by unit test in routes/search.rs (SearchRequestBody is private). + // That test confirms the Debug impl redacts `q` and `filter` fields. + // This placeholder keeps the integration test file's acceptance criteria visible. } // ---------------------------------------------------------------------------