Tenant Isolation Model
Key Principles
Data Isolation
All project data is scoped to a tenant. Users cannot access projects from tenants they don’t belong to.
Flexible Membership
Users can be members of multiple tenants simultaneously with different roles in each.
URL-Based Routing
Tenant slug in URL provides context:
/app/:tenantSlug/projects/:projectIdHierarchical Permissions
Two-tier system: tenant-level roles and project-level roles
Tenant Schema
Tenant Table
packages/app/supabase/migrations/20260217143000_multi_tenant_onboarding.sql
- Lowercase alphanumeric with hyphens
- No leading/trailing hyphens
- Globally unique
- URL-safe for routing
Tenant Membership
Role Hierarchy
Tenant Roles
- Owner
- Admin
- Member
Permissions:Typical Use Case: Founder or organization admin
- Full control over tenant
- Manage tenant settings (name, slug)
- Add/remove members
- Delete tenant
- Create projects
Project Roles
- Owner
- Editor
- Viewer
Permissions:
- Full project control
- Manage project members
- Edit project settings
- Delete project
- Create/edit/delete tasks
Permission Matrix
* Tenant members can create projects if the tenant policy allows. This is configurable per tenant.
Creating Tenants
Database Function
packages/app/supabase/migrations/20260217143000_multi_tenant_onboarding.sql
- Automatic slug generation from name
- Conflict resolution with numeric suffixes
- Creator automatically becomes owner
- Idempotent member insertion
Slug Normalization
Creating Projects in Tenants
Updated Function Signature
packages/app/supabase/migrations/20260217143000_multi_tenant_onboarding.sql
The function signature changed from accepting just
p_name and p_description to requiring p_tenant_slug as the first parameter.Auto-Member Addition
1
Project Creator
Always gets
owner role regardless of tenant role2
Tenant Owners/Admins
Automatically get
editor role in new projects3
Tenant Members
Automatically get
viewer role in new projects4
Future Members
When new users join the tenant, they are NOT automatically added to existing projects (must be invited)
Permission Enforcement
Database Functions
Row Level Security
- Tenant Policies
- Project Policies
- Task Policies
Migration Strategy
From Single-Tenant to Multi-Tenant
The migration20260217143000_multi_tenant_onboarding.sql automatically converts existing data:
1
Add tenant_id Column
2
Generate Temporary Mapping
3
Create Tenants from Projects
4
Backfill tenant_id
5
Migrate Memberships
6
Drop Single-Tenant Triggers
URL Structure
Routing Pattern
- Clear tenant context in URL
- Shareable links with implicit workspace
- SEO-friendly for public pages
- Simple authorization checks
Repository Interface
packages/app/src/domain/repositories/interfaces.ts
- All project operations require
tenantSlug - Tenant context passed explicitly
- Type-safe tenant isolation
Best Practices
Always Validate Tenant Context
Never trust tenant slug from URL alone. Always verify user membership before data access.
Use Slug for Routing, ID for Data
- URLs: Use human-readable slugs
- Database: Use UUIDs for foreign keys
- Convert slug to ID at API boundary
Enforce RLS at Database Level
Never rely on application-level checks alone. Database RLS provides defense-in-depth.
Handle Tenant Switching
Users can be in multiple tenants. Clear client-side caches when switching contexts.
Security Considerations
Tenant Data Leakage
Tenant Data Leakage
Risk: User accesses data from wrong tenant via URL manipulationMitigation:
- RLS policies check tenant membership
current_project_rolevalidates both tenant AND project membership- Database functions reject cross-tenant operations
Privilege Escalation
Privilege Escalation
Risk: Member promotes themselves to ownerMitigation:
- RLS policies restrict role changes to owners
security definerfunctions setsearch_path = public- All mutations require explicit permission checks
Tenant Deletion
Tenant Deletion
Risk: Accidental tenant deletion loses all dataMitigation:
- Soft delete via
archived_attimestamp - Only owners can archive tenants
- Cascade deletes handled by foreign keys
- Consider implementing trash/recovery period
Next Steps
Architecture Overview
Return to high-level architecture concepts
Database Schema
Explore complete table definitions and relationships