Skip to main content

Isolation Model

Switchbord is a multi-tenant platform where each tenant organization operates as an independent workspace. The isolation guarantee is:
A user in workspace A cannot read, write, or act on data belonging to workspace B — regardless of how API calls are constructed.
This guarantee is enforced server-side at the API layer, not through client-side routing or UI controls alone.

Workspace Context Resolution

resolveCallerWorkspaceFromSupabase(userId)

Every authenticated API route resolves workspace context by querying the workspace_members table using the authenticated user’s ID:
Key properties:
  • Reads from workspace_members, not environment variables
  • Returns the workspace the user actually belongs to — cannot be overridden by request parameters
  • Throws immediately if the user is not a member of any workspace
  • Used as the foundation for all workspace-scoped data access

requireSettingsAccess()

All 13 settings API routes use requireSettingsAccess() as their first operation, which calls resolveCallerWorkspaceFromSupabase and enforces a minimum role level before any settings data is read or written:
Never pass workspaceId as a query parameter or request body field that is used for authorization. Always derive it server-side from the authenticated session.

Deprecated Pattern: readSingleWorkspace()

The function readSingleWorkspace() read workspace configuration from environment variables, which is incompatible with multi-tenancy. It has been deprecated and removed from all production code paths. Migration path for any code still referencing it:

Settings Route Threading

All 13 settings API routes thread workspaceId derived from requireSettingsAccess() through every downstream query. No settings route reads workspace data without first establishing the caller’s workspace context. Example pattern for a settings route:

Message Dispatch Isolation

The dispatchMessageViaMetaInSupabase function reads Meta credentials from the workspace identified by job.workspace_id — the workspace that owns the job, not a global configuration:
This means:
  • Workspace A cannot cause messages to be sent via Workspace B’s Meta phone number
  • Credential leakage between tenants at the dispatch layer is structurally impossible
  • Each workspace configures and rotates its own Meta access token independently

Invite-Only Join Model

Users can only join a workspace through an explicit invitation from an existing workspace admin or owner. There is no self-serve workspace discovery or join flow. This ensures:
  • Workspace membership is always intentional
  • New members receive only the role explicitly granted by the inviting admin
  • Removing a member immediately revokes all access, including active sessions
See Authentication & Access Control for session revocation details.

API Key Scoping

API keys are scoped to the workspace that created them. All API key operations (list, delete, revoke) filter by the caller’s resolved workspace_id:

AI Assistant Isolation

The /api/ai-assistant endpoint previously lacked an auth guard. It now requires authentication and resolves workspace context before processing any request. AI context is scoped to contacts and conversations within the caller’s workspace only.

Compliance Mapping

For the full compliance control mapping, see the Compliance Matrix.