Skip to content

ADR 002: Tenancy via FK Scoping (Option A)

Status

Accepted

Context

Multi-tenancy needs data isolation between organizations. Two approaches: FK-based scoping (org FK on every model + middleware) or schema-per-tenant (Postgres schema isolation via django-tenants).

Decision

Implement FK-based scoping (Option A) with TenantMiddleware that resolves request.organization and request.project from headers, session, or default membership. Schema-per-tenant is a future option behind a feature flag.

Consequences

  • Every query that should be tenant-scoped must include .filter(organization=request.organization) — missing a filter leaks data across tenants
  • TenantMiddleware resolves org from X-Organization header, session, or first membership (in that priority order)
  • Hierarchy: Organization → Team → Workspace → Project. Tasks and WorkflowInstances scope to Project. Skills and Configs scope to Organization.
  • FK approach is simpler to implement, works with Django admin, and doesn't require migration-per-schema overhead
  • Risk: a missed filter is a data leak. Mitigated by audit policy in CLAUDE.md ("audit ALL routes for the same pattern")