Repository navigation
fix: fix Web Console hanging when SSO token refresh fails - #603
glasstiger wants to merge 54 commits into
Conversation
When an OIDC token refresh failed at the transport level (token endpoint unreachable, or a non-JSON response body), refreshTokenMethod() rejected inside the setInterval callback of refreshAuthToken(), before the static refreshTokenPending flag was reset. The flag was left stuck true, the outer promise never settled, and every subsequent query deadlocked waiting on it — the console silently froze with no 401 and no logout. Wrap the refresh in try/catch/finally so refreshTokenPending is always reset. On failure the stale token is kept in place and the next request receives a 401, which drives the existing re-auth flow — matching the behaviour when there is no refresh token at all. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts: # src/utils/questdb/client.test.ts
Web Console deploy preview
|
The OIDC refresh-failure E2E test reuses the fake token fixtures used throughout oidc.spec.js. Ignore the findings in 0f4d4ac and mark the lines with gitleaks:allow so the squash commit on main is not flagged either.
The legacy grid mounts only after the first result arrives, so asserting .qg-viewport right after reloading with useNewGrid=0 always timed out. Assert it after the first query instead. Also release the old query's page before the new result loads that page. The previous scroll away and back could refetch the page, hiding the stale write, so the test only sometimes failed without the generation guard.
When the server reads the user's groups from the ID token (acl.oidc.groups.encoded.in.token), the console authenticates with the ID token, yet it timed the refresh by the token response's expires_in, which describes the access token. Time it by the ID token's exp claim instead, and fall back to expires_in only when the claim is unreadable. If the identity provider did not return the ID token the server expects, at sign-in or on refresh, the console sent "Bearer undefined", and the resulting 401s ended the session with no explanation. Show a "Missing ID token" error instead, and never install a missing bearer. The OAuth callback params stayed in the URL after a failed sign-in, so a reload resubmitted the used code, and its invalid_grant error replaced the original one. Restore the URL whatever the outcome, which also keeps a shared query link across a failed sign-in. A token endpoint that could not be reached, returned a response that is not JSON, or did not respond left the sign-in on a blank screen. Show an error instead, and give up after 10 seconds, the same timeout as the refresh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A token response may omit expires_in, which OAuth only recommends. An ID token bearer expires at its exp claim regardless, so it no longer needs one. Without any known expiry, sign in anyway, but never refresh the token, proactively or after a 401: such a provider typically issues no refresh tokens either, so the token is used until the server rejects it, and the user then signs in again. A catalog request's 10s deadline kept running while the client waited for the token refresh that follows a 401, so Query Activity and table details could become unavailable even though the refresh succeeded. The client now reports every refresh wait, and the catalog deadline gives the refresh its own bounded time before restarting the SQL timeout. Modal dialogs hide the rest of the page from assistive technology, except live regions, which hid the SSO refresh warning from screen readers. Mount the notifications in a live region, as later react-toastify versions do. The refresh warning promised a retry, which does not happen while a timed-out refresh request is still pending. State only the consequence. The enterprise reload test returned expires_in: 0, which is not a valid lifetime. Use 300 seconds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Address the PR review findings across token renewal, script outcomes, notebook persistence, session teardown, accessibility, and auth types. Add regression coverage and document the complete PR scope.\n\nValidated with typecheck, lint, production build, 2,838 unit tests, and 38 stubbed auth browser tests.
Preserve never-started notebook run outcomes, reject stale headless results before serialization, and fix dialog and login focus handling. Update persistent refresh warnings at token expiry, add regression coverage, and correct the PR description shortcut and fixture count.
Restore SSO refresh capability across provider remounts, recover schema after local renewal failures, and preserve no-send outcomes for queued headless reads. Settle script loading independently of abort targets, defer accepted snapshot preparation until after session invalidation, and align headless cancellation metadata. Add 14 regression tests. Validated with typecheck, lint, build, and 2,887 unit tests across 151 files.
Keep transient refresh failures recoverable after SQL 401 responses, preserve password form focus, and restore shortcut focus when closing notifications. Simplify loading notification settlement to use only the query ID and extract the shared button base without tooltip dependencies. Add unit and browser regression coverage.
Prevent obsolete initial code exchanges from replacing recovered logins, coordinate recovery across mounted schema panels, and report validation-only notebook runs as never executed. Add regression coverage for all three review findings.
Level-3 code reviewIssuesNo confirmed introduced defects found in PR #603, reviewed at The level-3 review completed all 13 independent passes and a widened follow-up on unchanged callers. No broken out-of-diff contract was established. False-positivesNo draft findings were submitted for per-finding verification. Two exploratory concerns were resolved during the caller follow-up:
SummaryVerdict: approve, based on source review and passing local quality gates—not a completed CI or live-integration sign-off.
Validation limits at review completion:
No introduced regression was confirmed across authentication, query execution, notebook persistence, notifications, catalog recovery, or grid replacement. Totals: 0 confirmed findings; 0 draft findings requiring verification. 0 in-diff / 0 out-of-diff defects. No source files were changed. |
Resolve all 32 review findings covering refresh coordination, session isolation, keyboard access, schema recovery, notebook persistence, and regression coverage. Remove the stale PR draft and unrelated server bump.
Address the Moderate and Minor review findings for PR 603, including toast accessibility, CSV upload races, interruption history, session fencing, schema recovery, settings feedback, and non-renewing telemetry. Consolidate shared helpers and extend regression coverage. Validated typecheck, lint, production build, 3,031 unit tests, and 64 stubbed Chrome browser-auth tests. Live Enterprise OIDC and manual screen-reader validation remain separate checks.
Propagate terminal query outcomes to accepted aliases and moved namespaces. Batch CSV status refreshes and include pending uploads in reauthentication interruption checks. Restore grid selection after notification excursions and origin focus on toast message dismissal. Add unit and native-browser regression coverage.
Replace fixed rendering sleeps and zero-timeout snapshots with retryable DOM assertions. Wait for the measured scroll range before scrolling while retaining the 10,000-query virtualization, filter and sorting checks.
Include pending preference writes in sign-in interruption checks. Restore notification focus on actual dismissal and retain external origins across toasts. Use an IndexedDB compound revision index for headless snapshot checks without loading result payloads. Add unit and browser regression coverage.
Option+N types ñ/ã/õ (as a dead key) or ń on Apple keyboards. While any toast was visible, the notification shortcut consumed that key in Monaco and other text fields and moved focus into the toast. On macOS and iPadOS the shortcut now leaves Option+N to text fields and still works elsewhere. Windows and Linux Alt+N, which types nothing, is unchanged. The refresh warning tells Apple users to press it outside a text field. The logout and "Sign in again" warnings counted console-issued reads as user statements, so an expired session reported that statements may have executed when nothing was run. Catalog, schema, monitoring, telemetry, result paging, chart and notebook auto-refresh reads now pass a background option that is never sent to the server. They are still aborted when the session ends, but no longer count. "Sign in again" only claims execution uncertainty when a user statement or write was sent. Pin the platform in e2e tests that press Alt+N in text fields, so the suite matches CI on macOS hosts, and add a macOS Option+N test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The three .gitleaksignore entries added here fingerprint lines 102-104 of e2e/tests/enterprise/oidc.spec.js in commit 0f4d4ac. That commit is on the #603 branch, not in this branch's history, and those lines hold no token here. Every token this branch adds to oidc.spec.js is marked with gitleaks:allow, so the entries suppressed nothing. #603 carries its own copy of them.
) * fix: fix Web Console hanging or signing out when SSO tokens expire Extracted from #603: the console half of questdb/questdb#7799 and questdb/questdb-enterprise#1267. Those PRs stop serving a request from the qdb_session cookie when its Authorization header is rejected, so an expired or stale bearer now gets a 401 and closes the session instead of being masked. - Refresh an ID-token bearer (acl.oidc.groups.encoded.in.token=true) by the ID token's exp claim rather than the access token's expires_in, and report a missing ID token instead of sending "Bearer undefined". - Read the bearer at send time for SQL, validation, CSV check/import and preference requests, and never let stored REST/Basic credentials replace an SSO bearer. - Coordinate token refresh in one bounded, cancellable place: queries wait up to 10s, a rotating refresh may still land within 60s, transient failures back off without logging out, and an expired bearer is never sent after a failed renewal (fixes the refresh deadlock that froze every query). - Recover from a rejected bearer: refresh and resend once (a 401 executed no SQL), ignore 401s answered for an older bearer, and log out only when the current bearer is rejected. - Show a renewal warning and a recovery view with Retry/Sign in again instead of a blank console, and report sign-in failures. - Share one client between the console and telemetry so telemetry never sends a stale bearer, and mark read-only requests as background so logout warnings only count statements and writes. - Dispatch the Enterprise Web Console e2e lane added by questdb-enterprise#1267, send the stored REST token in e2e execQuery, and extend the unit and stubbed browser auth tests. * update submodule * fix: keep uploads, the schema tree and notebook results intact when the session ends - Let uploads and settings saves that are already being sent finish when the session ends, instead of aborting them mid-stream: an aborted CSV upload can leave a partially imported table. Their results are still rejected as session-ended and no longer count as the next login's activity. Queries, and writes still waiting for renewal, are cancelled. - Show a failed SSO renewal in the Schema panel and reload it once a request succeeds, instead of leaving the tree blank. - Supersede notebook cell runs, auto-refresh rounds and headless agent runs before session end aborts their requests. Their aborted results no longer overwrite the last good snapshot, save refresh errors, delete chart snapshots or record a possibly committed write as a failed run. - Cover the session-end client behaviour, Schema recovery, notebook session end and run_query's unverified classification, and add an e2e test for renewing and resending an editor statement once after a 401. * test: test SSO 401 recovery against a real Enterprise server Every 401 in the auth e2e tests was stubbed, so nothing checked the tandem server change (questdb/questdb#7799, questdb/questdb-enterprise#1267) against a real server. The new Enterprise OIDC test leaves /exec unstubbed. After a reload, silent re-auth installs a bearer the userinfo fixture rejects, while the browser still sends the qdb_session cookie of the earlier sign-in. The test checks that the server answers that session start with 401 instead of serving it from the cookie, and that the console renews its token once and resends its startup check once, then keeps working as the same user. Document this coverage, and that ID-token bearers still need an Enterprise lane with a fixture that signs ID tokens. * update submodule * update submodule * ci: run the OSS submodule check on Python 3.12 "Check if OSS is on master" failed on runners with the ubuntu-26.04 image, whose default Python is 3.14. pygit2 1.14.1 ships wheels only up to CPython 3.12, so uv built it from source and failed on the missing libgit2 headers (git2.h). Runs on ubuntu-24.04 still passed. Pin the interpreter so uv installs the prebuilt wheel on every image. The check itself is unchanged; the e2e/questdb pointer is the OSS master head. * fix: warn before leaving the page would cancel uploads still being sent Ending a session lets uploads and settings saves that are already being sent finish, because aborting a CSV upload mid-stream can leave a partially imported table. But "Sign in again" told users those uploads "may still finish", and the Login view's next step, signing in with SSO, navigates away and cancels them. - Keep counting sent writes after their session ends, until they settle. - Show that count on the Login view, and ask the browser to confirm leaving the page (SSO redirect, reload or closing the tab) until they finish. Logging out from the toolbar, which reloads at once, is unchanged. - Say in the "Sign in again" confirmation that uploads continue only while the tab stays open. * test: test startup 401 recovery in the required auth e2e lane The only check of the tandem server change (questdb/questdb#7799) against a real server is in the Enterprise lane, which CI skips unless ENTERPRISE_E2E_ENABLED is set. Replay its startup sequence with stubs, for access-token and ID-token bearers: the server rejects the new bearer of both the session start and the startup check, and the console renews its token once, resends the check once and keeps the session. * fix: keep CSV uploads and edits when a delayed table check returns A table check can now wait up to 10s for a token refresh. The Import view then replaced the whole file list with a copy taken before the wait. That reset a running upload to "Upload", so a second click could import the file twice. It also reverted edits and dropped files added meanwhile. - Merge only the checked status into the current list, and ignore a status checked for a name the file no longer has. - Apply renames and other edits at once, so an upload started during the check uses the new name. Only the status waits for the check. * fix: stop a query rejected with 401 from waiting 60s for renewal After a 401, a query waited for the token refresh until its 60s network deadline. Queries waiting before their first request gave up after 10s, when the console already reported the renewal as failed, so a rejected statement kept running next to the failure warning. After a 401, wait no longer than before the first request. The refresh itself still runs to its network deadline, so a late rotated token is still installed for the next request. * fix: stop asking to sign in again on queries the old session interrupted Ending the session without a reload rejects the queries still running with "Your session has ended. Please sign in again." The editor and the AI chat stored that as the query's notification, so after signing in again with a password, the console still asked the user to sign in. - Editor, script and AI chat runs now say that the query was not run, or that it was interrupted and may have executed. This also replaces the "Running..." notification, whose Stop button would otherwise start a query. - A result page read interrupted by the session end adds no notification. * fix: clear the Schema panel's renewal error once the tables load again A failed SSO renewal is shown in the Schema panel. After the renewal recovered and the tables loaded, a later unrelated failure still showed "Could not renew your SSO session". * fix: end the identity provider's renewal error as a sentence Identity providers often omit the full stop, e.g. Keycloak's "Token is not active", which read "Token is not active Please sign in again." * fix: keep downloads working after the console recovers from a 401 A 401 for a rejected bearer closes the server's cookie session, and the Enterprise server deletes the qdb_session cookie with every 401. The console renewed its token and resent the query, but never asked for a new session. Downloads authenticate only with that cookie, so CSV and Parquet exports failed with "Unauthorized" until the page was reloaded. After a 401, the next SQL request of the same SSO login now sends session=true, one request at a time, until the server accepts one. The server opens a session for it only when the browser sent no cookie, so the parameter changes nothing while the cookie is still valid. * fix: stop showing the old table's status for a renamed CSV import Renaming the target table of a queued CSV applied the new name at once, but kept the old name's status until the existence check answered. The check can wait up to 10s for a token renewal, and a failed check never answered. A file renamed to an existing table could show "Ready to upload", and its upload appended to that table without the "Table already exists" warning. The new name now shows "Checking table name…" and can't be uploaded until its check answers. A failed check shows "Could not check table name" instead of the old status. * fix: keep the unfinished-upload warning after signing in again Ending a session lets uploads and settings saves that are already being sent finish, and Login asked before leaving the page until they did. But signing in again with a password replaces Login without leaving the page, so the notice and the leave-page prompt disappeared while the upload was still being sent. A reload then cancelled it without asking, which can leave a partially imported table, and the empty Import view invited importing the same file again. - Ask before leaving the page in every view, not only on Login, until the previous session's writes settle. - After signing in again, show a warning with their live count in the console until they settle. - Logging out from the toolbar still reloads at once. Asking there could keep a console without a session, as Login is not shown before the reload. The warning says that logging out cancels them. * fix: stop an editor script cleanly when the session ends Ending the session aborts a running script's statement and stops the script before its next one, but nothing tested it, and the end of the run failed: the editor is unmounted while the script settles, and revealing the position of an editor without a model threw "Invalid arguments". The run was never settled, so the editor stayed marked as running a script and the query log missed its "Stopped after..." summary. - Settle the run when the editor no longer has a model. - Check for a stop before the first statement too, so a session that ends while the script waits to start sends nothing. - Test both ways a session ends during a script, with stop after failure off: signing in again while a statement runs, and a 401 that signs the user out. The script stops before its next statement, and the log says whether the interrupted statement may have executed or was not run. * chore: drop gitleaks fingerprints of a commit outside this branch The three .gitleaksignore entries added here fingerprint lines 102-104 of e2e/tests/enterprise/oidc.spec.js in commit 0f4d4ac. That commit is on the #603 branch, not in this branch's history, and those lines hold no token here. Every token this branch adds to oidc.spec.js is marked with gitleaks:allow, so the entries suppressed nothing. #603 carries its own copy of them. * fix: reopen the cookie session after any 401, not only a query's The server closes the session of a request whose bearer it rejects, and Enterprise deletes the qdb_session cookie with every 401. The console asked for a new session (session=true) only after an /exec 401. Live validation, CSV checks, uploads and settings saves send the same cookie, and validation runs while the user types. If one of them saw the 401, and the bearer was renewed before any query was rejected, no query asked for a session. CSV and Parquet exports, which authenticate with the cookie alone, then kept failing. Record the lost session whichever request saw the 401. While the cookie is still valid, asking for a session changes nothing. * fix: keep dropped CSV files when their table check fails A table check can wait for a token renewal and then fail, e.g. after a failed SSO renewal. Only a renamed file handled that. A dropped file was silently lost: it never appeared, and no error was shown. And one failed recheck, when the Import view became visible, discarded every other file's new status. - List a dropped file whose check fails as "Could not check table name", like a renamed one, and let it be uploaded. - Keep a file for an existing table whose schema can't be read, without a pre-filled schema. QuestDB then infers it from the file. - Keep a file's status when its recheck fails, and merge the others. - Count dropped files as queued at once, so that dropping one again while its check waits is reported as a duplicate, not queued twice. * fix: keep notebook snapshots when a refresh is not executed After a failed SSO renewal the user stays signed in, but statements are not executed. Auto-refresh rounds treated that like a failed query. A chart's frame was replaced with errors and its saved snapshot deleted, and a grid saved "Could not renew your SSO session" as a refresh error, shown again after the next sign-in. Rounds cut off by the end of the session are already dropped. Treat a statement that was not executed like an aborted one. A chart keeps its frame and its saved snapshot. One with nothing to show yet shows the failure, but still keeps its snapshot. A grid slot keeps its rows, and the round saves nothing. * fix: stop presenting auth failures as SQL errors or unsent requests A failed SSO renewal was marked in the editor like a SQL error: a red marker on the query's first word, with the cursor moved there. A session end already only replaced the "Running..." notification. The messages also said "not sent" of requests that the server had received and rejected with 401 or 403. What holds in every case, and tells the user that a retry is safe, is that nothing was executed. - Show a failed renewal in the notification only, for single runs and scripts, without marking the query. - "Not executed: your previous session ended without running this query." replaces "Not run: your previous session ended before this query was sent." - A failed renewal says "the request was not executed" instead of "the request was not sent", and the recovery view no longer says "No request was sent." * fix: clear the last query result when the session ends The store outlives the console: signing in again with a password remounts it in the same document, without a reload. The result grid then showed the previous login's last rows, possibly to another user, and scrolling re-ran its query with the new credentials. Clear the result when the session ends. Notifications stay: they tell whoever signs in next what the end of the session interrupted. Also correct the logout comment, which described a store reset that did not happen. * update submodule * fix: renew the SSO session when Retry is pressed after a failure After a failed SSO renewal, the recovery view's Retry did nothing for 5 to 30 seconds: the backoff between failed renewals refused it at once, without a request, and the view looked unchanged. While a renewal that had timed out was still waiting for the identity provider, for up to 50 seconds, Retry was refused the same way. The view still said "Retry to renew it". - Retry skips the backoff between failed renewals, which protects the identity provider from background requests. The throttle after a successful renewal still applies. - If a renewal is still in flight, Retry waits for its answer instead of starting another, which could spend a refresh token the first has rotated. It shows "Reconnecting…" meanwhile. - The recovery view no longer asks to wait before retrying. The renewal warning says that queries retry the renewal after a short wait. They keep the backoff, so that a script doesn't renew once per statement. * fix: stop an edited chart drawing forever when it is not executed A refresh round with a statement that was not executed, e.g. after a failed SSO renewal, kept any frame the cell held, and didn't settle. After an edit, that frame was for the old SQL, which the chart doesn't draw. The cell showed "Drawing…" with no error until a later round reached the server. Keep the frame only if the chart draws it for the current statements, using the same test as DrawCanvas. Otherwise show the failure, as for a chart with no frame, and still keep the saved snapshot. * fix: end the previous login when settings recovery shows Login A failed settings refresh unmounts the console, and Retry mounts it again without ending the tab's login. If another tab had logged out meanwhile, removing the shared password credentials, Login was shown while this tab still counted as signed in. The next sign-in then kept that session: requests of the previous login could still complete into it, and none of the session-end cleanup ran, so its last result stayed. End the session before showing Login in that case, and explain the interrupted requests as logout does. Stored credentials and the server session are left alone. * fix: close gaps around session end and failed SSO renewal - An agent's run on a closed notebook was dropped whole when the session ended, so the cell kept its previous run on record, even for writes that had already committed, and they could be repeated. Only a run that has not launched is cancelled now. A launched run records the statements that completed, and the one in flight as interrupted, with its outcome unverified. Its remaining statements are not sent without the login's credentials, and are recorded as not executed. A saved result says what the end of the session did to the query, instead of asking to sign in again. - A chart whose frame for its SQL had no rows to draw, e.g. the error of a run kept when the cell became a chart, still showed "Drawing…" forever after a round that was not executed. Keep only a frame that the chart draws. - A CSV file dropped again while the table check of its first drop waited for a token refresh could still be queued twice: any change to the list, and showing the list for the first time, forgot the pending name. ImportCSVFiles now tracks the dropped files that are not listed yet, and the drop box counts them as queued. - "Sign in again" removed the SSO session flag that other tabs share, so another SSO tab that reloaded showed Login instead of signing in silently. It now ends only this tab's session. - When the session ended, the Schema panel took its interrupted columns load for an unsupported function, and sent the fallback query without credentials. It now stops. After a failed renewal it doesn't try the fallback either, as the server ran no query. Answers that arrive after the session ended are not stored. - The tables and columns of the previous login stayed in the store after a session end without reload, and fed autocomplete, the AI assistant and CSV import for whoever signed in next. They are now cleared with the last result. * update submodule * fix: close more gaps around logout, session end and SSO renewal - Ending the session of an SSO tab, by logging out, signing in again or after a 401, removed the password credentials that tabs share, so another tab signed in with a password showed Login once it reloaded. Only a tab signed in with a password removes them now. An SSO tab also keeps its login method, so that reloading it resumes SSO or shows Login, instead of signing in with another tab's password. - Logging out from the toolbar reloads the page at once, which cancelled running statements and uploads being sent without asking, although a cancelled CSV upload can leave a partially imported table. It now asks first, and keeps the session if declined. - Logging out from the toolbar also cleared the last result, tables and columns before the reload, blanking the console for a moment. The reload discards them anyway, so they are left to it. - When the session ended, an agent's read-only run on a closed notebook recorded its reads as interrupted or not executed, replacing the previous run and its saved rows. A read-only run is now cancelled like one that has not launched, so the previous run stays on record. A run that writes still records what it did. - Once the token had expired, a statement run again while a timed-out renewal still waited for the identity provider, for up to 50 seconds, failed at once without a new renewal, although the renewal warning says that running it again after a short wait retries the renewal. After the backoff, a statement the user runs now waits for that renewal to be answered or given up, and then renews. Background reads, and statements run during the backoff, still fail at once. - The one-off telemetry config read at startup never renewed the session, so it failed near expiry or after a failed renewal, e.g. at every login with a token that lives under 30 seconds. Metrics then asked to enable telemetry, and console events were not tracked, until the next login. The read may now renew the session, like the console's other reads. - If the request that opens the cookie session at SSO sign-in was rejected or could not be sent, downloads could fail for the whole login: only a later 401 made a request ask for a new session. The next SQL request now asks for one in that case, and a network error there no longer escapes as an unhandled rejection. - A chart without a frame it could draw deleted its saved snapshot on the second round in a row that was not executed: that round matched the failure the first one showed, and an unchanged frame without rows cleared the snapshot. The snapshot now stays until a round reaches the server.
|
superseded by #617 |
Review follow-up pushed in
9da50a589c36e7bf1d8719f8db919f0e6636b3fd.Summary
Fix the Web Console hanging indefinitely when an SSO token refresh fails, and
make query execution and notebook persistence respect the authentication session
that started the work.
Refreshing is shared across SQL consumers, cancellable and bounded. Queries
normally wait up to 10 seconds; a rotating refresh request can continue until
its separate hard deadline (at most 60 seconds). A server-side 401 recovery
waits for that request rather than cancelling a potentially usable rotated
refresh token.
Transient transport, timeout, HTTP 429 and 5xx failures back off without forcing
logout. Once the bearer expires, SQL is not sent until renewal succeeds. The
console reports that explicitly, rather than reporting a database outage or
telling an agent that a never-sent write may have committed. An authoritative
OAuth rejection still returns the user to sign-in.
Complete scope
optional expiry handling; ID-token bearer expiry; refresh-token rotation;
missing required ID-token errors; callback URL restoration; tab-local session
generations; stable provider callbacks and subscription cleanup.
for SQL, validation, import and preferences requests; bounded refresh waits;
one safe retry after a rejected bearer; session-aware result/error fencing;
explicit session-ended and not-sent outcomes.
live queries, cancel delayed telemetry polls, and reset active/pending query
confirmations (including confirmations already waiting for cancellation).
excluded from notification history; settled/superseded loading notifications
are cleaned up; the notification Stop button only cancels its own execution;
scripts preserve confirmed outcomes and report partial completion on logout.
Script teardown is shared, without an extra settlement dispatch per statement.
separate layout-phase detachment from passive destruction; flush frames
accepted before logout while discarding late responses; atomically save
accepted headless metadata/snapshots; recover with metadata-only persistence
when a large snapshot aborts the root transaction. Byte capping runs before
acquiring the buffer write lock. Search updates publish only after root
commit.
refresh waits and SQL requests their own deadline budgets. Catalog code
receives the refresh budget from the client rather than importing coordinator
internals.
an older page cannot replace the current result; expose recycled row indices
to the stale-page regression test and document result-specific layout restore.
of queued requests, preserving concurrency limits and ordering.
its heading and transfer focus into the recovered console; preserve Retry
focus while busy; focus/describe sign-in errors; keep toast announcements
available outside the SQL gate and during dialogs; use live theme tokens; warn
both before and after token expiry; prevent incidental click dismissal;
restore a dismissed warning on subsequent failures; provide expiry
information, a sign-in action and Alt+N keyboard access. Renewal failures use
consistent copy.
types; extend unit and stubbed browser regressions; allowlist fake test tokens
in gitleaks; update the QuestDB E2E submodule (26 commits, including
permission-aware table visibility).
.github/workflows/enterprise_e2e.yml, an opt-in Azuredispatch using
vars.ENTERPRISE_E2E_ENABLEDandsecrets.ENT_DISPATCH_PAT.Fork PRs do not receive that secret. Private Enterprise source, binaries and
live fixtures remain in the private repository. Dispatch success is not a
passing integration result: check
enterprise-e2e-web-consolefor the testedSHA. Setup and local execution are documented in
e2e/README.md.Review follow-up coverage
Validation
Validation of earlier PR head
908eba9dd43af4f7080599b4cb1f7760e2d65a67(before the local six-issue follow-up):
yarn typecheck— passed.yarn lint— passed, including color-token checks.yarn build— passed (existing bundle-size advisory remains).yarn test:unit— 2,925 tests passed in 153 files.yarn cypress run --spec 'e2e/tests/auth/*.spec.js' --browser electron—57 passed against the production preview with stubbed HTTP responses:
47 auth, 6 notification and 4 unauthorized-recovery tests.
Six-issue follow-up validated locally on 2026-10-16 and now published in
842d2545e84cd134c01fb719ed0b0ad71e3a3f81(included in current PR head75eae8bb9ccb3526cc3270eb38eb32a2f521ded1):yarn typecheck,yarn lintandyarn build— passed.yarn test:unit— 2,941 tests passed in 154 files.yarn cypress run --spec 'e2e/tests/auth/*.spec.js' --browser electron—60 passed against the production preview with stubbed HTTP responses:
50 auth, 6 notification and 4 unauthorized-recovery tests.
CI selector follow-up in
75eae8bb9ccb3526cc3270eb38eb32a2f521ded1:name,
Close notification, instead of the obsoletecloseselector.yarn cypress run --spec e2e/tests/console/editor.spec.js --browser electroncompleted with 122 tests passing and 1 pre-existing pending test. The local
macOS Electron process then segfaulted during shutdown, so this was not a
clean command exit. A focused rerun of the previously failing test passed
with a clean exit against the real local QuestDB server.
and context-path tests.
Their final results are not claimed by the local validation above.
The earlier 2,838-unit/38-auth figures described an older validation checkpoint,
not the current published head or the local follow-up. The full console E2E
suite and live Enterprise OIDC lane were not run locally. The Enterprise
rotation assertion was extended locally but remains unverified in the private
lane; the stubbed auth suite is not a substitute for live IdP/Enterprise tests.