Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/crates/adapters/ai-adapters/src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
11 changes: 7 additions & 4 deletions src/crates/contracts/config-contracts/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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(),
}
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ async function resolveInitialLoggingSettings(): Promise<InitialLoggingSettings>
includeSensitiveDiagnostics:
typeof configs[LOGGING_INCLUDE_SENSITIVE_PATH] === 'boolean'
? configs[LOGGING_INCLUDE_SENSITIVE_PATH]
: true,
: false,
flowChatDiagnostics: configs[FLOW_CHAT_DIAGNOSTICS_PATH] === true,
};
}
Expand All @@ -115,7 +115,7 @@ async function resolveInitialLoggingSettings(): Promise<InitialLoggingSettings>
includeSensitiveDiagnostics:
typeof configs[LOGGING_INCLUDE_SENSITIVE_PATH] === 'boolean'
? configs[LOGGING_INCLUDE_SENSITIVE_PATH]
: true,
: false,
flowChatDiagnostics: configs[FLOW_CHAT_DIAGNOSTICS_PATH] === true,
};
}
Expand All @@ -125,7 +125,7 @@ async function resolveInitialLoggingSettings(): Promise<InitialLoggingSettings>
includeSensitiveDiagnostics:
typeof configs[LOGGING_INCLUDE_SENSITIVE_PATH] === 'boolean'
? configs[LOGGING_INCLUDE_SENSITIVE_PATH]
: true,
: false,
flowChatDiagnostics: configs[FLOW_CHAT_DIAGNOSTICS_PATH] === true,
};
}
Expand Down
4 changes: 3 additions & 1 deletion src/web-ui/src/shared/utils/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading