fix(studio): prevent auth monitor reload loop - #7118
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces changes to prevent the global settings dialog from mounting or being opened via shortcuts during authentication flows (login, change password, onboarding). It also ensures that the persisted system monitor stays dormant on the login page and resumes polling only after successful authentication. Corresponding Playwright and unit tests have been added to verify these behaviors. The reviewer feedback suggests explicitly specifying encoding='utf-8' when reading and writing files in Python to avoid platform-dependent encoding issues.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
Pull request overview
This PR fixes an infinite reload loop on Studio authentication routes caused by the persisted System monitor polling protected /api/system while /login (or /change-password) is active, repeatedly triggering 401 redirects. It introduces explicit “auth-flow route” metadata to prevent mounting global settings/monitor UI on those routes, and makes auth redirects idempotent when already at the target route.
Changes:
- Add
staticData.isAuthFlowroute metadata and use it in the root layout to avoid mountingSettingsDialogand to disable/close settings-dialog behavior during auth flows. - Update
redirectToAuth()to avoid reassigningwindow.location.hrefwhen already on the resolved auth target, releasing the redirect latch when navigation is skipped. - Add/extend tests to pin the auth-flow boundary behavior and to verify monitor polling is dormant on
/loginand resumes after authentication.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
studio/frontend/src/app/routes/__root.tsx |
Introduces isAuthFlow route static data and uses it to gate Settings dialog mounting and shortcuts during auth flows. |
studio/frontend/src/features/auth/api.ts |
Makes redirectToAuth() idempotent when already on /login or /change-password, preventing reload loops. |
studio/frontend/src/app/routes/login.tsx |
Marks /login as an auth-flow route via staticData.isAuthFlow. |
studio/frontend/src/app/routes/change-password.tsx |
Marks /change-password as an auth-flow route via staticData.isAuthFlow. |
studio/frontend/src/app/routes/onboarding.tsx |
Marks /onboarding as an auth-flow route via staticData.isAuthFlow. |
tests/studio/test_auth_form_input_count.py |
Adds focused source/runtime contracts for auth-flow boundaries and redirect idempotence/concurrency. |
tests/studio/playwright_chat_ui.py |
Extends the existing smoke flow to assert /api/system polling is dormant on /login and resumes after login, and that settings-dialog state doesn’t leak across auth. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@codex review |
1 similar comment
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Fixes #7114
Summary
/login,/change-password, and onboarding as authentication-flow routes and do not mount the global settings UI or persisted System monitor on those routes.redirectToAuth()skip assigningwindow.location.hrefwhen the browser is already at the resolved/loginor/change-passwordtarget, and release the redirect latch when navigation is skipped./loginand resumes after authentication.Root cause
SettingsDialogwas mounted globally and always mountedFloatingMonitor. When the persisted monitor state was open, authentication routes immediately polled protected/api/system. A401calledredirectToAuth(), which assigned/logineven when already on/login; the reload restored the open monitor and repeated the same request and redirect indefinitely.Fast reproduction
On an unfixed web build, open DevTools, enable Preserve log in the Network panel, and run:
Before this patch,
/loginrepeatedly reloads after/api/systemreturns401. With this patch,/loginremains stable and does not request/api/system; after a successful login, the persisted monitor resumes polling normally.Validation
python -m pytest tests/studio/test_auth_form_input_count.py -q npx --yes --package=node@22 -- python -m pytest tests/studio/test_auth_form_input_count.py -q python -m ruff check tests/studio/test_auth_form_input_count.py tests/studio/playwright_chat_ui.py python -m py_compile tests/studio/test_auth_form_input_count.py tests/studio/playwright_chat_ui.py cd studio/frontend npm run typecheck npm run build/login, settings-shortcut cleanup, and polling resumption after login.Risk
The boundary is explicit route metadata, so any future guest authentication-flow route must opt in with
isAuthFlow: true. Token refresh and Tauri automatic authentication paths are unchanged.