Repository navigation
Conversation
camielvs
added this pull request to stack #2930
October 22, 2026 19:23
🎩 PreviewA preview build has been created at: |
2 of 4 tasks
camielvs
force-pushed
the
cvs/team-context
branch
from
October 22, 2026 20:12
93462fd to
1a4a152
Compare
1 of 3 tasks
The foundation for workspace secrets under team impersonation. Inside a project whose workspace maps to a team, secrets are managed and runs are submitted as that team by adding the backend's impersonation header to those specific requests. Nothing here sends the header yet or changes any screen; later changes in this stack draw on it. - `getTeamImpersonationHeaderName` reads the header name the host page injects as `window.__TANGLE_TEAM_IMPERSONATION__`. With none configured, as in an OSS deployment, every team lookup resolves to "none". - `teamRequestHeaders` is the one place the header is built. - `resolveTeamId` is the one place that knows a workspace names its team through `data.teamId`, the interim contract until the backend has a field. - `readTeamMemberships` is the one place that knows the `teams` map on `GET /api/users/me`, which is fetched without the header (with it, the response describes the team and carries no `teams`). - `fetchTeamIdentity` asks `/api/users/me` with the header. A team is only active when the backend answers as that team: the development backend ignores the header but still lists teams, and a `nobody` role passes impersonation with no access. `canWrite` comes from the permissions the backend returns rather than from role names. - `resolveTeam` decides the outcome from the lookups, and `useTeamForProjects` gathers them: none, resolving, active, not-member, unavailable, conflict (projects on different teams) or error. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
camielvs
force-pushed
the
cvs/team-context
branch
from
October 23, 2026 22:58
1a4a152 to
18c82f0
Compare
This branch has not been deployed
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.
Description
The first of three foundation PRs for workspace secrets under team impersonation. Inside a project whose workspace maps to a team, secrets are managed and runs are submitted as that team: the backend's impersonation header is added to those specific requests only, never globally. This PR decides which team, if any, a set of projects acts as. Nothing here sends the header or changes a screen yet.
getTeamImpersonationHeaderNamereads the header name the host page injects aswindow.__TANGLE_TEAM_IMPERSONATION__. With none configured, as in a default deployment, every team lookup resolves tononeand the app behaves exactly as today.teamRequestHeaders(teamId)is the one place the header is built. It returns{}without a configured header name or a team id.resolveTeamIdis the one place that knows a workspace names its team throughdata.teamId, the interim contract until the backend has a field for it.readTeamMembershipsis the one place that knows theteamsmap onGET /api/users/me. That map is fetched without the header; with it, the response describes the team and carries noteams.fetchTeamIdentityasks/api/users/mewith the header. A team only counts as active when the backend answers as that team. That's because the development backend ignores the header but still lists teams, and anobodyrole passes impersonation with no access.canWritecomes from the permissions the backend returns rather than from role names.resolveTeamturns the lookups into one outcome, anduseTeamForProjectsgathers them. The outcome is one ofnone,resolving,active,not-member,unavailable,conflict(projects on different teams) orerror.Related Issue and Pull requests
Type of Change
Line Breakdown
Checklist
Screenshots (if applicable)
None. There's no UI change.
Test Instructions
pnpm validate(format, lint, typecheck, knip) passes. No screen calls these hooks yet, so there's nothing to click through.Additional Comments
src/services/teamsis added toreact-compiler.config.js.useTeamForProjectsreads projects and workspaces through the existingProjectsQueryKeys/WorkspacesQueryKeyscaches and treats a deleted project as absent rather than as an error.🤖 Generated with Claude Code