1.6 KiB
1.6 KiB
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()againstagency_members:public.is_agency_member(agency_id)public.is_agency_admin(agency_id)(owneroradmin)
Role model
owner: full admin permissions in agencyadmin: same operational permissions as owner for managed resourcesmember: read-mostly on sensitive resources, no admin writes
Write restrictions by table
agenciesINSERT: any authenticated user (supports first-time onboarding)UPDATE/DELETE: admin only
agency_membersSELECT: own membership rowsINSERT: onboarding self-owner membership, or admin adding membersUPDATE/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:
- insert first
agenciesrow, - insert first
agency_membersrow asownerforauth.uid(), - then operate normally under tenant-scoped access.
This supports the server-side auto-bootstrap flow used by getServerAgencyContextOrRedirect().