Concept
Multi-tenancy & security
One tenant must never see another's data. Coro treats this as a database-level guarantee, not a UI convention.
Every table has a tenant_id
There are no exceptions. Every row in every financial, operational, and reference table carries a tenant_id, and every query is scoped by it through Postgres Row-Level Security — not just a WHERE tenant_id = ? clause an application developer could forget to add.
What RLS actually buys you
- A bug in application code can't leak cross-tenant data — the database itself refuses the row
- Direct API calls are checked the same way the UI is, so editing the DOM never grants access the role doesn't have
- Financial mutations run through Postgres functions with their own tenant and permission checks — a defense-in-depth layer beyond RLS
Roles, enforced twice
Role-based access control exists in the UI for a good experience, and again in RLS policies for the actual guarantee. An Auditor role sees every screen a Manager does, but every write attempt — from the UI or directly against the API — is rejected at the database.