Skip to content

A stale pre-login refresh() can wipe a just-completed login() #83

Description

@tyler-rich

Background

AuthProvider (frontend/src/auth/AuthContext.tsx) fires a refresh() on mount.
If the operator signs in while that first fetchAuthStatus is still in flight, the
response — requested before the credential existed, so it carries user: null
can land after login() has already written the authenticated user, and overwrite
it. The shell drops back to the login screen despite a successful sign-in; the next
refresh() (or a re-login) recovers it.

This is the mirror image of the P3-4 race fixed in #82. P3-4 closed the
dangerous direction — a late refresh restoring a session that a 401/logout had
already ended. This one runs the other way: a late refresh clearing a session
that just legitimately started.

Why it is a small standalone follow-up, not part of #82

Scope of work

  • Decide the sequencing rule for authentication vs. an in-flight refresh() and
    apply it in login, verifyMfa, and setup (one mechanism, matching the guard
    idiom already in the file — not a third pattern).
  • Extend frontend/src/auth/AuthContext.test.tsx with a jsdom case: hold the mount
    refresh open, complete a login, then resolve the stale status with user: null
    and assert the session stays signed in. Confirm it fails before the fix.
  • Confirm the fix does not weaken the P3-4 invariant — a logged-out session must
    still never be restored by a late-arriving refresh — and that the existing race
    tests still pass.

Acceptance

  • A fetchAuthStatus answered before login and resolving after it can no
    longer clear the authenticated user.
  • The P3-4 invalidation tests (event mid-refresh, logout() mid-refresh) still
    pass unchanged.
  • New jsdom test verified to fail against the pre-fix provider.
  • Dated docs/ARCHIVE.md § 14 entry.

Ref: frontend review P3-4 (docs/reviews/frontend-review.md § Priority 3) and the
2026-07-24 § 14 entry added in #82.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions