Files
pleskSaas/SECURITY.md

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() 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().