fix(auth): use scoped_teams when scoped_organizations is empty#2490
fix(auth): use scoped_teams when scoped_organizations is empty#2490raquelmsmith wants to merge 1 commit into
Conversation
…zations is empty PostHog returns `scoped_teams` instead of `scoped_organizations` when the OAuth grant is project-level. Before this, project-level tokens produced an empty orgProjectsMap, leaving currentProjectId null and surfacing "no projects available" in the switcher. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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
apps/code/src/main/services/auth/service.ts:635-640
**Project-scoped token may always yield "(unknown)" org name**
`fetchOrgWithProjects` calls `/api/organizations/${orgId}/` using the same access token. A project-scoped OAuth grant is unlikely to carry permission to read the org endpoint, so `res.ok` will be `false`, the function returns `null`, and every project-scoped login will display `"(unknown)"` as the org name in the switcher. The PR test plan specifically checks that the org name is visible — worth confirming the token does have org-read access, or falling back to the project's own `organization` ID as the display label when the org fetch fails.
### Issue 2 of 2
apps/code/src/main/services/auth/service.ts:632-643
**Superfluous full-org fetch: only `orgName` is consumed**
`fetchOrgWithProjects` issues a network request to `/api/organizations/${orgId}/` and parses the entire `teams` array — all of which is discarded, since `projects` in the returned tuple comes from `projectsByOrg` (the scoped team metas), not from the org call. Consider extracting a thin `fetchOrgName` helper that skips the `teams` mapping, or at least skip the call entirely when the org ID can be used as a display label. This follows simplicity rule 4 (no superfluous parts) and avoids the unnecessary allocation on each login.
Reviews (1): Last reviewed commit: "fix(auth): build org/project map from sc..." | Re-trigger Greptile |
| const org = await this.fetchOrgWithProjects( | ||
| accessToken, | ||
| cloudRegion, | ||
| orgId, | ||
| ); | ||
| return [orgId, { orgName: org?.orgName ?? "(unknown)", projects }]; |
There was a problem hiding this comment.
Project-scoped token may always yield "(unknown)" org name
fetchOrgWithProjects calls /api/organizations/${orgId}/ using the same access token. A project-scoped OAuth grant is unlikely to carry permission to read the org endpoint, so res.ok will be false, the function returns null, and every project-scoped login will display "(unknown)" as the org name in the switcher. The PR test plan specifically checks that the org name is visible — worth confirming the token does have org-read access, or falling back to the project's own organization ID as the display label when the org fetch fails.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/main/services/auth/service.ts
Line: 635-640
Comment:
**Project-scoped token may always yield "(unknown)" org name**
`fetchOrgWithProjects` calls `/api/organizations/${orgId}/` using the same access token. A project-scoped OAuth grant is unlikely to carry permission to read the org endpoint, so `res.ok` will be `false`, the function returns `null`, and every project-scoped login will display `"(unknown)"` as the org name in the switcher. The PR test plan specifically checks that the org name is visible — worth confirming the token does have org-read access, or falling back to the project's own `organization` ID as the display label when the org fetch fails.
How can I resolve this? If you propose a fix, please make it concise.| const entries = await Promise.all( | ||
| Array.from(projectsByOrg.entries()).map( | ||
| async ([orgId, projects]): Promise<[string, OrgProjects]> => { | ||
| const org = await this.fetchOrgWithProjects( | ||
| accessToken, | ||
| cloudRegion, | ||
| orgId, | ||
| ); | ||
| return [orgId, { orgName: org?.orgName ?? "(unknown)", projects }]; | ||
| }, | ||
| ), | ||
| ); |
There was a problem hiding this comment.
Superfluous full-org fetch: only
orgName is consumed
fetchOrgWithProjects issues a network request to /api/organizations/${orgId}/ and parses the entire teams array — all of which is discarded, since projects in the returned tuple comes from projectsByOrg (the scoped team metas), not from the org call. Consider extracting a thin fetchOrgName helper that skips the teams mapping, or at least skip the call entirely when the org ID can be used as a display label. This follows simplicity rule 4 (no superfluous parts) and avoids the unnecessary allocation on each login.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/main/services/auth/service.ts
Line: 632-643
Comment:
**Superfluous full-org fetch: only `orgName` is consumed**
`fetchOrgWithProjects` issues a network request to `/api/organizations/${orgId}/` and parses the entire `teams` array — all of which is discarded, since `projects` in the returned tuple comes from `projectsByOrg` (the scoped team metas), not from the org call. Consider extracting a thin `fetchOrgName` helper that skips the `teams` mapping, or at least skip the call entirely when the org ID can be used as a display label. This follows simplicity rule 4 (no superfluous parts) and avoids the unnecessary allocation on each login.
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
human description
I could not get an agent to run when using local PostHog. After an hour with claude it tells me this is the fix - and now it's working locally.
Summary
scoped_organizationsis empty when the OAuth grant is project-level — PostHog returnsscoped_teamsinstead. The old code only consultedscoped_organizations, so project-scoped logins ended up with an emptyorgProjectsMap, nocurrentProjectId, and "No projects available" in the switcher (downstream:Missing auth credentialsand the agent failing to start a session).scoped_teamsto the OAuth token Zod schema and, whenscoped_organizationsis empty, build the org/project map fromscoped_teams: fetch each project via/api/projects/<id>/, group byorganization, then fetch each org's name. Only the teams the user actually authorized are included.scoped_organizationspath still wins when populated.Test plan
Missing auth credentialsin~/.posthog-code/logs-dev/main.log).🤖 Generated with Claude Code