fix(web): stop displaying preemptive password modal during connecting - #228
Merged
co-l merged 2 commits intoAug 12, 2026
Conversation
The PasswordModal was rendered in the pre-connection branch of App whenever no token was in localStorage, before /api/auth had resolved. Servers that don't require auth would briefly show "Password Required" with a stale hardcoded message before the WS handshake completed. The condition is unchanged; only the modal itself is removed from the preemptive branch. The modal still renders via the second render path once showPasswordModal is set by the store after /api/auth confirms auth is required, or after a 401/closeCode 4000. Adds two regression tests in web/src/App.test.tsx: - negative: no PasswordModal when reconnecting without token and server does not require auth - positive: PasswordModal renders via showPasswordModal state after /api/auth confirms auth required Fixes #4
theshwal
marked this pull request as draft
August 8, 2026 22:05
theshwal
marked this pull request as ready for review
August 8, 2026 22:05
Contributor
Author
|
ai-disclosure is the only failing check. The PR body already contains the required AI model disclosure. Could you please rerun that failed job? |
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
Fixes theshwal#4
The web UI was rendering
<PasswordModal isOpen={true} />in the pre-connection branch ofAppwhenever no token was inlocalStorage, beforeGET /api/authhad resolved. Servers that do not require authentication would briefly flash a "Password Required" dialog with a stale hardcoded message before the WebSocket handshake completed, even though the server eventually returnedrequiresAuth: false.Root cause
web/src/App.tsx(line 362) had a pre-connection branch that rendered the modal preemptively based solely on the absence of a local token:The state
showPasswordModalis only set by the session store after/api/authreturnsrequiresAuth: true, or after a 401/closeCode 4000. The pre-connection choice was therefore not data-driven, and the dialog's hardcoded title ("Password Required") and body ("This server requires a password to connect.") were misleading as long as the server had not yet confirmed.The server contract was already correct:
GET /api/authreturns{ requiresAuth: requiresAuth() && hasPassword(), hasPassword: hasPassword() }, and the session store handles that response correctly. The only culprit was the preemptive UI render.Minimal fix
Removed only
<PasswordModal>and the surrounding fragment from the pre-connection branch. The condition (notably!showPasswordModal) and the spinner wrapper are preserved verbatim. The modal is now shown exclusively through the second render path, controlled by the store'sshowPasswordModalflag.The fix is intentionally scoped to the false-positive startup case. On servers that legitimately require authentication, the modal still appears as soon as the store flips
showPasswordModaltotrueafter/api/authresolves.Tests
Two regression tests were added in
web/src/App.test.tsxunder a newdescribe('App - Password modal rendering')block:connectionStatus='reconnecting',showPasswordModal=false, and no token, the rendered DOM containsConnecting to server..., does not containPassword Required, and the modal'sdata-testidelement is absent.connectionStatus='reconnecting'andshowPasswordModal=true, the modal is rendered withPassword Required.Both tests pass when the fix is applied. The negative test fails when the modal is reintroduced in the pre-connection branch (verified locally), confirming the test catches the regression.
Test command:
npx vitest run web/src/App.test.tsx→ 3/3 passed.Quality checks
npm run typecheck→ passednpm run lint→ passednpm run format→ passednpm run test:unit→ 3472/3473 passedsrc/server/routes/plugins.test.ts(GET /installed > returns empty list when no plugins directory exists) failed intermittently across runs. This test is environmentally dependent on the user-level plugins directory and is not related to this change. The user has explicitly acknowledged this as a pre-existing flaky test.Out of scope
src/server/auth.tsorsrc/server/index.ts; the server-siderequiresAuth()/hasPassword()logic and the truth table covered bysrc/server/auth.test.tsare already correct.e2e/auth.test.tsremainsdescribe.skipper its existing isolation constraints; no global reactivation was attempted.PasswordModal, the session store, or the WebSocket layer.Files changed
web/src/App.tsx: 9 lines (corrective)web/src/App.test.tsx: 229 lines (regression tests)AI-Enhanced Development
Cache Impact