Skip to content

Make route guards await the current user - #11

Merged
percolator merged 1 commit into
mainfrom
claude/bioinformatics-quiz-app-lpr8hz
Aug 2, 2026
Merged

Make route guards await the current user#11
percolator merged 1 commit into
mainfrom
claude/bioinformatics-quiz-app-lpr8hz

Conversation

@percolator

Copy link
Copy Markdown
Contributor

Frontend-only hardening plus regression cover for cold loads.

This does not fix the "Session not found." / broken QR report — see the honest note below before merging with that expectation.

Change

teacherGuard decided from auth.user() synchronously, while that value is filled in by an asynchronous /api/auth/me lookup. It now waits for that lookup, which AuthService.ensureLoaded() performs at most once and shares between callers.

A guard that races the very fact it depends on is wrong regardless of whether the race currently fires, and the shared fetch also removes a duplicate request on startup.

Honest assessment

I claimed this was a confirmed cause of the reported symptom. It is not, and the test proves it:

  • e2e/cold-load.spec.mjs reloads teacher URLs (/join, /control, /teacher) with /api/auth/me delayed by 700 ms to simulate a real connection
  • it passes both with and without the change

So the race does not appear to fire in practice — Angular's initial navigation evidently does not beat the lookup, even when the lookup is slow. The change is kept on its own merits, not as a fix.

Regression cover added

  • cold-load.spec.mjs — cold loads of teacher URLs must not bounce a logged-in teacher to the login page, and the view must render without an error banner. Nothing covered bookmarks, reloads, or the second window used for projecting.
  • smoke.spec.mjs now asserts that reloading a session view leaves no error banner and the QR still renders. The suite previously never checked the error banner was absent, which is precisely the symptom reported.

Testing

61 backend tests, 5 frontend unit tests, 5 browser specs — all green.

Still open

The reported "Session not found." with a broken QR, while the join URL renders, is unexplained. /join-url succeeded on the same page and with the same cookie that /state and /qr.svg apparently failed on. The status codes of those two requests from the browser's network tab would identify it: 401 points at an expired cookie (the session cookie lasts 12 hours), 404 at the session missing from the database, 500 at a server error with a traceback in the deployment log.

🤖 Generated with Claude Code

https://claude.ai/code/session_018u3wNzXNdrPw2Z59WjGHYv


Generated by Claude Code

The teacher guard decided from auth.user() synchronously while that value is
populated by an asynchronous lookup, so on a cold load the decision could be
made before the answer arrived. It now waits for the lookup, which is fetched
at most once and shared.

Note this was not reproducible: a browser test that reloads teacher URLs with
/api/auth/me delayed by 700ms passes both with and without the change, so the
race does not appear to fire in practice. The change is kept because a guard
that races the very fact it depends on is wrong regardless, and the test is
kept as regression cover for cold loads — reloads, bookmarks, and the second
window used for projecting.

The smoke test now also asserts that reloading a teacher view leaves no error
banner behind, which nothing covered before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018u3wNzXNdrPw2Z59WjGHYv
@percolator
percolator merged commit b1d094a into main Aug 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants