Skip to content

fix(auth): Auto-recover project-less session after re-auth#2655

Merged
charlesvien merged 4 commits into
mainfrom
fix/auth-recover-projectless-session
Jun 13, 2026
Merged

fix(auth): Auto-recover project-less session after re-auth#2655
charlesvien merged 4 commits into
mainfrom
fix/auth-recover-projectless-session

Conversation

@charlesvien

@charlesvien charlesvien commented Jun 13, 2026

Copy link
Copy Markdown
Member

Problem

After the OAUTH_SCOPE_VERSION bump 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:

  • cloud sends fail with "Authentication required for cloud commands"
  • the Cloud workspace mode disappears (the twig-cloud-mode-toggle flag has no posthog project group to evaluate against)
  • the billing/usage bar goes blank
  • the task list empties

Reported by Gustavo, who got stuck on local/worktree-only after re-auth.

Changes

  1. Distinguish transient (network/5xx) org-fetch failures from permanent (4xx) ones, and flag the session orgProjectsIncomplete only for the transient case
  2. Add a bounded, deduped refreshOrgProjects() that re-fetches orgs/projects and re-selects the project via the existing pickInitialProjectId
  3. Trigger recovery after an incomplete sync and from attemptSessionRecovery (connectivity-online + power-resume handlers)
  4. Preserve the last-selected project across a project-less sync so recovery restores the exact project the user had
  5. Tests for recover-and-restore on reconnect, recover on resume, and the empty-scoped_organizations no-retry path

Once currentProjectId is restored, the rest cascades back automatically (cloud sends, the cloud-mode flag via the re-set posthog project group, 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 — clean
  • biome lint packages/core/src/auth/* — clean

New 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 empty scoped_organizations does not trigger a retry loop. No manual app run.

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

charlesvien commented Jun 13, 2026

Copy link
Copy Markdown
Member Author

@github-actions

github-actions Bot commented Jun 13, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 210a0ae.

@charlesvien charlesvien changed the title auto-recover org projects after failed auth fetch fix(auth): Auto-recover project-less session after re-auth Jun 13, 2026
@charlesvien charlesvien marked this pull request as ready for review June 13, 2026 05:33
@charlesvien charlesvien added the Stamphog This will request an autostamp by stamphog on small changes label Jun 13, 2026

@stamphog stamphog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

@stamphog stamphog Bot removed the Stamphog This will request an autostamp by stamphog on small changes label Jun 13, 2026
@greptile-apps

greptile-apps Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor
Prompt To Fix All With AI
Fix 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

Comment thread packages/core/src/auth/auth.test.ts
Comment thread packages/core/src/auth/auth.test.ts
@charlesvien charlesvien force-pushed the fix/auth-recover-projectless-session branch from 6e2fdfb to 975837d Compare June 13, 2026 06:26
Base automatically changed from fix/agent-session-init-timeout to main June 13, 2026 07:14
@charlesvien charlesvien merged commit a9718c2 into main Jun 13, 2026
20 checks passed
@charlesvien charlesvien deleted the fix/auth-recover-projectless-session branch June 13, 2026 07:16
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.

1 participant