Repository navigation
feat(workspaces): every row belongs to a workspace, every account has one (D5) - #492
Merged
Merged
Conversation
Contributor
Bugbot couldn't run - usage limit reachedBugbot 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: ce2b8a9b-f689-49ac-be3f-18f39577e540) |
This was referenced Oct 9, 2026
… one D5 of docs/plans/2026-10-09-workspaces-and-admin-policy.md, with no visible change: each account gets a personal workspace, and its role there mirrors the account role, so nobody can do anything new. - Migrations 28 (workspaces, members, invites), 29 (workspace_id on connections, secrets, cloud credentials, Lokee databases, migration and data-migrate runs) and 30 (unique keys per workspace, one personal workspace per account). - Services take a WorkspaceScope instead of a user id; authGuard resolves X-Fox-Workspace (unknown or not a member: 404). - Permissions = install keys from the account role + workspace keys from the workspace role; code cells, workflows, Git and user management stay install keys. - backfillWorkspaces runs at every start and moves rows without a workspace into their author's. - Route deps that were typed any are typed, so the compiler finds every call site. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
huyplb
force-pushed
the
feat/workspaces-foundation
branch
from
October 10, 2026 04:23
94b7577 to
fd40ee9
Compare
Contributor
Bugbot couldn't run - usage limit reachedBugbot 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: e5e904ef-1e4d-4535-abb1-2487216e79d4) |
| async (req: AppRequest, res: FastifyReply) => { | ||
| try { | ||
| const userId = (req as AuthedRequest).userId!; | ||
| const scope = scopeOf(req as AuthedRequest)!; |
| async (req: AppRequest, res: FastifyReply) => { | ||
| try { | ||
| const userId = (req as AuthedRequest).userId!; | ||
| const scope = scopeOf(req as AuthedRequest)!; |
| requirePermissions('editor.access'), | ||
| async (req: AppRequest, res: FastifyReply) => { | ||
| const userId = (req as AuthedRequest).userId!; | ||
| const scope = scopeOf(req as AuthedRequest)!; |
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.
D5 of the workspaces plan. Stacked on #491 (D1); retarget to
mainonce that merges.No visible change: every account gets a personal workspace and its role there mirrors the account role (admin = owner), so effective permissions are exactly what they were. Deviation from the plan: the plan made new accounts owners of their own workspace; mirroring the account role keeps this PR permission-neutral, and D3 decides how inviting into one's own workspace works.
What changes
workspaces,workspace_members,workspace_invites;workspace_idon the six workspace-owned tables; unique keys re-keyed from author to workspace (secret names, cloud credential names, Lokee database identity) and one personal workspace per account.WorkspaceScope(platform/http/scope.ts).authGuardresolvesX-Fox-Workspace→ last used → personal; a workspace the account is not in answers 404./api/auth/mereturns the workspace and its permissions.INSTALL_PERMISSIONS(code cells, workflows, Git, user management,workspace.create) come only from the account role; the rest only from the workspace role. New keysworkspace.members/workspace.settings(owner, plus a one-time grant to roles that deploy migrations) andworkspace.create(admin).backfillWorkspacesruns at every start: personal workspace for each account without one, and rows without a workspace move to their author's. Verified on a dev DB with 949 connections: every account kept exactly its own.anyare now typed. Several were, which would have let a misseduserId → scopechange compile and fail at runtime as "not found".Tests
workspace.service.test.ts(17): personal workspaces + role sync, request resolution (404 not 403, last-used, archived), permissions per role, backfill, isolation for every scoped service (same author, two workspaces), unique keys.effectivePermissionstests; two live HTTP checks in the contract test (unknown workspace → 404;/mefallback).Review
Fixed: per-user unique indexes (migration 30), possible duplicate personal workspaces, the CLI following the browser's last workspace. Left: run-history pruning is now per workspace; a few extra metadata queries per request.
🤖 Generated with Claude Code
Note
High Risk
Large metadata migration and auth/scoping changes affect how all workspace-owned data is read and written; incorrect backfill or scope resolution could leak or hide data across workspaces.
Overview
Introduces workspaces as the tenancy boundary for connections, secrets, migration history, Lokee schema history, and related metadata. Every account gets a personal workspace (with role mirrored from the account role so effective permissions stay the same for this release), and existing rows are backfilled onto the author’s workspace at startup.
Server: DB migrations add
workspaces/ members / invites,workspace_idon scoped tables, and workspace-scoped unique keys (secret names, cloud cred names, Lokee fingerprints). Protected APIs resolve the active workspace fromX-Fox-Workspace, last-used preference, or personal default; workspaces the user cannot access return 404./api/auth/mereturns the active workspace and workspace-filtered permissions (install-level vs workspace-level split). Connection, secrets, history, Lokee, data-migrate, file import, git, and access routes now passWorkspaceScopeinstead ofuserIdinto stores.CLI/TUI:
getContext()always uses the install owner’s personal workspace so the CLI does not follow the browser’s last-selected workspace; commands and tests updated accordingly.Reviewed by Cursor Bugbot for commit fd40ee9. Bugbot is set up for automated code reviews on this repo. Configure here.