Skip to content

feat: Scope oauth tokens by org#2364

Open
charlesvien wants to merge 4 commits into
mainfrom
05-25-auth_org_keyed_map
Open

feat: Scope oauth tokens by org#2364
charlesvien wants to merge 4 commits into
mainfrom
05-25-auth_org_keyed_map

Conversation

@charlesvien
Copy link
Copy Markdown
Member

@charlesvien charlesvien commented May 25, 2026

Problem

Multi-org users can only see and access projects from their current PostHog organization. The renderer derives projects from currentUser.organization.teams, which only contains the active org, so switching to or paying for other orgs requires leaving the app.

Changes

  1. Replace OAuth scoped_teams with org-scoped tokens and a orgProjectsMap: Record<orgId, {orgName, projects}> on AuthState
  2. Build the map in the main process via one /api/organizations/{org_id}/projects/ per scoped org during session bootstrap
  3. Add auth.switchOrg tRPC that PATCHes /api/users/@me/ and remembers lastSelectedProjectId per org
  4. Rewrite useProjects to derive from the map only, removing the useCurrentUser dependency and the project-info N+1
  5. Bump OAUTH_SCOPE_VERSION 4 to 5 so existing users re-auth into org-scoped tokens
  6. Unify the currentUser query key between authStore.syncAuthState and useCurrentUser

How did you test this?

manually

Publish to changelog?

no

Copy link
Copy Markdown
Member Author

charlesvien commented May 25, 2026

@charlesvien charlesvien changed the title scope auth tokens by org with project map feat: scope auth tokens by org with project map May 25, 2026
@charlesvien charlesvien changed the title feat: scope auth tokens by org with project map feat: Scope oauth tokens by org with project map May 25, 2026
@charlesvien charlesvien changed the title feat: Scope oauth tokens by org with project map feat: Scope oauth tokens by org May 25, 2026
@charlesvien charlesvien marked this pull request as ready for review May 26, 2026 01:08
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 26, 2026

T-Rex T-Rex Logs

What T-Rex did

  • Created a focused auth-service repro suite for org-scoped token behavior and exercised login, project selection, and org switching against stubbed PostHog endpoints, covering duplicate project IDs across orgs, switching into an org with no projects, switching with post-login project changes, and stale org-project preferences; the generated run produced two failing repros and two passing checks.
  • Reviewed the renderer project and org selection behavior for the new auth state shape, including sidebar project selection, onboarding org/project controls, auth-store syncing, current-user query keys, and client project ID updates.
  • UI capture was not produced because the changed screens require a real authenticated multi-org PostHog account.
Artifacts

Verbose Vitest output for generated auth-service repros

  • Shows the full test-run output for the generated auth-service repros, including pass/fail counts.

Generated targeted auth-service repro test

  • Contains the TypeScript repro test used to validate org-scoped token behavior for the auth service.

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (1)

  1. apps/code/src/renderer/features/onboarding/components/ProjectSelectStep.tsx, line 96-99 (link)

    P1 Filter project choices

    The organization combobox can show one selected org, but the project combobox is built from the flat projects list across every org. A user can select org A and then pick a project from org B, leaving onboarding with mismatched org/project state. Filter sortedProjects by the selected/current org or include the target org in the project selection call.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/code/src/renderer/features/onboarding/components/ProjectSelectStep.tsx
    Line: 96-99
    
    Comment:
    **Filter project choices**
    
    The organization combobox can show one selected org, but the project combobox is built from the flat `projects` list across every org. A user can select org A and then pick a project from org B, leaving onboarding with mismatched org/project state. Filter `sortedProjects` by the selected/current org or include the target org in the project selection call.
    
    How can I resolve this? If you propose a fix, please make it concise.
Prompt To Fix All With AI
Fix the following 6 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 6
apps/code/src/main/services/auth/service.ts:245-253
**Switch server organization**

When a user selects a project from another org, this only changes the local session's `currentOrgId`. It does not send the `set_current_organization` PATCH that `switchOrg` sends, so PostHog Cloud still treats the user as being in the previous org while the renderer uses the new org/project. The next `getCurrentUser()` or org-scoped API call can then operate with a stale server-side organization.

### Issue 2 of 6
apps/code/src/main/services/auth/service.ts:245-247
**Disambiguate project orgs**

This resolves the org by scanning the map for the first matching project ID. If two orgs contain the same numeric project ID, selecting that project while currently in the second org flips `currentOrgId` to the first org in map order and persists the preference under that org. Prefer the current org when it contains the project, or pass the target `orgId` with the project selection.

### Issue 3 of 6
apps/code/src/main/services/auth/service.ts:296-300
**Refresh org projects**

After switching orgs, this chooses the project from the `orgProjectsMap` snapshot captured during login. If the target org gained or lost projects after bootstrap, those projects stay invisible and the fallback can select a stale first project until the user fully re-authenticates. Refresh the target org's projects after the PATCH succeeds and merge that result before choosing `currentProjectId`.

### Issue 4 of 6
apps/code/src/main/services/auth/service.ts:492-501
**Restore selected org**

`lastSelectedOrgId` is persisted, but session creation never reads it. When `selectedProjectId` is null or no longer valid, this falls back to the first project across all orgs, which can move a multi-org user back to whichever org appears first instead of the org they last selected. Use the stored org preference to choose the fallback org/project.

### Issue 5 of 6
apps/code/src/renderer/features/onboarding/components/ProjectSelectStep.tsx:96-99
**Filter project choices**

The organization combobox can show one selected org, but the project combobox is built from the flat `projects` list across every org. A user can select org A and then pick a project from org B, leaving onboarding with mismatched org/project state. Filter `sortedProjects` by the selected/current org or include the target org in the project selection call.

### Issue 6 of 6
apps/code/src/renderer/features/projects/hooks/useProjects.tsx:59-70
**Avoid cross-org auto-select**

This auto-selects `projects[0]` from the flattened list across all orgs whenever the current project is missing. If the active org has no projects, or its selected project disappears, this silently selects a project from another org and changes the user's scope without an explicit org switch. Prefer projects in `currentOrgId` and avoid cross-org auto-selection unless the org switch is intentional.

Reviews (1): Last reviewed commit: "fix selectProject orgId drift and route ..." | Re-trigger Greptile

Comment thread apps/code/src/main/services/auth/service.ts
Comment thread apps/code/src/main/services/auth/service.ts Outdated
Comment thread apps/code/src/main/services/auth/service.ts Outdated
Comment thread apps/code/src/main/services/auth/service.ts Outdated
Comment thread apps/code/src/renderer/features/projects/hooks/useProjects.tsx Outdated
@charlesvien charlesvien force-pushed the 05-25-auth_org_keyed_map branch from c8e3d0e to 1382e6f Compare May 26, 2026 01:48
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