Packages

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's SessionContext. Networkless when you supply jwtKey.
  • 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 buyer app role.
  • Entitlement gate (holdsOrgControls), the fail-closed predicate gating the module's own surfaces.

Install

bun add @caisson/org-controls

Quickstart, 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 callback

Clerk 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); // -> SessionContext

An 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.