Skip to content

Start Practice when session storage is blocked - #603

Open
sidney-Hung wants to merge 2 commits into
sysprog21:mainfrom
sidney-Hung:lobby-blocked-storage
Open

sidney-Hung wants to merge 2 commits into
sysprog21:mainfrom
sidney-Hung:lobby-blocked-storage

Conversation

@sidney-Hung

@sidney-Hung sidney-Hung commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Problem and behavior

Where site data is blocked, reading the sessionStorage global throws. The lobby's Start handler named the global in the arguments of its storage helpers, so the exception came before any helper could handle it. Its message landed in #grounding-error, inside a collapsed <details>, and Start looked like it did nothing.

After this change, Practice without grounding opens the interview with storage unreachable. With grounding selected, Practice shows the existing "Clear grounding to start normally" message, since the packet can only reach the interview page through storage. When Practice starts without grounding, a ticked "share this focus" choice is not carried: storeSharedFocus() already treats a failed write as an unshared focus, and a refusal would land in the collapsed section like the original bug. Strict still stays on the lobby because it cannot run without storage, and #grounding-error now holds storageError instead of the raw exception text.

A real browser block also refuses the session cookie. On a server that admits guests, Practice reaches the interview. On a server that requires sign-in, with nobody signed in and session storage unreachable, Start now stays on the lobby with its choices kept, says in #account-status: "Signing in needs site data, which this browser is blocking for this site. Allow site data for this site, then reload this page.", and moves focus to the sign-in field so the message is on screen at narrow widths. Without that check, the storage fix alone would send the candidate to the interview page, which finds nobody signed in and bounces back to a reset lobby. The check assumes that blocked session storage means blocked cookies. Where only storage is blocked and cookies still work (Firefox's dom.storage.enabled=false may produce this; I have not checked), Start refuses a candidate who could sign in; the "Use GitHub" button still signs them in.

That check needs the session state, which is unknown until /api/session answers. With session storage unreachable, Start is held while the answer is pending, without the site-data message since the server may still admit guests, and is released when it arrives. If the check fails with no login attempted, the lobby goes to the existing account retry state instead of "Signed out" with Start enabled. The cost: with storage blocked and the check failing, a guest also waits for a successful retry before Start.

A storage global named directly under web/ now fails ESLint, with one exemption described below.

Limits, not changed here:

Sign-in itself is unchanged. Under a full block, "Use GitHub" and Enter in the sign-in field still call /api/login and report "Try signing in again", which cannot work there and replaces the site-data message.

From reading the code, once Start reaches the interview with storage unreachable, some existing choices do not survive, as before for any page without storage: the "Show the LeetCode problem" tick, lobby settings after returning, candidate cases on reload, and in-interview preferences. The grounding refusal is also hidden if the candidate closed the section again before pressing Start.

Strict visibility: the storageError text stays hidden while the <details> is collapsed. Where to show a storage failure is an open question in #600, so this change leaves the <details> as it is.

web/peer-lobby.js is exempt from the rule until its own fix; I can open a separate issue for it if you agree. It holds five of the 18 references #600 lists at 4de45b1. Opened from an invite link with storage blocked, the page throws at module scope and stays on "Checking account..."; signed out without an invite, it shows the raw exception text. A mechanical conversion would pass the rule and still throw on null.

Approach

The first commit passes storageArea("sessionStorage"), added in d5ad668, at the four web/app.js call sites; the helpers already handle the null it returns. It also adds the sign-in check above and the hold and retry routing for an unknown session state, all gated on session storage being unreachable. Two existing tests in tests/browser/account.test.js assert the literal call text, so they are updated, and tests/browser/lobby-render.test.js pinned the old failed-check state, so its expected values now describe the retry state. New lobby tests cover Start with storage unreachable in Practice, in Practice with grounding selected, in Practice with a shared focus ticked, in Strict, and on a server that requires sign-in (at a 375-pixel width), while the session check is pending, and after it fails. They make sessionStorage throw while cookies and localStorage still work, a partial block rather than a real browser setting. Most of the commit's size is these tests.

The second commit adds no-restricted-globals and no-restricted-properties for both storage names and converts the seven references in web/history.js. They go through a small deviceStorage() helper that throws when no store can be reached, so each caller's catch still reports the failure and their results do not change. A new test checks that deleteReport still answers "failed" and "account-deleted-local-failed" with storage unreachable. The storageArea() doc comment in web/audio-output.js now says that a caller that must tell a failure from an empty store has to check for null itself, which is what deviceStorage() does.

web/history.js imports storageArea from ./audio-output.js rather than a new module: both pages that use it already load that file, and moving the helpers is a separate refactor. The rules apply to web/**/*.js only; the review workbench is a local developer tool that does not import audio-output.js.

Validation

Each new Start test fails without its part of the change and passes with it. The deleteReport test fails without deviceStorage() and passes with it. npx eslint . passes, and reintroducing the module-scope read d5ad668 removed fails it at web/interview.js:477. A script also ran Start in Chromium with its real block-site-data setting: on a server that requires sign-in it stays on the lobby with the message above, and after allowing site data the open page still threw until it was reloaded, which is why the message asks for a reload.

Locally, review-memory-tests, shell-syntax and interview-scroll.test.js fail, and each fails the same way on main on this machine. local-recorder.test.js failed once in a full browser lane and passed six of six runs alone, on this branch and on main; this change does not touch the files it covers. The interactive-review check fails at its checkout step before measuring anything, as on #605 and other pull requests from forks.

Not checked: Firefox, keyboard and screen-reader behavior on the refusal (pressing Start again rewrites the same text, so a repeat may not be announced), the hold and retry states under a real browser block, and the real interview page under a real block on a server that admits guests.

Close #600

Written for commit 8a49e07. Summary will update on new commits.

View guided diff

cubic-dev-ai[bot]

This comment was marked as resolved.

@sidney-Hung
sidney-Hung force-pushed the lobby-blocked-storage branch from e23d9fd to 8a49e07 Compare November 6, 2026 13:32
jserv

This comment was marked as outdated.

Comment thread web/app.js Resolved
jserv

This comment was marked as outdated.

@jserv jserv added the explained A maintainer has seen the contributor explain this large change label Nov 6, 2026
@sysprog21 sysprog21 deleted a comment from sidney-Hung Nov 6, 2026
@sidney-Hung
sidney-Hung force-pushed the lobby-blocked-storage branch from 7bdf6a2 to 970da60 Compare November 6, 2026 18:12

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebase the current branch onto the upstream default branch and resolve any conflicts. Run /codetrial-review in AI agents (use $codetrial-review in Codex) and resolve all identified issues. Rework the series into minimal, logically coherent commits, squash closely related commits, and ensure all commit messages follow the project’s rules.

Comment thread web/app.js Resolved
@jserv

jserv commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Some review comments on this pull request are not settled yet. Please refine the change per the review comments listed below, reply on each thread with what you changed or why you did not, and mark each thread resolved yourself once it is settled (Resolve conversation, at the bottom of the thread). The pull request stays blocked while review threads are open.

Not addressed at the current head:

Addressed at the current head; reply with what changed and resolve:

Checked at 970da60.

@sidney-Hung
sidney-Hung force-pushed the lobby-blocked-storage branch from 970da60 to fad6f07 Compare November 7, 2026 04:52
cubic-dev-ai[bot]

This comment was marked as resolved.

Comment thread web/app.js Resolved
Comment thread web/app.js Resolved

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebase the current branch onto the upstream default branch and resolve any conflicts. Run /codetrial-review in AI agents (use $codetrial-review in Codex) and resolve all identified issues. Rework the series into minimal, logically coherent commits, squash closely related commits, and ensure all commit messages follow the project’s rules.

@sidney-Hung
sidney-Hung force-pushed the lobby-blocked-storage branch from fad6f07 to 3d27e68 Compare November 7, 2026 05:51

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

View guided diff | Re-trigger cubic

Comment thread tests/browser/account.test.js Resolved
Where site data is blocked, reading the sessionStorage global throws.
The lobby's Start handler named the global in the arguments of its
storage helpers, so the throw came before any helper could answer it,
and the only trace was the browser's exception in an error line inside
a collapsed section: Start looked like it did nothing. d5ad668 gave the
interview page storageArea() for this, and the helpers already accept
the null it answers, so Practice without selected grounding now reaches
the interview, as the interview page expects. A server that requires
sign-in cannot admit a candidate whose session cookie is refused, so
when nobody is signed in Start stays on the lobby, says why in the
account line and does not call /api/login. This assumes a blocked
session storage means blocked cookies. Until the session answers Start
waits, and a failed check offers the account retry instead of
navigating, because either could hide such a server. A practice focus
the candidate ticked to share is not carried: storeSharedFocus holds an
unshared focus to be the safe outcome, and a refusal would land in the
collapsed section. Selected grounding can only travel through storage,
and Strict cannot run without it, so both stay on the lobby and that
line now holds their own reason instead of the browser's exception. The
section stays collapsed, so a Strict candidate still has to open it to
read the reason.

Change-Id: I811889775931b8bb8c1246e2446330ac2e8d0860
Naming localStorage or sessionStorage throws where site data is
blocked, and works everywhere else, so the bug passes every local run:
it stopped the interview page from loading until d5ad668 and left the
lobby's Start doing nothing visible. The lint gate now refuses the
names under web/ and points at storageArea(), which answers null
instead. web/history.js moves to it through a helper that throws when
no store can be reached, because its callers tell a failed delete from
an empty store by that throw: each catch still reports the failure, so
its results do not change. web/peer-lobby.js is left out with the
reason beside the exclusion: it has the same failure, at module scope
when opened from an invite, and fixing it means choosing where an
invite token lives without storage, not a rename.

Close sysprog21#600

Change-Id: I8fddb84b7ff95dc4a0e507b2d5b1b522ba9154f7
@sidney-Hung
sidney-Hung force-pushed the lobby-blocked-storage branch from 3d27e68 to 58ec809 Compare November 7, 2026 06:08

@jserv jserv left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebase the current branch onto the upstream default branch and resolve any conflicts. Run /codetrial-review in AI agents (use $codetrial-review in Codex) and resolve all identified issues. Rework the series into minimal, logically coherent commits, squash closely related commits, and ensure all commit messages follow the project’s rules.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

explained A maintainer has seen the contributor explain this large change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Start does nothing visible in the lobby when site data is blocked

2 participants