From 034342eee736788741a5f09b2f9be55228e9b774 Mon Sep 17 00:00:00 2001 From: Xmon Dai Date: Thu, 24 Sep 2026 06:36:37 +0800 Subject: [PATCH] fix(config): default sensitive diagnostics to off, matching the UI copy --- .../adapters/ai-adapters/src/diagnostics.rs | 4 +++- .../contracts/config-contracts/src/types.rs | 11 +++++---- .../services/FrontendLogLevelSync.test.ts | 23 +++++++++++++++++++ .../config/services/FrontendLogLevelSync.ts | 6 ++--- src/web-ui/src/shared/utils/logger.ts | 4 +++- 5 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/crates/adapters/ai-adapters/src/diagnostics.rs b/src/crates/adapters/ai-adapters/src/diagnostics.rs index aa2ff27f74..01e7faa9f1 100644 --- a/src/crates/adapters/ai-adapters/src/diagnostics.rs +++ b/src/crates/adapters/ai-adapters/src/diagnostics.rs @@ -1,6 +1,8 @@ use std::sync::atomic::{AtomicBool, Ordering}; -static INCLUDE_SENSITIVE_DIAGNOSTICS: AtomicBool = AtomicBool::new(true); +// Fail closed until the config layer applies the saved preference (#3213): +// sensitive diagnostics are opt-in everywhere else (config default, UI copy). +static INCLUDE_SENSITIVE_DIAGNOSTICS: AtomicBool = AtomicBool::new(false); pub fn set_include_sensitive_diagnostics(enabled: bool) { INCLUDE_SENSITIVE_DIAGNOSTICS.store(enabled, Ordering::Relaxed); diff --git a/src/crates/contracts/config-contracts/src/types.rs b/src/crates/contracts/config-contracts/src/types.rs index bc1bd8b3d4..c13999cf42 100644 --- a/src/crates/contracts/config-contracts/src/types.rs +++ b/src/crates/contracts/config-contracts/src/types.rs @@ -380,7 +380,9 @@ pub struct AppLoggingConfig { /// Allowed values: trace, debug, info, warn, error, off. pub level: String, /// Whether diagnostic logs may include sensitive troubleshooting payloads. - #[serde(default = "default_true")] + /// Off by default, matching the settings UI copy ("Off by default") and the + /// privacy guidance in the capability docs (#3213). + #[serde(default)] pub include_sensitive_diagnostics: bool, /// Whether the local UI records detailed Flow Chat viewport diagnostics. #[serde(default)] @@ -1908,7 +1910,8 @@ impl Default for AppLoggingConfig { Self { // Set to Debug in early development for easier diagnostics level: "debug".to_string(), - include_sensitive_diagnostics: true, + // Off by default: sensitive payloads are opt-in (#3213) + include_sensitive_diagnostics: false, flow_chat_diagnostics: false, model_exchange_tracing: ModelExchangeTracingConfig::default(), } @@ -3469,13 +3472,13 @@ mod tests { } #[test] - fn app_logging_defaults_to_sensitive_diagnostics_enabled() { + fn app_logging_defaults_to_sensitive_diagnostics_disabled() { let config: AppLoggingConfig = serde_json::from_value(serde_json::json!({ "level": "trace" })) .expect("logging config without sensitive preference should deserialize"); - assert!(config.include_sensitive_diagnostics); + assert!(!config.include_sensitive_diagnostics); assert!(!config.flow_chat_diagnostics); assert_eq!( config.model_exchange_tracing.mode, diff --git a/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.test.ts b/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.test.ts index dde14d5fd4..0d5d8e245e 100644 --- a/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.test.ts +++ b/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.test.ts @@ -99,4 +99,27 @@ describe('FrontendLogLevelSync startup reads', () => { expect(loggerMocks.setIncludeSensitiveDiagnostics).toHaveBeenCalledWith(true); expect(loggerMocks.setFlowChatDiagnosticsEnabled).toHaveBeenCalledWith(false); }); + + it('defaults sensitive diagnostics to off when no saved preference exists (#3213)', async () => { + configApiMocks.getConfigs.mockResolvedValueOnce({ + [LOGGING_LEVEL_PATH]: 'warn', + }); + configApiMocks.getRuntimeLoggingInfo.mockResolvedValueOnce({ effectiveLevel: 'warn' }); + + const { initializeFrontendLogLevelSync } = await importSyncModule(); + await initializeFrontendLogLevelSync(); + + expect(loggerMocks.setIncludeSensitiveDiagnostics).toHaveBeenCalledWith(false); + }); + + it('falls back to runtime info with sensitive diagnostics off when no saved preference exists (#3213)', async () => { + configApiMocks.getConfigs.mockResolvedValueOnce({}); + configApiMocks.getRuntimeLoggingInfo.mockResolvedValueOnce({ effectiveLevel: 'error' }); + + const { initializeFrontendLogLevelSync } = await importSyncModule(); + await initializeFrontendLogLevelSync(); + + expect(loggerMocks.setLevel).toHaveBeenCalledWith(4); + expect(loggerMocks.setIncludeSensitiveDiagnostics).toHaveBeenCalledWith(false); + }); }); diff --git a/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.ts b/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.ts index 299142a24a..a68e149f52 100644 --- a/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.ts +++ b/src/web-ui/src/infrastructure/config/services/FrontendLogLevelSync.ts @@ -102,7 +102,7 @@ async function resolveInitialLoggingSettings(): Promise includeSensitiveDiagnostics: typeof configs[LOGGING_INCLUDE_SENSITIVE_PATH] === 'boolean' ? configs[LOGGING_INCLUDE_SENSITIVE_PATH] - : true, + : false, flowChatDiagnostics: configs[FLOW_CHAT_DIAGNOSTICS_PATH] === true, }; } @@ -115,7 +115,7 @@ async function resolveInitialLoggingSettings(): Promise includeSensitiveDiagnostics: typeof configs[LOGGING_INCLUDE_SENSITIVE_PATH] === 'boolean' ? configs[LOGGING_INCLUDE_SENSITIVE_PATH] - : true, + : false, flowChatDiagnostics: configs[FLOW_CHAT_DIAGNOSTICS_PATH] === true, }; } @@ -125,7 +125,7 @@ async function resolveInitialLoggingSettings(): Promise includeSensitiveDiagnostics: typeof configs[LOGGING_INCLUDE_SENSITIVE_PATH] === 'boolean' ? configs[LOGGING_INCLUDE_SENSITIVE_PATH] - : true, + : false, flowChatDiagnostics: configs[FLOW_CHAT_DIAGNOSTICS_PATH] === true, }; } diff --git a/src/web-ui/src/shared/utils/logger.ts b/src/web-ui/src/shared/utils/logger.ts index e7ef8a16bf..0dfa39dd96 100644 --- a/src/web-ui/src/shared/utils/logger.ts +++ b/src/web-ui/src/shared/utils/logger.ts @@ -34,7 +34,9 @@ const isTauri = typeof window !== 'undefined' && '__TAURI__' in window; const isDev = import.meta.env?.DEV ?? process.env.NODE_ENV === 'development'; const CONSOLE_FORWARD_INSTALLED = '__openbitfun_console_forward_installed__'; -let includeSensitiveDiagnostics = true; +// Off until the saved preference is loaded (#3213): the settings UI and the +// backend config both default sensitive diagnostics to disabled. +let includeSensitiveDiagnostics = false; declare global { // Injected by the desktop WebView initialization script before the frontend bundle runs.