fix(auth): Auto-recover project-less session after re-auth#2655
Merged
Conversation
Member
Author
This stack of pull requests is managed by Graphite. Learn more about stacking. |
2 tasks
|
React Doctor found no issues in the changed files. 🎉 Reviewed by React Doctor for commit |
There was a problem hiding this comment.
Gates denied this PR because it touches auth code (on the deny-list) and is classified as too complex for automated approval. The changes modify session persistence behavior (preserving prior selectedProjectId when null, skipping preference writes when no project is selected) and introduce a new async recovery loop — all in the auth service, which requires human review.
Contributor
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
packages/core/src/auth/auth.test.ts:873-971
**Reconnect and resume tests could be parameterised**
The "recovers on reconnect" and "recovers on resume" tests share the same arrange-and-assert skeleton — transient failure during login, switch to online, fire the recovery trigger, wait for `currentProjectId`. The only variation is the recovery trigger (`emitStatus(true)` vs `getResumeHandler()()`) and the expected restored project (84 vs 42, which itself follows from whether a prior session is seeded). Per the team's rule on preferring parameterised tests, an `it.each` table over `[{ trigger: emitStatus, expectId: 84, seed: true }, { trigger: getResumeHandler()(), expectId: 42, seed: false }]` would express the shared intent more clearly and make it cheaper to add a third trigger in the future.
### Issue 2 of 2
packages/core/src/auth/auth.test.ts:873-971
**Retry loop inside `doRefreshOrgProjects` has no multi-failure test**
`doRefreshOrgProjects` retries up to `ORG_RECOVERY_MAX_ATTEMPTS` (5) with exponential backoff. The new tests only exercise the first-attempt-succeeds path: connectivity is restored, recovery fires once, and the project is set. There is no test for "2 transient failures then success" within a single recovery window, nor for "all 5 attempts fail and the session stays project-less". Per the team's rule on retry-logic coverage, at least one test should drive multiple failures through the loop before letting the stub succeed, verifying that the session remains incomplete during retries and is committed only on the successful pass.
Reviews (1): Last reviewed commit: "auto-recover org projects after failed a..." | Re-trigger Greptile |
2 tasks
6e2fdfb to
975837d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
After the
OAUTH_SCOPE_VERSIONbump forced a re-authentication, a transient org/projects fetch failure (a network blip on a fresh re-auth) leaves the user authenticated but with no project selected (currentProjectId = null), and nothing recovers it. That single state silently cascades:twig-cloud-mode-toggleflag has no posthogprojectgroup to evaluate against)Reported by Gustavo, who got stuck on local/worktree-only after re-auth.
Changes
orgProjectsIncompleteonly for the transient caserefreshOrgProjects()that re-fetches orgs/projects and re-selects the project via the existingpickInitialProjectIdattemptSessionRecovery(connectivity-online + power-resume handlers)scoped_organizationsno-retry pathOnce
currentProjectIdis restored, the rest cascades back automatically (cloud sends, the cloud-mode flag via the re-set posthogprojectgroup, the seat/usage bar, and the task list), so no UI changes are needed.Related (adjacent angles of the same incident): #2594 (analytics feature-flag race hiding the cloud option) and #2647 (explicit OAuth scopes instead of
*).How did you test this?
pnpm --filter @posthog/core test— 31 auth tests pass (3 new recovery tests + existing suite, including the existing 4xx no-retry case)pnpm --filter @posthog/core typecheck— cleanbiome lint packages/core/src/auth/*— cleanNew unit tests fake a transient
/api/organizations/{id}/failure during re-auth and assert the session becomes authenticated-but-project-less, then recovers and restores the previous project on reconnect and on resume; and that an emptyscoped_organizationsdoes not trigger a retry loop. No manual app run.Automatic notifications