Multi-Tenancy

How Mistvine isolates organization data.

Last updated

Mistvine is a multi-tenant SaaS. Each organization's data is logically isolated from other organizations through row-level security and per-request membership verification.

Isolation Architecture

Defense in Depth

Row-level security at the database is the authoritative enforcement boundary. The routing and session layers are independent verifications layered on top, so a misconfiguration in any single non-database layer does not by itself produce cross-tenant access.

Layer Purpose
Routing The organization is identified from the request's subdomain and verified against the authenticated user's active memberships before binding the request's org context.
Session A single authenticated session carries per-organization claims (org, role, ownership) that are re-evaluated on every request.
Database Row-level security policies on every organization-scoped table restrict reads and writes to the caller's active memberships.

Isolation Guarantees

  • Users authenticated to one organization cannot access another organization's data
  • Each request is bound to exactly one organization context, verified against the user's active memberships before any data access
  • No shared in-memory or cached state crosses tenant boundaries within a request

Multi-Organization Users

Users can belong to multiple organizations simultaneously. Each organization membership:

  • Is selected per request via the organization's subdomain and verified against the user's active memberships
  • Has independent role and permissions
  • Cannot transfer data between organizations

Audit Trail

Audit logs are scoped to organizations. Only organization administrators can view their organization's audit logs. Cross-tenant audit access is not possible.

Testing

An automated cross-tenant test suite runs in CI against the database's row-level security policies and asserts, across the full set of organization-scoped tables, that:

  • Cross-tenant data access is blocked
  • Cross-tenant data modification is blocked
  • Session and routing context cannot bypass database-layer isolation