50 lines
1.6 KiB
Markdown
50 lines
1.6 KiB
Markdown
# Security Model (CL2)
|
|
|
|
## Tenancy model
|
|
|
|
- Tenant boundary is `agency_id`.
|
|
- Every business table row is scoped to an agency.
|
|
- RLS helper functions enforce scope using `auth.uid()` against `agency_members`:
|
|
- `public.is_agency_member(agency_id)`
|
|
- `public.is_agency_admin(agency_id)` (`owner` or `admin`)
|
|
|
|
## Role model
|
|
|
|
- `owner`: full admin permissions in agency
|
|
- `admin`: same operational permissions as owner for managed resources
|
|
- `member`: read-mostly on sensitive resources, no admin writes
|
|
|
|
## Write restrictions by table
|
|
|
|
- `agencies`
|
|
- `INSERT`: any authenticated user (supports first-time onboarding)
|
|
- `UPDATE/DELETE`: admin only
|
|
- `agency_members`
|
|
- `SELECT`: own membership rows
|
|
- `INSERT`: onboarding self-owner membership, or admin adding members
|
|
- `UPDATE/DELETE`: admin (delete also allows self-leave)
|
|
- `clients`
|
|
- member-readable and member-writable (chosen for MVP collaboration speed)
|
|
- `plesk_instances`
|
|
- member-readable, admin-writable
|
|
- `plesk_subscriptions`
|
|
- member-readable, admin-writable
|
|
- `plesk_domains`
|
|
- member-readable, admin-writable
|
|
- `actions_log`
|
|
- member-readable, admin insert/update
|
|
- `billing_accounts`
|
|
- member-readable, admin-writable
|
|
- `entitlements`
|
|
- member-readable, admin-writable
|
|
|
|
## Onboarding compatibility
|
|
|
|
Policies are designed so a newly authenticated user can:
|
|
|
|
1. insert first `agencies` row,
|
|
2. insert first `agency_members` row as `owner` for `auth.uid()`,
|
|
3. then operate normally under tenant-scoped access.
|
|
|
|
This supports the server-side auto-bootstrap flow used by `getServerAgencyContextOrRedirect()`.
|