fix(auth): preserve fallback routes and OAuth state (salvage #65264) - #65656
Merged
Conversation
Switch provider and model together after setup-time auth failure. Serialize global auth-store merges under target-specific locks and preserve auth-to-shared lock ordering for profile OAuth refreshes.
Skip provider-only setup fallbacks, keep fallback selection explicit for resumed sessions, preserve configured primary identity for cron drift checks, and make the auth lost-update regression deterministic.
Only fallback resolution needs an explicit target model. Keep the primary resolver call compatible with existing callers and test doubles while retaining atomic provider/model fallback selection.
Remove the dynamic active-store holder so a profile context switch cannot inherit another auth store's lock depth and skip its kernel lock.
This was referenced Jul 16, 2026
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Setup-time auth fallback now switches provider and model as a pair on the TUI/desktop and cron surfaces (matching the CLI), and profile OAuth write-through to the global auth store is serialized under a lock keyed to the target store — so a failed Codex route becomes the configured OpenRouter/GLM route instead of OpenRouter + the original GPT model, and concurrent refreshes can no longer erase other providers' credentials.
Salvages #65264 by @dschnurbusch — all four commits cherry-picked onto current main, authorship preserved. Related: supersedes #47460 (xAI-only subset) and overlaps the TUI half of #43861.
Root cause
tui_gateway/server.pyandcron/scheduler.pyfallback loops carried onlyproviderthrough the chain, keeping the primary model.hermes_cli/cli_agent_setup_mixin.pyalready switched both — TUI/cron were the divergent siblings (gateway was already correct)._write_through_*_to_global_rootinhermes_cli/auth.pyandagent/credential_pool.pyloaded the global auth.json, mutated one provider, and rewrote the whole file holding only the profile's lock — a lost-update window on the global store.threading.local, so a mid-thread profile switch could inherit another store's lock depth and skip its kernel flock.Changes
tui_gateway/server.py,cron/scheduler.py: fallback resolves provider+model atomically; provider-only entries are skipped (CLI semantics); cron drift guard compares pre-fallback snapshots so a legitimate fallback doesn't trip a false drift-skiphermes_cli/auth.py:_persist_provider_state_to_store()centralizes target-store-locked merges;_auth_lock_holder_for()keys reentrancy by canonical resolved path; auth → global → Nous-shared lock order preservedagent/credential_pool.py: write-through routed through the locked helperValidation
581/581 targeted tests (
test_credential_pool_oauth_writethrough,test_scheduler,test_auth_profile_fallback,test_tui_gateway_server); tests fail on main without the fix (verified during review); live E2E of lock keying + concurrent write-through against a temp HERMES_HOME; ruff clean.Note: provider-only fallback entries now fail closed on TUI/cron (consistent with the CLI) — worth a release-note line.
Closes #65264.
Infographic