You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Step 2 of phase 2 of the App.tsx decomposition — see #2129 for the phase, #2126 for the whole effort.
This is a stacked PR. Its branch is cut from step 1's (v2/chore/2129-use-session-ref, #2152) and its PR targets that branch, not v2/main, so the diff shows only this step and the order dependence is visible on the PR itself. GitHub retargets it to v2/main when step 1 merges. Do not land it before #2152.
Scope — useOAuthRecovery(session), ~560 lines
The largest single cluster and the one with the most subtle behavior:
step-up state, trySetPendingStepUp, the in-progress guards
Returns the banner state, the step-up state and handlers, and — critically — runWithCommandAuthRecovery, which step 4 wraps every command in. That is why step 4 cannot precede this one.
The oauthCallbackHandledRef / staleOAuthCheckedRef / oauthResumeUiAppliedRef / reauthResumeInProgressRef / stepUpAuthorizeInProgressRef guards are once-only latches guarding real re-entrancy, several of them there to survive StrictMode's effect replay. Move them with the cluster and do not "simplify" them.
resumePendingReauth needs to drive a reconnect, which step 3 owns. Inject it as a callback (onReconnect) rather than importing across — that keeps the direction one-way.
No behavior change.
Done when
useOAuthRecovery is its own hook, taking the sessionRef seam from step 1
≥90% on all four coverage dimensions, v8 ignore only for genuinely unreachable branches (StrictMode replay blocks are an accepted reason)
Activity
chore(web): address Copilot review on #2153
chore(web): extract App.tsx's OAuth recovery cluster into useOAuthRec…
chore(web): resolve the react-hooks findings the decomposition unmask…