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")