cpatpa adds a workspaces layer between users and the organisation
Three commits build a team-scope container that sits above individual users: the `workspaces` and `workspace_members` tables, workspace_id foreign keys on projects/chats/reviews/workflows with backfill, and a full frontend workspace switcher and management UI. Each user gets an auto-provisioned Personal workspace on signup.
Migration 0013 (61dda046) creates workspaces with nullable AI policy override columns - instructions, allow_external_models, retention_days - that inherit from org_settings when null. A partial unique index limits each user to one Personal workspace. The ensure_personal_workspace trigger auto-provisions a Personal workspace and owner membership on every users INSERT; the migration also backfills existing users. workspace_members carries role CHECK IN ('owner', 'admin', 'member'), invited_by, and joined_at. Both tables have RLS enabled and forced, anon/authenticated grants revoked, matching the Phase 2 table posture.
Migration 0014 (171d88d4) adds workspace_id to projects, chats, tabular_reviews, and workflows via a three-step pattern: add the nullable column with FK and cascade, UPDATE every row to the owner's Personal workspace (or parent project's workspace for chats and reviews), then SET NOT NULL. Workflows keep workspace_id nullable because system workflows have no owner. A small STABLE SQL function personal_workspace_id(uuid) is defined once and reused in the backfill UPDATE, which is a sensible approach when the same lookup appears across multiple tables.
The backend route surface (routes/workspaces.ts) covers the expected CRUD plus member management: GET/POST/PATCH/DELETE on the workspace, GET/POST/PATCH/DELETE on members, with last-owner protection (can't demote or remove the last owner), Personal-workspace protection (can't delete), and self-leave. Audit events emitted on every member lifecycle action.
The frontend commit (1587d287) adds a WorkspaceProvider that persists the active workspace selection to localStorage, a workspace switcher in the sidebar, and a /workspaces/[id] settings page. Admins can edit name, description, instructions, the external-AI policy override, and retention days. Owners can change member roles and invite by email. The sidebar was rebranded from "Mike" to "PIP" in this same commit.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?