Skip to content

feat(api): manage workspace members through the v2 API - #9852

Merged
waleedlatif1 merged 6 commits into
stagingfrom
feat/v2-workspace-member-management
Nov 10, 2026
Merged

waleedlatif1 merged 6 commits into
stagingfrom
feat/v2-workspace-member-management

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Adds PATCH /api/v2/workspaces/{workspaceId}/members/{userId} (change a member's role) and DELETE (remove a member, or leave), mirroring the v2 organization member routes
  • Both run the existing workspace permission and member-removal use cases, now admitted for personal API keys and OAuth tokens with api:write; workspace keys stay denied since they can never hold admin
  • Existing guards apply unchanged: owner and billing account stay admin, no self-demotion, org admins and SCIM-managed members are refused, the last admin cannot leave
  • v2 errors: non-members are 404 on both verbs, lock contention is 503 with Retry-After, removing an owner with no billing-account heir is 409, and SCIM refusals keep the SCIM_MANAGED_MEMBERSHIP code (internal UI routes respond exactly as before)
  • CLI: workspaces members list|update|remove; the shipped sim workspaces members spelling still lists
  • Regenerated OpenAPI, CLI API/docs, MCP operations, and the v2 route table

Type of Change

  • New feature

Testing

  • apps/sim/lib/workspaces/__integration__/members.integration.ts (17 passing) drives the real v2 handlers in-process against PostgreSQL with hashed personal/workspace keys and OAuth tokens; reverting the principal widening, scope, 404, 503, 409, and SCIM-code changes each turns its test red
  • manage-permissions.test.ts, remove-member.test.ts, public-queries.test.ts, CLI group-default.test.ts and reference tests
  • tsc on apps/sim; check:openapi, cli-api, cli-docs, mcp-operations, v2-route-table, route-verbs, principal-kind-parity, api-validation:strict, test-patterns, boundaries, source-conventions; biome

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing (new tests pass the test-audit authoring gate)
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

Add PATCH and DELETE /api/v2/workspaces/{workspaceId}/members/{userId},
backed by the existing permission-update and member-removal use cases.
Both operations now admit personal API keys and OAuth tokens with
api:write; workspace API keys stay refused.

PATCH returns the member exactly as the roster lists them, read before
the write so a committed change is never left unaudited. DELETE reports
whether leaving removed the organization membership.

A directory-managed member's refusal keeps its SCIM_MANAGED_MEMBERSHIP
code through the store's HTTP wrapper. The v2 member policy answers the
billing-account removal refusal as 409 and exhausted transaction
contention as 503 instead of 500.

The CLI gains `workspaces members update` and `workspaces members
remove`; the listing becomes `workspaces members list` and shows user ids.
Add a real-HTTP E2E script for the new member update and removal
endpoints, reporting to WORKSPACE_MEMBERS_E2E_REPORT_PATH: workspace-key
and api:read-only OAuth refusals, role and tenant denials, non-member
targets, self-demotion, protected owner/billing/org-admin roles, no-op
writes without audit, last-admin leave, the 409 owner removal, self-leave
with a personal key, input validation, and the key owner as audit actor.

The use-case test now refuses a workspace key, which the operations still
reject, rather than a personal key, which they now admit, and pins that a
coded directory refusal survives the store's HTTP wrapper.
…reSQL

Replace the running-app E2E script with an integration suite that drives
the real v2 member route handlers with hashed personal keys, a workspace
key, and OAuth tokens against PostgreSQL, including a SCIM-managed member.

Simplify the store-failure mapping with findCause and a status table, and
keep the store's HTTP error as the cause of a coded refusal so the internal
permissions route renders it exactly as before. Spread params and body in
the PATCH route like the organization member route, trim comments, and
list the renamed member commands in the Teammates settings section.
- Answer a role change for a non-member with 404 "Member not found", as
  the organization member route does, and drop the post-write re-read.
- Answer role-change contention with 503 and Retry-After, like removal;
  the internal route keeps its 409.
- Keep `sim workspaces members` listing members as the default
  subcommand of the new group.
- Correct the member route prose and the workspaceId parameter wording.
- Give each integration test its own fixture and cover contention.
@vercel

vercel Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docs Ready Ready Preview Nov 10, 2026 9:26pm UTC

Request Review

@greptile-apps

greptile-apps Bot commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[High impact] The changes appear safe to merge; no new actionable issues were found.

Summary

Adds v2 routes to change workspace member roles and remove members through the existing authorized use cases.

  • Workspace admins can change a member’s role through the v2 API.
  • Workspace members can leave, and admins can remove members, through the v2 API.
  • The CLI lists, updates, and removes workspace members.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  CLI[CLI or MCP] --> V2[v2 member routes]
  V2 --> Auth[Check caller and workspace access]
  Auth --> Update[Change member role]
  Auth --> Remove[Remove member or leave]
  Update --> Store[Existing workspace stores]
  Remove --> Store
  Store --> Audit[Record member changes]
Loading

Reviews (2) · Last reviewed commit: "fix(docs): keep the shipped workspaces m..." · Reviewed by Greptile

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Review completed against the latest diff

Turn on auto-fix | Re-trigger cubic

…e member update

- Pin the CLI reference heading for `sim workspaces members list` to the
  `#sim-workspaces-members` anchor it shipped under, through a reference-page
  counterpart of the existing legacy anchor map, and restore that heading in
  the docs compatibility baseline.
- Classify `updateWorkspaceMember` as non-destructive alongside
  `updateOrganizationMember`.
- Cover an inherited organization admin with no grant row: PATCH answers the
  documented 400 for every requested role and writes nothing.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cubic-dev-ai review this PR

@cubic-dev-ai

cubic-dev-ai Bot commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

@cubic-dev-ai review this PR

@waleedlatif1 I have started the AI code review. It will take a few minutes to complete.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 29 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@waleedlatif1
waleedlatif1 merged commit 1174092 into staging Nov 10, 2026
83 checks passed
@waleedlatif1
waleedlatif1 deleted the feat/v2-workspace-member-management branch November 10, 2026 21:35

This branch was successfully deployed

1 active deployment
Preview — 84ac1111 Deployed Nov 10, 2026 by vercel[bot]
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