From 3f59ab3746329c6a754194d6d3fa1e23878e7db2 Mon Sep 17 00:00:00 2001 From: Jason Date: Sat, 30 May 2026 21:04:23 +0800 Subject: [PATCH] Default Codex auth preservation to off (opt-in) Flip preserve_codex_official_auth_on_switch from true to false so third-party Codex switches overwrite auth.json by default, matching the expectation that switching providers also swaps credentials. Users who rely on keeping the ChatGPT login in auth.json while on a third-party provider (for official plugins / remote login) can enable it in Settings -> Codex Authentication. The toggle field ships for the first time here (it is not in v3.16.0), so no existing settings.json holds an explicit value -- every user lands on the new default and no migration is required. Also set the flag explicitly in the preservation unit test instead of relying on the global default, keeping it valid now that the default is false. --- src-tauri/src/services/proxy.rs | 8 ++++++++ src-tauri/src/settings.rs | 7 ++++--- src/components/settings/CodexAuthSettings.tsx | 2 +- src/hooks/useSettingsForm.ts | 6 +++--- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src-tauri/src/services/proxy.rs b/src-tauri/src/services/proxy.rs index cefa5b107..682e8edb5 100644 --- a/src-tauri/src/services/proxy.rs +++ b/src-tauri/src/services/proxy.rs @@ -2560,6 +2560,11 @@ mod tests { fn codex_custom_provider_live_write_preserves_oauth_auth_json() { let _home = TempHome::new(); crate::settings::reload_settings().expect("reload settings"); + crate::settings::update_settings(crate::settings::AppSettings { + preserve_codex_official_auth_on_switch: true, + ..Default::default() + }) + .expect("enable Codex official auth preservation"); let db = Arc::new(Database::memory().expect("init db")); let service = ProxyService::new(db); @@ -2635,6 +2640,9 @@ wire_api = "responses" live_config.contains(PROXY_TOKEN_PLACEHOLDER), "live config should carry the proxy placeholder token" ); + + crate::settings::update_settings(crate::settings::AppSettings::default()) + .expect("reset settings"); } #[test] diff --git a/src-tauri/src/settings.rs b/src-tauri/src/settings.rs index 4f2a90945..02276ce60 100644 --- a/src-tauri/src/settings.rs +++ b/src-tauri/src/settings.rs @@ -253,8 +253,9 @@ pub struct AppSettings { /// Whether to show the failover toggle independently on the main page #[serde(default)] pub enable_failover_toggle: bool, - /// Keep Codex ChatGPT login material in auth.json when switching to third-party providers - #[serde(default = "default_true")] + /// Keep Codex ChatGPT login material in auth.json when switching to third-party providers. + /// Opt-in: defaults to false so third-party switches cleanly overwrite auth.json. + #[serde(default)] pub preserve_codex_official_auth_on_switch: bool, /// User has confirmed the failover toggle first-run notice #[serde(default, skip_serializing_if = "Option::is_none")] @@ -369,7 +370,7 @@ impl Default for AppSettings { usage_confirmed: None, stream_check_confirmed: None, enable_failover_toggle: false, - preserve_codex_official_auth_on_switch: true, + preserve_codex_official_auth_on_switch: false, failover_confirmed: None, first_run_notice_confirmed: None, common_config_confirmed: None, diff --git a/src/components/settings/CodexAuthSettings.tsx b/src/components/settings/CodexAuthSettings.tsx index 047fd7318..0472acfdc 100644 --- a/src/components/settings/CodexAuthSettings.tsx +++ b/src/components/settings/CodexAuthSettings.tsx @@ -25,7 +25,7 @@ export function CodexAuthSettings({ icon={} title={t("settings.preserveCodexOfficialAuthOnSwitch")} description={t("settings.preserveCodexOfficialAuthOnSwitchDescription")} - checked={settings.preserveCodexOfficialAuthOnSwitch ?? true} + checked={settings.preserveCodexOfficialAuthOnSwitch ?? false} onCheckedChange={(value) => onChange({ preserveCodexOfficialAuthOnSwitch: value }) } diff --git a/src/hooks/useSettingsForm.ts b/src/hooks/useSettingsForm.ts index 3a73fd9f2..245b7a66d 100644 --- a/src/hooks/useSettingsForm.ts +++ b/src/hooks/useSettingsForm.ts @@ -117,7 +117,7 @@ export function useSettingsForm(): UseSettingsFormResult { silentStartup: data.silentStartup ?? false, skipClaudeOnboarding: data.skipClaudeOnboarding ?? false, preserveCodexOfficialAuthOnSwitch: - data.preserveCodexOfficialAuthOnSwitch ?? true, + data.preserveCodexOfficialAuthOnSwitch ?? false, claudeConfigDir: sanitizeDir(data.claudeConfigDir), codexConfigDir: sanitizeDir(data.codexConfigDir), geminiConfigDir: sanitizeDir(data.geminiConfigDir), @@ -142,7 +142,7 @@ export function useSettingsForm(): UseSettingsFormResult { useAppWindowControls: false, enableClaudePluginIntegration: false, skipClaudeOnboarding: false, - preserveCodexOfficialAuthOnSwitch: true, + preserveCodexOfficialAuthOnSwitch: false, language: readPersistedLanguage(), } as SettingsFormState); @@ -181,7 +181,7 @@ export function useSettingsForm(): UseSettingsFormResult { silentStartup: serverData.silentStartup ?? false, skipClaudeOnboarding: serverData.skipClaudeOnboarding ?? false, preserveCodexOfficialAuthOnSwitch: - serverData.preserveCodexOfficialAuthOnSwitch ?? true, + serverData.preserveCodexOfficialAuthOnSwitch ?? false, claudeConfigDir: sanitizeDir(serverData.claudeConfigDir), codexConfigDir: sanitizeDir(serverData.codexConfigDir), geminiConfigDir: sanitizeDir(serverData.geminiConfigDir),