feat(workspaces): add Mode B workspace switcher - #36
Merged
Conversation
Mode B Phase 2: adds a top-bar TeamSwitcher that lets a user move between their personal workspace (team_id: null) and any team they belong to, backed by the existing auth-service POST /auth/switch-team. - backend: routes_auth_proxy.py gains a pure relay for /auth/switch-team (same _proxy_to_auth pattern as every other route in this file; this service never inspects or trusts team_id). - frontend: auth.ts adds SessionUser.teamId/teamRole and switchTeam(), which persists the reissued access token and re-validates the session before the caller may reload -- never a locally-computed team_id, no X-Team-Id/X-Workspace-Id header. - frontend: new TeamSwitcher.tsx/test.tsx, wired into TopAppBar. Rebased onto main (PR #35, Team Management v0.8.0 Step 5); two test fixtures (TeamSwitcher.test.tsx's Team mocks, TeamMembersPanel.test.tsx's SessionUser mock) updated to match the interfaces both branches now share -- no functional changes to Step 5's own implementation. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.
Mode B Phase 2 — Workspace Switcher
Adds the top-bar workspace switcher: a user can move between their personal workspace and any team they belong to, entirely through the existing auth-service authority.
What this does
POST /auth/switch-teamroute inroutes_auth_proxy.pyis a pure relay (_proxy_to_auth), identical in shape to every other route in this file. Control-center never inspects or truststeam_iditself.team_idis resolved on the auth-service side from the presented token's ownsubclaim, with org-membership and team-membership independently re-checked on every switch. Control-center only relays the request/response.team_id: null. Treated as a real, meaningful state end-to-end (not a sentinel), including in the newswitchTeam(teamId: number | null)client function.switchTeam()persists the reissued access token, then callsvalidateSession()on it, and only resolves successfully once that validation succeeds.TeamSwitcher.tsxcallswindow.location.reload()only afterswitchTeam()resolves.X-Team-Id/X-Workspace-Idmechanism. The only place client intent is expressed is theteam_idfield in the/auth/switch-teamrequest body; there is a dedicated regression test asserting neither header is ever sent.TeamSwitcher.tsxreadsorgId/userId/teamIdonly from the authenticatedSessionUserand useslistTeams()purely for display filtering — the server's own membership re-check on/auth/switch-teamis the only authority on whether a switch is allowed.SessionUsergainsteamId/teamRole(nullable, mirrors the existingorgId/orgRolesshape).TeamSwitcheris wired intoTopAppBarnext to the existing (placeholder)OrgSelector.Rebase note
This branch had zero commits unique from its fork point, so bringing it onto current
main(PR #35, Team Management v0.8.0 Step 5) was a fast-forward, not a replay — the implementation diff is byte-for-byte identical before and after. The only adjustment needed was mechanical fixture updates required by interfaces the two branches both extended independently:TeamSwitcher.test.tsx'sTeammocks gaineddescription/created_by_user_id(added by PR feat(teams): Team Management v0.8.0 Step 5 — Control Center UI #35'sTeaminterface).TeamMembersPanel.test.tsxSessionUsermock gainedteamId/teamRole(added by this branch).No functional change to PR #35's Step 5 implementation.
Verification
Backend tests were run with
PYTHONPATHpointed at this worktree's ownbackend/srcto avoid a known editable-install shadowing issue wherecontrol_centercan resolve to a different checkout'ssrc/instead of the one under test.🤖 Generated with Claude Code