#Roles & permissions
The backend is the final authority. The frontend only hides or disables what the user can't use, so the UI isn't confusing.
#What exists in each source
| Source | Roles | Permission shape |
|---|---|---|
| V7 V7 only | Per organization: system owner + admin (created with the organization) + custom roles. A member can hold several roles | Boolean grants: a role has a permission or not. ~92 permission rows on levels organization, dashboard, server, application, database, backup, cronjob, firewall, application-user, plus integration sub-levels. Each row also says which plan tiers include it (free_default, newbie_default, pro_default, …) |
| OSS OSS API | Panel roles (Administrator + custom) | Three states per permission: none (hidden), view (read only), manage (read & write). Catalog GET /admin/permissions with groups and access_levels. 35 permissions: server-level (dashboard, application, database, system_user, firewall, cronjob, fail2ban, logs, service, php, node, setting, disk_cleaner, backup, activity_log, sync, git, storage) and application-level (app_dashboard, app_domain, app_deployment, app_environment, app_worker, app_file, app_log, app_backup, app_php, app_security, app_firewall, app_bot_blocker, app_fail2ban, app_staging, app_clone, app_magic_login, …) |
| Demo Demo UI only | Admin, Member (system) + custom | `level.name.view |
| V8 doc V8 requirement Phase 4 (2026-10-03) | Owner and Admin are fixed. Custom roles per organization. One role per member. A role can't be deleted while members hold it | view / manage, with parent permissions ticked automatically. The permission names are not published yet (the permission list and seeder are a separate step), so the matrix must be built from the API catalog |
#Roles
| Role | Rules | Source |
|---|---|---|
| Owner | Creator of the organization. Full access including billing, delete organization, remove members. Can't be removed. Exactly one? V7 allows only the creator Assumption | V7 only |
| Admin | Full organization access except owner-only items (billing/plan/usage summary hidden by default). Fixed role, permissions read-only V8 requirement Phase 4 (4.5). An old owner who transfers the organization becomes admin (4.7) | V7 only V8 requirement |
| Custom roles | Created per organization, any permission set. Editable and deletable | V7 only Route::resource('roles') |
Role operations (V7): list, create, show, update, delete. V8 Missing.
- Create needs a unique role name and at least one permission (
permission_ids). V7 only - Deleting:
ownerandadminare refused. V8 refuses to delete a custom role while any member holds it V8 requirement Phase 4 (4.5) — stricter than V7, which deleted it anyway. The UI disables Delete with "N members use this role — move them first".
#Permission matrix (proposed V8 defaults)
N = no access · V = view · M = manage. Proposed, to confirm in D-7. Not a backend fact.
| Area | Owner | Admin | Custom (example "Developer") | Notes |
|---|---|---|---|---|
| Dashboard | M | M | V | Spend widget hidden without Billing view |
| Servers (list, connect, disconnect) | M | M | V | Connect/disconnect = manage |
| Server Details → per OSS permission | M | M | per grant | Maps to the OSS catalog names (application, database, system_user, service…) |
| Providers | M | M | N | Holds cloud credentials |
| Blueprints | M | M | V | |
| Organizations (settings) | M | V | N | Rename/logo = manage. Delete = owner only |
| Members | M | M | N | Remove members: V7 owner only |
| Roles | M | M | N | System roles read-only |
| Plans | M | N | N | V7 owner-only |
| Subscription | M | N | N | V7 owner-only |
| Billing | M | N | N | V7 owner-only |
| Audit Log | M | V | N | Read-only area. "M" = export Assumption |
#Plan-gated features
In V7 a permission can be off because of the plan: VerifyPermission checks {plan}_default on the permission for the owner's tier (except members, role-permissions, share-server). The UI should show such items as locked with an upgrade hint, not hidden. V8 needs the API to return the reason: denied_by: role | plan | subscription_expired. Missing
#Frontend behaviour
- Load the current user's permission map once per organization switch (V7
my-permissions/{level}). Missing - Hide sidebar entries with
none. Disable action buttons with a tooltip forview. - Never rely on the hidden state: every mutation can still return 403. Handle it with a toast and a permission refresh.
#Shared servers (V7)
V7 also lets an owner share one server with a person (organization_members.server_id, /servers/{server}/share-server). The person sees only that server.