FEATURES / MULTI-TENANCY

Workspaces,
memberships,
and API keys.

Every model is org-scoped. Invitations, role assignment, and tenant API keys are wired end-to-end. Platform-admin impersonation ships with HMAC-signed cookies.

Built around the Organization aggregate.

Org workspaces

Every domain entity carries an orgId foreign key. Repos enforce it via a tenant-scoped DataSource — no leaks across orgs.

Invitations

Time-limited invite tokens, role-on-accept, expiry, revoke, resend. Email templates ready in 3 languages.

API keys

Per-tenant keys with scoped permissions, rotation, last-used tracking, BCrypt-hashed at rest. CLI included.

Member roles

Owner, admin, member out of the box. Add roles in one file; ESLint flags every spot you forgot to update.

Domain claim

Optional email-domain auto-join — invite the team by claiming acme.com once.

Impersonation

Platform admins can act as any tenant for support. Every action gets logged + the cookie is HMAC-signed and short-lived.

A repository pattern that knows your tenant.

Tenant scoping happens in the data layer, not in every query. The repository constructor takes an OrgId; every find/create/update implicitly carries it. You cannot accidentally read another org's data.

modules/tenancy/infrastructure/orgScopedRepo.ts
 1  export class OrgScopedProjectRepo implements IProjectRepo {
 2    constructor(private readonly db: PrismaClient,
 3                private readonly orgId: OrgId) {}
 4  
 5    findAll() {
 6      return this.db.project.findMany({
 7        where: { orgId: this.orgId },
 8      });
 9    }
10  }

Multi-tenant from line one.

No retrofitting org-scoping six months in. UseDeploy bakes it into the aggregate.