Multi-tenant model
The application is organization-scoped. Core records are associated with an organization and usually further scoped by location and pool. Primary tenant entities:- organizations
- locations
- pools
- users
- chemical records
- maintenance logs
- compliance incidents
- corrections (a polymorphic table keyed by
entity_type/entity_id, spanning chemical records, maintenance logs, and form submissions)
Access model
The current access model combines:- organization scoping
- a per-user
PermissionKeyenum (src/lib/permissions.ts) assigned directly to each user — no separate role/template entity;org:manageis a wildcard equivalent to every other key - location-level grants for selected workflows
Security posture
- Supabase Auth handles authentication
- service-role access stays server-only
- server actions are the main mutation boundary
- tenant checks must be applied consistently across joined data and exports
- direct URL access should never bypass permission checks
Current design constraints
Todayusers.organization_id is a strict one-to-one organization assignment. The roadmap includes a future move to many-to-many organization memberships with an active-organization concept for multi-org accounts.
Operational guidance
- treat
.env.localas the secret boundary - do not expose service-role credentials to client components
- verify tenant scoping on exports, alerts, dashboards, and cross-module joins
- include restricted-access accounts in end-to-end verification