Skip to content

fix(web): user-scope the prechat resume sessionStorage key (LUM-1763 follow-up)#31431

Merged
ashleeradka merged 1 commit into
mainfrom
ashlee/lum-1763-followup-user-scope-prechat-screen
May 21, 2026
Merged

fix(web): user-scope the prechat resume sessionStorage key (LUM-1763 follow-up)#31431
ashleeradka merged 1 commit into
mainfrom
ashlee/lum-1763-followup-user-scope-prechat-screen

Conversation

@ashleeradka
Copy link
Copy Markdown
Contributor

Follow-up to LUM-1763 (#31416, merged), addressing the unresolved Codex P2 thread on that PR.

Why

Codex flagged that the prechat_native_screen sessionStorage key wasn't user-scoped. Concrete scenario:

User A reaches the vibe step → logs out → user B logs in in the same webview session → user B lands directly on the vibe step instead of the name step.

The lazy useState initializer was reading the key unconditionally on mount, before any user identity was known.

What

  • Compute screenStorageKey = userId ? \prechat_native_screen:${userId}` : null` (null while auth is still loading).
  • Read happens in a useLayoutEffect keyed on screenStorageKey, so the restore runs once userId is available, before paint — no flash to the wrong step.
  • All write/clear sites (goToVibeStep, finishNativePreChat, vibe-step back button) use the user-scoped key.

If user B logs in after user A left the key behind, user B reads their own key (which doesn't exist) and starts at the name step. No leak.

Verified locally

  • bun run lint — 0 errors.
  • bun run typecheck — clean.

Test plan

  • CI green
  • Manual: native iOS, reach vibe step, hot-reload → still on vibe step (existing behavior preserved)
  • Manual: native iOS, reach vibe step, sign out, sign in as different user → land on name step (the leak this fixes)

https://claude.ai/code/session_01JPGu4yGPTL4JoLaPuqpEW2


Generated by Claude Code

@linear
Copy link
Copy Markdown

linear Bot commented May 21, 2026

LUM-1763

@ashleeradka ashleeradka marked this pull request as ready for review May 21, 2026 02:27
Follow-up to LUM-1763 (#31416 merged) addressing the Codex P2
comment on that PR:

> Reading prechat_native_screen unconditionally from
> sessionStorage means a stale value from a prior onboarding
> attempt can skip the name step for a different login in the
> same webview session (user A reaches vibe step, logs out, then
> user B logs in and lands directly on vibe).

Fix: key the persisted screen by userId. Read happens in a
`useLayoutEffect` once userId is known (vs the previous lazy
useState initializer that didn't have access to it), so we
restore before paint without risking a flash to the wrong step.
Write/clear sites now use the same user-scoped key.

If the prior session never logged out cleanly, user B reads
"their" key which doesn't exist, and starts fresh at the name
step — no leak.

Verified locally: lint, typecheck clean.

https://claude.ai/code/session_01JPGu4yGPTL4JoLaPuqpEW2
@ashleeradka ashleeradka force-pushed the ashlee/lum-1763-followup-user-scope-prechat-screen branch from 6d9bfe7 to 38629ce Compare May 21, 2026 02:28
Copy link
Copy Markdown
Contributor

@vex-assistant-bot vex-assistant-bot Bot left a comment

Choose a reason for hiding this comment

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

APPROVE

Clean follow-up to the Codex P2 from #31416. Also picks up the goToVibeStep de-dup I flagged as non-blocking there.


User-scoped key

screenStorageKey = userId ? \prechat_native_screen:${userId}` : nullcorrectly scopes the key to the active user and evaluates tonullwhile auth is still loading. All four storage sites (restore,goToVibeStep, finishNativePreChat, vibe-step back) guard on screenStorageKey` being non-null before touching sessionStorage. The logout→login bleed scenario Codex flagged is cleanly closed.

useLayoutEffect over lazy useState initializer

Right call. useLayoutEffect fires synchronously before paint, so the screen correction happens before the user sees anything — no flash to the wrong step if restore runs async. The deps array is [screenStorageKey] with screen intentionally omitted: re-restore should only trigger when the active user identity changes (mount or logout→login), not on every screen transition. Correct.

No cleanup needed on the effect

There's no subscription, timeout, or async operation — the effect is a single synchronous sessionStorage read. No cleanup function required.

goToVibeStep extraction

The de-dup lands here as a side-effect — onContinue and onSkip now share the same closure, so the user-scoped key is written in one place instead of two. Less drift risk going forward.

CI — 7/7 green. ✅

@vex-assistant-bot
Copy link
Copy Markdown
Contributor

@codex review
@devin review this PR

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 3 additional findings.

Open in Devin Review

@ashleeradka ashleeradka merged commit 59bbaf6 into main May 21, 2026
7 checks passed
@ashleeradka ashleeradka deleted the ashlee/lum-1763-followup-user-scope-prechat-screen branch May 21, 2026 02:32
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38629ce4fa

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +87 to +88
const saved = sessionStorage.getItem(screenStorageKey);
if (saved === "1") setScreen(1);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Reset screen for users without a saved native prechat step

When screenStorageKey changes, this effect only updates state if the new key stores "1". If user A was on screen === 1 and user B logs in without a saved key, screen stays at 1 in memory, so user B can still land on the vibe step despite having no persisted progress. This can happen whenever the component remains mounted across an auth identity swap (the exact scenario this change is targeting). The restore path should explicitly set screen back to 0 when no saved value exists for the active user key.

Useful? React with 👍 / 👎.

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