Skip to content

Multi-Tenancy

flowgeist.tool is a B2B SaaS: every business entity belongs to exactly one tenant (customer organization). Strict data isolation between tenants is a hard requirement — it is part of the product’s security model.

  • Tenant entities carry a tenant_id foreign key.
  • The TenantResolverGuard resolves the tenant context early in the guard pipeline — before authentication and authorization.
  • Queries must always be scoped to the resolved tenant. A resource from a different tenant must behave as if it does not exist (404, never 403-with-leak).
  1. Every query is tenant-scoped. When writing Prisma queries, always include the tenant filter — never rely on “the ID is unguessable”.
  2. Cross-tenant access returns 404. Do not distinguish “not found” from “belongs to another tenant” — that would leak existence.
  3. Tenant context comes from the server side (JWT claim / resolved tenant), never from a client-supplied parameter alone.
  4. Super-Admin is the only role that can act across tenants (provisioning, tenant lifecycle: ACTIVE → SUSPENDED → TERMINATED).
Status Effect
ACTIVE Normal operation
SUSPENDED Users set INACTIVE, login refused
TERMINATED Soft-deleted (no purge — audit trail)

Tenants are provisioned through a dedicated M2M API (/api/v1/provisioning/*) authenticated by a shared secret with timing-safe comparison — it fails closed (503) when the secret is not configured.

Every service test must verify tenant isolation:

  • Reading/updating a resource owned by another tenant → 404 / NOT_FOUND.
  • List endpoints must not leak other tenants’ rows.
  • Use synthetic fixtures only — no PII in test data (example.com domains, synthetic UUIDs).