Skip to content

feat(workspaces): create shared workspaces, switch, manage members (D3) - #493

Merged
huyplb merged 1 commit into
mainfrom
feat/workspaces-shared
Oct 10, 2026
Merged

huyplb merged 1 commit into
mainfrom
feat/workspaces-shared

Conversation

@huyplb

@huyplb huyplb commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor

D3 of the workspaces plan. Stacked on #492 (D5) → #491 (D1).

What changes

  • API /api/workspaces: list with currentId and canCreate, create, select, rename, archive, members (admin adds an existing account directly; owners change roles and remove; anyone leaves). Contract table 119 → 127.
  • Permissions come from the role in the target workspace (workspace.members, workspace.settings), not from the workspace the request acts in. Non-members get 404.
  • Guards: a shared workspace always keeps an owner; a personal workspace keeps its account (can't leave, be removed, have its role changed, or be archived).
  • Who creates (D3): admins; everyone when the admin ticks Members can create workspaces on App users. Everyone always has their own.
  • Switching: the server keeps the current workspace (user_preferences.last_workspace_id), so switching is select + reload. Several feature APIs call fetch directly and would never send a header.
  • UI: the profile menu lists workspaces (current ✓), Workspace settings (name, members with roles, leave, archive), New workspace. Lazy-loaded, so the first load stays within budget.

Tests

  • workspace-directory.service.test.ts (14): creating (admin / setting / name rules), a shared connection visible to members and only there, viewer-in-workspace permissions, a viewer account owning a workspace gets no code cells, select, owner and personal guards, leave, archive. A/B: no role check, no owner guard and anyone-creates each fail.
  • Component tests for the menu and dialog, plus the admin switch.
  • New e2e workspaces.test.ts against the dev server: create from the menu → current; a connection saved there is absent from the personal workspace; rename via settings. It always restores the admin's own workspace.
  • Full suite 5985 passed; first load within the 170 KB budget.

Review

Left as is: tabs saved in the browser can name a connection from the previous workspace after switching; a non-owner account can't rename its own workspace.

🤖 Generated with Claude Code


Note

Medium Risk
Touches auth-scoped data isolation (connections per workspace), session workspace selection, and member/role enforcement—important for access control but heavily tested.

Overview
Adds shared workspaces end-to-end: a new /api/workspaces surface (list with currentId / canCreate, create, select, rename, archive, members) backed by WorkspaceDirectory, with permissions evaluated against the target workspace role and non-members getting 404.

The profile menu gains lazy-loaded Workspace UI: switch workspaces (select + full reload), create when allowed, and open Workspace settings for rename, member roles, leave, and archive. Admins get a Members can create workspaces toggle on the app-users policy screen, wired through membersCanCreateWorkspaces on /admin/policy.

Coverage includes server directory tests, component tests for the menu/dialog, an e2e workspaces.test.ts in the default runner, generated test IDs, and HTTP contract entries (119 → 127 routes).

Reviewed by Cursor Bugbot for commit e133993. Bugbot is set up for automated code reviews on this repo. Configure here.

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Test IDs

Added (22)

  • admin-policy-members-create
  • workspace-member-remove-{…}
  • workspace-member-role-{…}
  • workspace-member-{…}
  • workspace-menu
  • workspace-menu-create
  • workspace-menu-create-form
  • workspace-menu-create-name
  • workspace-menu-create-submit
  • workspace-menu-error
  • workspace-menu-item-{…}
  • workspace-menu-settings
  • workspace-settings
  • workspace-settings-archive
  • workspace-settings-close
  • workspace-settings-error
  • workspace-settings-leave
  • workspace-settings-members
  • workspace-settings-name
  • workspace-settings-rename
  • workspace-settings-rename-submit
  • workspace-settings-saved

{…} is a part filled in at run time. The full tree: docs/testing/TEST_IDS.md.

@cursor

cursor Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: f1eaecb9-b024-4c46-85f7-42f6d8ae33d4)

…ge members

D3 of the workspaces plan.

- /api/workspaces: list (with the current one), create, select, rename,
  archive, members (add directly as admin, change role, remove, leave).
- What a caller may do to a workspace comes from its role in that
  workspace. A workspace always keeps an owner; a personal workspace
  always keeps its account.
- Creating is for admins, or everyone when the admin turns on "Members
  can create workspaces" (App users).
- The current workspace is kept on the server (last selected), so
  switching is select + reload and every request, tab and CLI follow.
- Profile menu: workspace list, Workspace settings, New workspace.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@huyplb
huyplb force-pushed the feat/workspaces-shared branch from e86e756 to e133993 Compare October 10, 2026 04:27
@cursor

cursor Bot commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: db890e35-59fd-4610-b503-2c331f84f691)

@huyplb
huyplb merged commit ae3e0ab into main Oct 10, 2026
13 checks passed
@huyplb
huyplb deleted the feat/workspaces-shared branch October 10, 2026 04:31
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