Workspaces and multi-org
How workspaces, memberships, and org connections fit together, plus the RLS story that keeps them isolated.
Workspace vs org connection
A workspace is the OrgBolt unit — a team's shared bucket of tasks, chat history, and settings. An org connection is a Salesforce OAuth link that belongs to a workspace. One workspace can hold zero, one, or many org connections. A typical setup is one workspace for your company and three org connections for Dev, UAT, and Production.
You can belong to multiple workspaces — one for your day job, one for a client, one for a personal sandbox. OrgBolt tracks membership with a workspace_members join table. The workspace you see in the app at any given moment is stored in a cookie called orgbolt_workspace. Switch workspaces from the switcher in the header; your tasks, org connections, and settings all swap together.
Adding teammates
Workspace owners can invite teammates from Settings → Members. An invite is an email link that expires in 7 days. When the invitee clicks the link, they're added to workspace_members with the role the owner set. Billing seats are counted per workspace member, not per workspace — one person across three workspaces is three seats total.
Row-level security, plain English
Every table in OrgBolt that holds workspace data — tasks, chat messages, org connections, audit logs, skill customizations — has a Postgres row-level security policy attached to it. The policy says, in effect: "this row is only visible to users who are members of the workspace it belongs to." The policy is enforced by Supabase, not by application code.
Why this matters: if a bug ever slipped into OrgBolt's server code that forgot to filter a query by workspace ID, the database would still refuse to return another workspace's rows. RLS is a second line of defense that runs underneath every query, every time, with no way for the application to opt out.
How the workspace cookie works
The orgbolt_workspace cookie is a pointer, not a permission. It decides which workspace the UI renders, but RLS decides which rows are visible to your session. If you try to set the cookie to a workspace you're not a member of, the app will render empty — the database will refuse to return any rows — and you'll be redirected back to a workspace you own. This is by design.