Org controls
WorkOS SSO sign-in, a Clerk session-verification driver, owner-gated multi-user membership, and the cross-tenant admin-write RLS layer the operator control plane mutates through.
@caisson/org-controls is the commercial org and operator-controls module, carved out of the
open Base so the Apache-2.0 substrate stays small: WorkOS SSO, a Clerk session-verification
driver, the MANAGE half of the multi-user account model, and the admin-write RLS layer an
operator control plane mutates through. Buyer session resolution stays in the open
@caisson/auth; buyer tenant isolation stays in the open @caisson/tenancy-rls.
What it does
- WorkOS SSO (
createWorkosSsoProvider), a framework-agnostic AuthKit/SSO transport seam: builds the authorization URL, exchanges the callback code for the user's id + email. Config is injected, never read from env by the package. - Clerk session verification (
createClerkSessionVerifier), verifies a Clerk session token against Clerk's JWKS via@clerk/backend, then maps the claims onto the kernel'sSessionContext. Networkless when you supplyjwtKey. - Owner-gated membership (
listAccountMembers/addAccountMember/removeAccountMember/assertCanManageMembers), invite and remove seats on a shared account, owner-only. - Admin-write RLS (
withAdminWrite+ the policy builders), the cross-tenant write role an operator control plane mutates through, DB-separated from the buyerapprole. - Entitlement gate (
holdsOrgControls), the fail-closed predicate gating the module's own surfaces.
Install
bun add @caisson/org-controlsQuickstart, WorkOS SSO
import { createWorkosSsoProvider } from "@caisson/org-controls";
const sso = createWorkosSsoProvider({
clientId: process.env.WORKOS_CLIENT_ID!,
apiKey: process.env.WORKOS_API_KEY!,
redirectUri: "https://app.example.com/auth/callback",
});
const url = sso.authorizationUrl(state); // redirect the buyer here
const { userId, email } = await sso.exchangeCode(code); // on the callbackClerk session verification
import { createClerkSessionVerifier } from "@caisson/org-controls";
const verifier = createClerkSessionVerifier({
jwtKey: process.env.CLERK_JWT_KEY!, // networkless — no per-call JWKS fetch
authorizedParties: ["https://app.example.com"],
});
const session = await verifier.verifySession(clerkToken); // -> SessionContextAn active Clerk Organization maps to accountId/role; with no Organization active, the
session falls back to the personal-account convention (accountId === userId, role
"owner"). This mapping is stateless, route the verified userId through @caisson/auth's
resolveUserAccounts/selectActiveAccount when you need the DB-authoritative multi-account
resolution instead.
Membership management
import { addAccountMember, listAccountMembers } from "@caisson/org-controls";
// actorRole comes from the caller's resolved session; only "owner" may manage members.
await addAccountMember(db, actorRole, accountId, newUserId); // default role "seat"
const members = await listAccountMembers(db, accountId);Admin-write RLS
import {
withAdminWrite,
buildAdminWritePolicySql,
} from "@caisson/org-controls";
// At DEPLOY, alongside the table's existing tenant-isolation policy:
const sql = buildAdminWritePolicySql("account");
// At call time, in the operator control plane only:
await withAdminWrite(db, async (tx) => {
await tx.query(`UPDATE account SET ... WHERE id = $1`, [accountId]);
});withAdminWrite refuses a SUPERUSER/BYPASSRLS role before it ever assumes it, a
misconfigured role fails closed rather than silently widening access.
Entitlement gate
import { holdsOrgControls } from "@caisson/org-controls";
if (!holdsOrgControls(activeEntitlementIds)) {
throw new AuthzError("org-controls entitlement required");
}activeEntitlementIds must already be filtered to active grants, the predicate never reads
the database itself, and an empty set denies.
Composing with the base
org-controls composes DOWN onto @caisson/auth, @caisson/tenancy-rls, and
@caisson/kernel: buyer session resolution and buyer tenant isolation are never
reimplemented here, only extended: the owner-only MANAGE surface and the cross-tenant
admin-write role sit beside those open primitives, never in place of them.
org-controls is a $249 standalone commercial module (also included in the Everything
bundle), gate access to its surfaces with holdsOrgControls.