fix(workspaces): address review comments across stacked PRs#988
Merged
raivieiraadriano92 merged 38 commits intoJun 16, 2026
Conversation
…on workspace switch
… surface a screen
Semgrep Security ScanNo security issues found. |
ital0
requested changes
Jun 16, 2026
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bd4a338. Configure here.
ital0
requested changes
Jun 16, 2026
ital0
approved these changes
Jun 16, 2026
24cc392
into
raivieiraadriano92/thu-556-settings-workspace-permissions-manage_members-change_roles
10 of 17 checks passed
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
…D enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
…pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
…plicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
* feat(THU-552): promote pending membership to active on email match * feat(THU-552): createSharedWorkspace DAL function * feat(THU-552): useCanCreateWorkspace hook * feat(THU-552): EmailChipInput component * feat(THU-552): CreateWorkspaceModal component * feat(THU-552): Create workspace button in sidebar selector footer * feat(THU-552): seed defaults into newly-created shared workspace * fix(THU-552): scope cleanupRemovedDefaults to a workspace * feat(THU-552): split create + invite into two modals, single Create CTA * feat(THU-552): workspace selector design polish * fix(THU-552): rename SCREAMING_SNAKE constants to camelCase * feat(THU-554): Settings → Workspace → General (rename, slug, icon, duplicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
…pace (#961) * feat(THU-551): reactive active-workspace + URL helpers * feat(THU-551): useWorkspacesQuery hook + DAL test * feat(THU-551): WorkspaceMembershipGate + live membership query * feat(THU-551): mount workspace routes under /w/:workspaceId prefix * feat(THU-551): workspace selector in sidebar header * feat(THU-551): thread workspace prefix through navigation call sites * feat(THU-552): create workspace modal — name + invite by email (#965) * feat(THU-552): promote pending membership to active on email match * feat(THU-552): createSharedWorkspace DAL function * feat(THU-552): useCanCreateWorkspace hook * feat(THU-552): EmailChipInput component * feat(THU-552): CreateWorkspaceModal component * feat(THU-552): Create workspace button in sidebar selector footer * feat(THU-552): seed defaults into newly-created shared workspace * fix(THU-552): scope cleanupRemovedDefaults to a workspace * feat(THU-552): split create + invite into two modals, single Create CTA * feat(THU-552): workspace selector design polish * fix(THU-552): rename SCREAMING_SNAKE constants to camelCase * feat(THU-554): Settings → Workspace → General (rename, slug, icon, duplicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
…vity (#958) * feat(THU-553): polish mode-picker UI — layout, selection state, and connectivity * fix(THU-553): DI for mode-picker, drop mock.module('@/lib/http') leakage * feat(THU-551): workspace selector in sidebar + URL-based active workspace (#961) * feat(THU-551): reactive active-workspace + URL helpers * feat(THU-551): useWorkspacesQuery hook + DAL test * feat(THU-551): WorkspaceMembershipGate + live membership query * feat(THU-551): mount workspace routes under /w/:workspaceId prefix * feat(THU-551): workspace selector in sidebar header * feat(THU-551): thread workspace prefix through navigation call sites * feat(THU-552): create workspace modal — name + invite by email (#965) * feat(THU-552): promote pending membership to active on email match * feat(THU-552): createSharedWorkspace DAL function * feat(THU-552): useCanCreateWorkspace hook * feat(THU-552): EmailChipInput component * feat(THU-552): CreateWorkspaceModal component * feat(THU-552): Create workspace button in sidebar selector footer * feat(THU-552): seed defaults into newly-created shared workspace * fix(THU-552): scope cleanupRemovedDefaults to a workspace * feat(THU-552): split create + invite into two modals, single Create CTA * feat(THU-552): workspace selector design polish * fix(THU-552): rename SCREAMING_SNAKE constants to camelCase * feat(THU-554): Settings → Workspace → General (rename, slug, icon, duplicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
* feat(THU-578): scope all FE DAL methods to active workspaceId * fix(THU-578): seed trust domain in eval CLI + scope model-profile upsert by workspace * fix(THU-578): retry hydration when workspaceId resolves after WorkspaceGate * fix(THU-578): evict stale chat session on workspace switch * fix(THU-578): scope prompt join in getTriggerPromptForThread to active workspace * fix(THU-578): fix random test failures from workspaceId resolution races * feat(THU-553): mode picker UI — layout, selection state, and connectivity (#958) * feat(THU-553): polish mode-picker UI — layout, selection state, and connectivity * fix(THU-553): DI for mode-picker, drop mock.module('@/lib/http') leakage * feat(THU-551): workspace selector in sidebar + URL-based active workspace (#961) * feat(THU-551): reactive active-workspace + URL helpers * feat(THU-551): useWorkspacesQuery hook + DAL test * feat(THU-551): WorkspaceMembershipGate + live membership query * feat(THU-551): mount workspace routes under /w/:workspaceId prefix * feat(THU-551): workspace selector in sidebar header * feat(THU-551): thread workspace prefix through navigation call sites * feat(THU-552): create workspace modal — name + invite by email (#965) * feat(THU-552): promote pending membership to active on email match * feat(THU-552): createSharedWorkspace DAL function * feat(THU-552): useCanCreateWorkspace hook * feat(THU-552): EmailChipInput component * feat(THU-552): CreateWorkspaceModal component * feat(THU-552): Create workspace button in sidebar selector footer * feat(THU-552): seed defaults into newly-created shared workspace * fix(THU-552): scope cleanupRemovedDefaults to a workspace * feat(THU-552): split create + invite into two modals, single Create CTA * feat(THU-552): workspace selector design polish * fix(THU-552): rename SCREAMING_SNAKE constants to camelCase * feat(THU-554): Settings → Workspace → General (rename, slug, icon, duplicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
* feat(THU-550): BE workspaces tables + post-create bootstrap hook * feat(THU-550): PowerSync upload handler factory + workspace handlers * feat(THU-550): workspace_id on scoped tables + sync rules + ws handler * feat(THU-550): encrypt workspaces.name * feat(THU-550): shared deterministic personal-workspace id helpers * feat(THU-550): BE — FE-owned personal workspace creation * feat(THU-550): FE — workspace-aware DAL + post-auth bootstrap + gate * fix(THU-550): log permanently rejected upload ops * fix(THU-550): pin workspace_id in PATCH/DELETE WHERE clause * fix(THU-550): scope reconcile-defaults lookups and updates by workspace_id * fix(THU-550): force personal workspace name + shared workspace admin bootstrap * fix(THU-550): throw bootstrap error + update stale 400 upload test assertions * fix(THU-550): add workspaceId to model profile defaults + fix getSystemTinfoilClient cloud URL * fix(THU-550): restore BE test isolation broken by upload handler transactions * ci(THU-550): install root deps before BE type-check (shared/ uses uuid) * feat(THU-578): scope all FE DAL methods to active workspaceId (#951) * feat(THU-578): scope all FE DAL methods to active workspaceId * fix(THU-578): seed trust domain in eval CLI + scope model-profile upsert by workspace * fix(THU-578): retry hydration when workspaceId resolves after WorkspaceGate * fix(THU-578): evict stale chat session on workspace switch * fix(THU-578): scope prompt join in getTriggerPromptForThread to active workspace * fix(THU-578): fix random test failures from workspaceId resolution races * feat(THU-553): mode picker UI — layout, selection state, and connectivity (#958) * feat(THU-553): polish mode-picker UI — layout, selection state, and connectivity * fix(THU-553): DI for mode-picker, drop mock.module('@/lib/http') leakage * feat(THU-551): workspace selector in sidebar + URL-based active workspace (#961) * feat(THU-551): reactive active-workspace + URL helpers * feat(THU-551): useWorkspacesQuery hook + DAL test * feat(THU-551): WorkspaceMembershipGate + live membership query * feat(THU-551): mount workspace routes under /w/:workspaceId prefix * feat(THU-551): workspace selector in sidebar header * feat(THU-551): thread workspace prefix through navigation call sites * feat(THU-552): create workspace modal — name + invite by email (#965) * feat(THU-552): promote pending membership to active on email match * feat(THU-552): createSharedWorkspace DAL function * feat(THU-552): useCanCreateWorkspace hook * feat(THU-552): EmailChipInput component * feat(THU-552): CreateWorkspaceModal component * feat(THU-552): Create workspace button in sidebar selector footer * feat(THU-552): seed defaults into newly-created shared workspace * fix(THU-552): scope cleanupRemovedDefaults to a workspace * feat(THU-552): split create + invite into two modals, single Create CTA * feat(THU-552): workspace selector design polish * fix(THU-552): rename SCREAMING_SNAKE constants to camelCase * feat(THU-554): Settings → Workspace → General (rename, slug, icon, duplicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
raivieiraadriano92
added a commit
that referenced
this pull request
Jun 16, 2026
* feat(THU-549): serverId + extended /v1/config payload * feat(THU-549): trust-domain registry + namespaced auth/device/keys * feat(THU-549): boot env vars + trust-domain decision tree * feat(THU-549): scope DB filename by trust domain + lifecycle broadcast * feat(THU-549): logout = unconditional wipe * feat(THU-549): scope cloud URL by active server * refactor(THU-549): collapse registry actions into activateServer/activateStandalone * feat(THU-549): persist per-server session on ServerEntry + wire mirror * refactor(THU-549): drop unused db-reopened event + subscribeDbLifecycle * refactor(THU-549): extract shared sync-worker-name format * fix(THU-549): pin SERVER_ID for e2e backends * fix(THU-549): address PR review — timeout, Tauri OPFS, logout loading state, test SERVER_ID, auth-token let * fix(THU-549): wipe IDB databases on logout + fix SSO redirect race + delete E2EE keys IDB * fix(THU-549): use getActiveCloudUrl in getSystemTinfoilClient * fix(THU-550): fix BE/FE tests broken by THU-549 trust-domain rebase * feat(THU-550): Workspaces data layer (#944) * feat(THU-550): BE workspaces tables + post-create bootstrap hook * feat(THU-550): PowerSync upload handler factory + workspace handlers * feat(THU-550): workspace_id on scoped tables + sync rules + ws handler * feat(THU-550): encrypt workspaces.name * feat(THU-550): shared deterministic personal-workspace id helpers * feat(THU-550): BE — FE-owned personal workspace creation * feat(THU-550): FE — workspace-aware DAL + post-auth bootstrap + gate * fix(THU-550): log permanently rejected upload ops * fix(THU-550): pin workspace_id in PATCH/DELETE WHERE clause * fix(THU-550): scope reconcile-defaults lookups and updates by workspace_id * fix(THU-550): force personal workspace name + shared workspace admin bootstrap * fix(THU-550): throw bootstrap error + update stale 400 upload test assertions * fix(THU-550): add workspaceId to model profile defaults + fix getSystemTinfoilClient cloud URL * fix(THU-550): restore BE test isolation broken by upload handler transactions * ci(THU-550): install root deps before BE type-check (shared/ uses uuid) * feat(THU-578): scope all FE DAL methods to active workspaceId (#951) * feat(THU-578): scope all FE DAL methods to active workspaceId * fix(THU-578): seed trust domain in eval CLI + scope model-profile upsert by workspace * fix(THU-578): retry hydration when workspaceId resolves after WorkspaceGate * fix(THU-578): evict stale chat session on workspace switch * fix(THU-578): scope prompt join in getTriggerPromptForThread to active workspace * fix(THU-578): fix random test failures from workspaceId resolution races * feat(THU-553): mode picker UI — layout, selection state, and connectivity (#958) * feat(THU-553): polish mode-picker UI — layout, selection state, and connectivity * fix(THU-553): DI for mode-picker, drop mock.module('@/lib/http') leakage * feat(THU-551): workspace selector in sidebar + URL-based active workspace (#961) * feat(THU-551): reactive active-workspace + URL helpers * feat(THU-551): useWorkspacesQuery hook + DAL test * feat(THU-551): WorkspaceMembershipGate + live membership query * feat(THU-551): mount workspace routes under /w/:workspaceId prefix * feat(THU-551): workspace selector in sidebar header * feat(THU-551): thread workspace prefix through navigation call sites * feat(THU-552): create workspace modal — name + invite by email (#965) * feat(THU-552): promote pending membership to active on email match * feat(THU-552): createSharedWorkspace DAL function * feat(THU-552): useCanCreateWorkspace hook * feat(THU-552): EmailChipInput component * feat(THU-552): CreateWorkspaceModal component * feat(THU-552): Create workspace button in sidebar selector footer * feat(THU-552): seed defaults into newly-created shared workspace * fix(THU-552): scope cleanupRemovedDefaults to a workspace * feat(THU-552): split create + invite into two modals, single Create CTA * feat(THU-552): workspace selector design polish * fix(THU-552): rename SCREAMING_SNAKE constants to camelCase * feat(THU-554): Settings → Workspace → General (rename, slug, icon, duplicate) (#971) * fix(THU-554): align PageHeader actions with content padding * feat(THU-554): allow personal workspace rename via upload handler * feat(THU-554): updateWorkspaceName DAL, default name, createdAt stamps * feat(THU-554): useActiveWorkspaceMembership hook * feat(THU-554): split settings sidebar into Account Settings and Workspace groups * feat(THU-554): Workspace Settings page with autosave rename * feat(THU-554): add slug + icon columns to workspaces * feat(THU-554): workspace slug input with auto-derive from name * feat(THU-554): workspace icon picker (emoji or image upload) * feat(THU-554): render workspace icon in the sidebar selector * feat(THU-554): share WorkspaceFormFields between settings and create modal * feat(THU-554): duplicate workspace action * feat(THU-555): Settings → Workspace → Members (add / remove / role / pending) (#974) * feat(THU-555): add user_name/user_email to workspace_memberships * feat(THU-555): enrich membership upload handler with user display info * feat(THU-555): propagate user name/email changes to memberships * feat(THU-555): mirror userName/userEmail on FE workspace_memberships * feat(THU-555): reactive members + pending queries * feat(THU-555): membership mutation DAL * feat(THU-555): useWorkspacePermission hook * feat(THU-555): RequireWorkspacePermission route wrapper * feat(THU-555): Members page scaffold + route * feat(THU-555): Members sidebar entry gated by manage_members * feat(THU-555): render members table with role dropdown * feat(THU-555): wire Remove member with confirmation * feat(THU-555): use globe icon for General sidebar entry * fix(THU-555): rename SCREAMING_SNAKE constant to camelCase * feat(THU-593): gate member management on E2EE-enabled servers * fix(chat-store): dedupe concurrent hydrateChatStore calls * feat(THU-556): Settings → Workspace → Permissions page + resource-CRUD enforcement (#978) * feat(THU-556): setWorkspacePermissionRequiredRole DAL * feat(THU-556): RequireWorkspaceAdmin route guard * refactor(THU-556): consolidate workspace permission keys into shared/workspaces.ts * feat(THU-556): Permissions page (11 keys, labels only) * feat(THU-556): Permissions sidebar entry * feat(THU-556): mount Permissions route * feat(THU-556): refine Permissions page copy and layout * feat(THU-556): scope Permissions to agents/skills/models/mcps * feat(THU-556): use Lock icon for Permissions sidebar entry * feat(THU-556): permissionAllows + BE permission lookup helpers * feat(THU-556): permission-key gating in workspace-scoped handler * feat(THU-556): enforce add_agents/remove_agents permissions * feat(THU-556): treat soft-delete PATCH as remove for permission gating * feat(THU-556): enforce add_skills/remove_skills permissions * feat(THU-556): enforce add_models/remove_models permissions * feat(THU-556): enforce add_mcp_servers/remove_mcp_servers permissions * feat(THU-556): gate edit + chat bypasses, add permission gating tests * fix(workspaces): address review comments across stacked PRs (#988) * fix(THU-549): clear auth token after signOut so server can revoke session * fix(THU-549): clear registry before db-closing so reloaded tabs land at ModePicker * fix(THU-549): guard LogoutModal handleLogout against rapid double-click * fix(THU-549): friendlier ZodError for unset/invalid SERVER_ID * fix(THU-549): remove Cloud URL dev-settings input (use ModePicker flow instead) * fix(THU-552): preserve existing membership role on promote-on-insert * fix(THU-552): delete pending row by (workspace_id, email) after promote-on-insert * fix(THU-552): skip onCreated when create-workspace modal dismissed mid-flight * fix(THU-554): preserve slug/icon on PUT when payload omits them * fix(THU-554): reflect remote workspace updates into settings form * fix(THU-554): append random suffix to duplicate workspace slug * fix(THU-555): resolve workspace permission state when user has no membership * fix(THU-555): gate member actions on granular permission keys * fix(THU-551): expose URL workspace id immediately + collapse chat-id on workspace switch * fix(THU-550): wrap BrowserRouter in ErrorBoundary so bootstrap throws surface a screen * chore: strip PR-ref noise from review-followup comments * fix(THU-578): reset isReady before chat session eviction on workspace switch * fix(THU-553): dedupe ModePicker validation between blur and Continue * fix(THU-552): force ctx.userId for invitedByUserId in pending memberships * fix(THU-552): reject malformed emails on pending membership writes * fix(THU-578): persist selectedAgent against session.workspaceId not thread * fix(THU-556): hide chat-skills-bar when no edit perm and no pinned chips * docs: refresh workspace-memberships handler docstring for permission-key model * test(THU-578): seed workspace context in LinkPreviewWidget fallback tests * fix(THU-553): reset isValidating on SET_URL to unstick Continue after stale blur * fix(THU-553): reset stage to picker on stale-URL bail-out in handleContinue * fix(THU-549): pass captured serverId to handleFullWipe after registry clear * fix(THU-555): align pending-row gates + block admin escalation via invite * refactor(THU-555): use isResolved for membership loading distinction * refactor(THU-555): assign openRef in render body, drop useEffect * fix(THU-555): widen duplicate-slug suffix to 8 chars for collision resistance * docs(THU-555): refresh stale comments referencing removed manage_members guard * fix(THU-555): mirror serverUrl ref synchronously in mode-picker onChange * fix(THU-555): sync pending memberships to all workspace members * fix(THU-555): require change_roles for membership PUT that changes existing role * fix(THU-549): keep getAuthToken resolvable through signOut after registry clear * fix(THU-555): add last-admin guard to membership PUT apply path * fix(THU-555): gate pending-row Admin option on change_roles
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.

Single follow-up PR addressing review comments across the stacked workspaces feature PRs. One commit per fix; each original thread has a `Fixed in ` reply pointing here.
Stacked PRs covered (base → tip):
Note
High Risk
Changes authorization on membership and pending-invite uploads, expands who receives pending-invite sync data, and reorders sign-out/token/credential wiping—mistakes could allow privilege escalation, leave sessions or keys on disk, or break multi-tab logout.
Overview
This PR tightens workspace membership authorization end-to-end: PowerSync upload handlers no longer treat “workspace admin” as the only gate. Writes use
workspace_permissionskeys (invite_users,change_roles,remove_users) via sharedcallerSatisfiesPermission, with extra guards soinvite_usersalone cannot mint or promote admins, PUT upserts cannot demote admins or bypasschange_roles, and last-admin protection applies on membership PUT as well as PATCH/DELETE. Pending-invite handling is hardened: email format validation,invited_by_user_idforced to the caller, promote-on-insert uses insert-if-missing (no role downgrade) and delete pending by workspace+email after unique-key conflicts.Sync rules move
workspace_pending_membershipsfrom the admin-only bucket intoworkspace_dataso members granted invite/role/remove permissions can see pending rows; upload handlers remain the write authority.On the client, the Members route is readable by any shared-workspace member; Add / role / remove controls align with the granular keys (pending lifecycle gated on
invite_users).useActiveWorkspaceIdcan resolve from the URL before the workspace row exists; cross-workspace navigation resets chat detail paths to/chats/new. Sign-out wipe clearsactiveTrustDomainearly for multi-tab safety, passes capturedserverIdinto credential and encryption key cleanup, and defers token clearing until after authenticatedsignOut(withCapturedAuthToken). Smaller fixes include workspace PUT preserving omitted slug/icon,SERVER_IDvalidation messages, app error boundary, mode-picker stale validation, and duplicate-workspace slug suffixes.Reviewed by Cursor Bugbot for commit 3b9607c. Bugbot is set up for automated code reviews on this repo. Configure here.