Roles
Dev-Admin
Can create agents and manage phone numbers. Can only see agents they created. Full configuration access on their agents.Dev-Employee
Read-only counterpart to Dev-Admin: sees everything a Dev-Admin sees in their assigned organizations (full agent details incl. prompt/LLM/tools/knowledge base, phone numbers page, organizations page, performance control) but has zero write rights anywhere. Enforced on all three layers: UI (hidden/disabled controls), Edge API (not inJWT_WRITE_ROLES → 403 on all writes), and RLS (is_read_only_role() guard on all member-reachable write policies). Assigned manually via SQL or via the invite dialog (option visible to Dev-Admins only). Must never be org owner (user_organizations.is_owner = false) and must have profiles.admin = false.
Client-Admin
Can edit assigned agents with limited access (greeting, voice, employees, schedule). Cannot create agents or access phone numbers. Can add existing agents by phone number.Client-Employee
Read-only access to assigned agents. Can add existing agents by phone number. Cannot edit any configuration.Permission matrix
Client-Admin limited access mode
When a Client-Admin opens an agent detail page, they see a simplified view:- Visible: Greeting, voice/speech settings, language, employees, forwarding slots, schedule
- Hidden: System prompt, LLM settings, tools, knowledge base
- Save button: Shows “Save Greeting” instead of “Save”
Route access
How dev_employee is enforced (technical)
- DB constraint:
profiles_role_checkincludesdev_employee(andblockedfor the no-invite safety net). - RLS helpers:
is_dev_employee()grants the dev-level SELECTs (phone_numbers via membership, all profiles, org memberships, call_recordings/call_statistics).is_read_only_role()is appended asAND NOT is_read_only_role()to every write policy a plain org member can reach — org-scoped ones (calls, customer_database, employees, kb_, calendar_, agent_admin, mitarbeiter-slotting) plus the legacyagents-based ones (agentsitself and theagent_phone_number-derived write paths on calls/employees), the mislabelledservice_role_allpolicies on kb_documents/kb_chunks, and the org-owner policy on user_organizations. - Verified, not assumed: a rollback-only negative test as a simulated dev_employee attempted a no-op UPDATE and a DELETE against all 40 public tables plus targeted INSERTs — zero rows written anywhere, while reads (calls, agents, tools, phone numbers, statistics, profiles, memberships) stayed visible. The same test confirmed client_admin/client_employee/dev_admin still write exactly as before. This test found the legacy
agentsgap after the first migration, which is why a second one exists. - Edge API:
dev_employeeis intentionally absent fromJWT_WRITE_ROLESinsupabase/functions/api/lib/auth.ts→ every*:writepermission returns 403. - Signup hardening:
handle_new_user()whitelists roles from signup metadata and validates theinvite_tokenagainstorganisation_invites— self-signup cannot claim a role or org membership. - Assignment invariants:
profiles.admin = falseanduser_organizations.is_owner = falseare load-bearing — the admin flag and org ownership would grant writes through other policies.