#FE: Permissions & the role matrix (from backend Phase 4)
Frontend spec for backend Phase 4 items 4.9–4.11 — the permission list, its parent rules and its seeder — added 2026-10-08 (Pair 1), which took Phase 4 to requirements complete, and sharpened twice the same morning. V8 requirement This is the list every screen on this site has been waiting for — and as of 08:00 it is more than a list: the same entries carry the sidebar (title, icon, url, order), so the product's navigation is now backend data. Pair 1 now explicitly marks B4.9–B4.11 built (2026-10-09). Its API reference publishes GET /api/v1/organizations/{organization}/permissions (role-view) and /menu (any member); see API architecture. Menu URLs contain organization/server/application placeholders that the frontend fills from the current context. Pair 2 has not yet copied the new Phase 4 build status.
Phase 4 — how a permission reaches a screen
The seeder on the backend — 37 keys, each view / manage, with parents, owner-only flag and order
↓
Organization roles — the owner ticks keys; Owner and Admin are fixed and not editable
↓
Parents — ticking a child ticks its parents; unticking a parent unticks its children
↓
The user's own map — what this member may do in this organization
↓
The screen — hidden when none, read-only when view, full when manage
37 keys in four groups. Every key has view and manage, except the five read-only ones marked view only. manage includes create, edit and delete — there is no separate delete permission.
The root of the whole chain — server.view needs organization.view (4.10), so a member with nothing here sees nothing at all
organization.members
Members, invitations
Pairs with the fixed one-role-per-member rule (4.5)
organization.roles
Roles and this very matrix
The recursive one: a role with organization.roles.manage can edit roles, including its own. The form should make that obvious rather than let someone remove their own access by accident
organization.activity
Activity log
View only — nothing to manage, so the row has two states, not three
organization.integrations
Cloud providers, Git accounts (Phase 5)
This is the key FE: Integrations was missing for its "servers the user may manage" list (5.7). One key covers both providers and Git — not one each
organization.billing
Billing, charges, invoices
Owner only. See the callout in section C: this key is in the list but can never be ticked for a custom role
List, server page, dashboard, settings, power, resize, delete, disconnect, alerts, change IP, service monitoring, default page, panel update, sync
The widest key on the list, and the one to watch. Fourteen separate actions sit behind one tick — including delete, resize and change IP, three of the most destructive things in the product. A role that may change a server's name can also delete it. Nothing in the doc splits them, so the frontend cannot either; this spec flags it below
server.database
Databases and database users
server.system-user
System users
Also a hidden parent of application.manage — see 4.10
server.firewall
Firewall
server.fail2ban
Fail2ban
server.cronjob
Cron jobs
server.service
Services, including PHP-FPM
PHP-FPM config (9.30) lands here, not under server.runtime
server.runtime
PHP and Node.js versions
server.docker
Docker
New in V8 — no V7 equivalent, so migrated roles get it only where they had manage on the parent area
server.logs
System logs
View only
server.disk-cleaner
Disk cleaner
server.backup
Server backups
server.notification
Per-server notification settings (Phase 11)
This settles half of D-37: per-server notification channels are a permission-gated server area, so wherever that screen lands it is guarded by a server key, not an account one
manage here is the one with cross-area parents (4.10)
application.domain
Domains & SSL
application.file
File manager
application.logs
App logs
View only
application.php
PHP settings
application.environment
Environment
New in V8
application.deployment
Deployment, auto-deploy
application.database
The app's database link
application.backup
App backups
application.staging
Staging and clone
One key for both, so a role cannot have clone without staging
application.worker
Workers
application.security
Password protection, web firewall, bot blocker, Fail2ban
Four screens behind one key — the app menu (10.x) lists them separately, so the matrix is coarser than the menu
application.container
Containers
New in V8
application.settings
App settings
This names Settings as a real app area for the first time — it has been an unplaced tab in D-40 and the home of Premium Hosting Care's monitoring switch (14.6) with no key to guard it. Now it has one
Picking manage implies view. The two are flags, not alternatives (4.11), so a three-state control is a rendering choice — the request still carries view and manage
Every server feature needs server (view)
Ticking, say, manage on the firewall must turn on view for the server itself
Every application feature needs application (view)
Same for the app group
server (view) needs organization (view)
The root. So every grant in the product ultimately turns on view on the organization
application (manage) also needs server.system-user (manage) and server.database (manage) (as V7)
The surprising one — see below
Ticking a child ticks its parents
Cascade upward, visibly
Unticking a parent unticks its children
Cascade downward, visibly — and this one removes access the user had just granted, so it needs a confirm or at least a clear count ("this also turns off 6 permissions")
The backend re-adds missing parents on save
So a hand-made API call cannot produce an inconsistent role. The frontend should still cascade, because a role that silently gains two permissions it did not tick is worse than one that shows them
The permissions are written in the seeder itself, as V7 — not a config file. It syncs each one with updateOrCreate by name + level (as V7 / OSS), safe on every deploy, and fails on a missing parent or a loop. Roles then get permissions in the role editor (4.5), view and / or manage per permission, stored on the role ↔ permission link
The catalog is the form's blueprint, so the frontend renders rather than designs: the sequence, the grouping and the owner-only marking all come from the data. The identity is name + level — never match on a label, which is translated
It creates the fixed Owner and Admin roles: Admin gets every permission except owner-only ones; the owner skips checks entirely
Confirms what Roles & permissions proposed: Owner and Admin are read-only in the UI. And "the owner skips checks" means the frontend must not try to compute an owner's map — an owner is simply allowed
New permissions are never added to custom roles automatically — the owner ticks them
This needs a screen the frontend had not planned. When V8 ships a new feature, every custom role silently lacks it, and nothing tells the owner. Without a prompt, an organization upgrades and its roles quietly fall behind. This spec recommends a "new permissions available" notice on the Roles page, listing what was added since the role was last saved
A key removed from the seeder is deleted only with a prune option
So the catalog may contain keys that are on their way out. The matrix should render whatever the API returns and not assume the list only grows
Labels come from translation files
Quietly the best news on this page for i18n. The widest form in the product has 37 labels plus their group headings, and they are translatable from the start — so the matrix is not an English-only screen, and the frontend takes the label for a key from its own permissions.* namespace rather than printing whatever the API sends. It is a small, real step on Q8, in the same spirit as 11.3's email translation keys. One ambiguity: each seeder entry also carries a title (see section D), and nothing says whether that is a translation key or an English fallback Open question
⚠️ Reversed 2026-10-09: Control Panel users (12.3) have their OWN permission list, table and seeder — as V7's separate hosting-user seeder, built in Phase 12. What they share is the sync logic, not the list (updateOrCreate by name + level, fails on a missing parent or loop, prune option)
This corrects what this page said for one day. On 2026-10-08, 4.11 read "the same permissions are used for Control Panel users", and this spec recorded it as the answer to a question FE: Control Panel & White label had marked unpublished. Vishal reversed it: 12.3's tick-list is a second catalog, so that question is open again — the Control Panel's entries are still not published. The useful shape underneath is a pattern, not a single list: there are now three separate permission catalogs — organization (4.9), admin (17.2) and Control Panel (12.3) — each with its own table and seeder, all using the same sync mechanics. So build the matrix component once and point it at whichever catalog a screen needs; just never assume the entries are the same 12.3's tick-list is not a second catalog — it is this one. Which subset a Control Panel customer may be given is still not stated, so the screen renders the API's list and does not assume all 37
#D. The sidebar comes from the same list (4.11, added 2026-10-08)
This is the part that reaches furthest beyond the Roles screen. Every permission entry also carries its menu data, exactly as OSS does:
Field
What it is
Frontend consequence
title
The item's name
Shown in the sidebar. Labels also come from translation files, so whether title is a key or an English fallback is unstated Open question
icon
A Lucide icon name
This lines up with the frontend's icon library exactly — Lucide React is already the chosen set. But it means icons are resolved by name at runtime, so the app needs a name → component map with a fallback icon when the name is unknown (the backend says a fallback is expected). Worth knowing at build time: a dynamic lookup cannot tree-shake the way static imports do, so use a curated map of the names the seeder actually ships, not the whole icon set
url
Where the item goes
So routes are backend data too. They must contain no language prefix — the rule on this site and in the flow doc — and nothing in 4.11 says they don't Open question
order
Sort position, decimals allowed so items fit in between
The sidebar is sorted by this. Decimals are a small, sensible touch: a new item can be slotted between two existing ones without renumbering
parent group
Groups items into sub-menus
So the sidebar's grouping is data as well, not a frontend layout decision
How the sidebar is built: only the items the role can view, sorted by order, with the icon drawn by name. And one sentence carries real weight — "changing an icon, link or order = edit the seeder and deploy."
All 92 V7 organization permissions are mapped to the new keys, so every feature stays accessible
The migration is deliberately generous, not strict
A role gets a new key if it had any V7 permission that maps to it (parents added)
Where V7 was finer than V8 — phpmyadmin → server.database.manage, wp-login → application.manage — the role gets the broader key, never less access. The migration report lists these
Widening access is the safe direction for continuity and the unsafe one for least privilege, and the backend chose continuity. The report is therefore something an owner needs to see, not an internal artefact — a migrated owner should be told which roles gained more than they had. Where that report is read is not statedOpen question (the same gap as the combined-role report on FE: Admin panel)
New V8-only features — application.environment, application.container, server.docker, server.runtime, application.activity — go to roles that had manage on the parent area
So a V7 "Developer" role with server manage arrives with Docker and runtime access it never had. Worth surfacing in the same report
V7 support and site-migration have no key
Consistent with the rest of the doc: support tickets are not in V8 at all (decided 2026-10-08) and site migration is still pending. So these two are not oversights — one is cancelled, one is unwritten
Published: 4.9, 37 keysV8 requirement. Every one of those sentences is now wrong and has been rewritten
Is there a separate delete permission? (the backend's own Q1)
No — decided 2026-10-08.manage includes create, edit and delete, so the matrix is three states per row
Does the Control Panel have its own permission catalog? (12.3)
Yes — reversed 2026-10-09 (Vishal)V8 requirement. For one day 4.11 said it reused this list; it does not. 12.3 has its own list, table and seeder, as V7's separate hosting-user seeder, built in Phase 12 — sharing only the sync logic. So its entries are unpublished againOpen question
What guards per-server notification settings? (part of D-37)
server.notification — a server-level key, Phase 11
Is Settings a real application area? (part of D-40, and 14.6's home)
Yes — application.settings is a published key. Where the tab sits in the fixed app menu is still D-40, but the area itself is no longer in doubt
How do V7 roles survive the move? (D-7's last open half)
Mapped key by key, never losing access, with a migration report for the places V7 was finer
Do add-ons get their own permission screen?
No — application.wp-toolkit and application.log-monitoring are rows in the ordinary matrix
Where does the sidebar come from?
The same permission list (4.11, 2026-10-08) V8 requirement — each entry carries title, a Lucide icon name, url, order and a parent group, and the sidebar shows the items the role can view, sorted by order. So navigation is data, and Navigation structure describes a design the backend now supplies
Does the admin panel use this list too?
No — it has its own tables and seeder (17.2, 2026-10-08), separate from organization permissions, but in the same style. And since 2026-10-09 the Control Panel does too, so there are three catalogs sharing only their sync mechanics (one permission per feature, view / manage, same menu fields). Its group list is published — see FE: Admin panel. One shape appears there and not here: B17.2a now keeps only Log in as user manage-only. Admin roles & permissions has view+manage (2026-10-12): view reads roles/permissions/admin assignments; manage creates/edits/deletes/assigns. Users: manage grants neither. So across the two catalogs a row can have both flags, view only (five organization areas) or manage only — build the matrix to render all three from the data, not two
Who may manage blueprints, backup storage and the plan page? The list has no key for any of them Open question. Blueprints live in Central (16.7) and have their own module; Backup Storage is an organization-level page in its own right; and the only billing key, organization.billing, is owner only — so nothing says whether a member can even look at the plan. Three real screens with no guard named. The frontend cannot invent keys, so these pages are specced as owner-only until told otherwise, which is the safe reading but probably not the intended one
D-53
Should server really be one key for fourteen actions — including delete, resize and change IP?Open question A role that may rename a server may also delete it. V7 was no finer, so this is inherited rather than new, but V8 added resize, change IP and panel update to the same tick. This spec follows the doc and keeps one key, and flags that the destructive actions therefore need their own confirms (U13's TYPE-TO-CONFIRM rule) because the permission layer will not stop anyone
—
Does application.view need server.view? 4.10 chains server keys to server.view and server to organization.view, but the application group is only chained to application.viewOpen question. Applications live on servers, so the chain presumably continues — but it is not written, and the form has to cascade something
—
Where does an owner read the migration report? (4.9 Existing users) Open question Same shape as the combined-role report on FE: Admin panel — the backend produces a list and no screen owns it
—
What happened to "hosting users"? Phase 4's "Not in this phase — delete permission and hosting users: waiting on the open questions" line was deleted on 2026-10-08. The delete-permission half was answered; the hosting-users half simply vanished with the lineOpen question. It may have been absorbed by Control Panel users (12.3, 12.12), which is part of D-41 — but no text says so
—
How is the owner told that new permissions exist? (4.11) Nothing is added to custom roles automatically Open question, so this spec proposes a notice on the Roles page rather than leaving roles to fall behind silently
—
Are the server-panel and application-panel menus also seeder-driven? 4.11 says "the sidebar"; the frontend doc fixes those two menus separately (U13.4, U14.4) Open question. They are lists inside a server, so they may not be what 4.11 means
—
Do the seeder's urls carry a language prefix? They must not — paths are the same in every language, with the locale from a cookie Open question. 4.11 does not say either way, and this is the kind of thing that is cheap to agree now and expensive later
**Latest B17.2/17.2a built on Pair1:**59-entry admin catalog/API51, role list/detail/create/edit/delete and administrator list/assign APIs52–58; admin-roles view/manage, fixed SuperAdmin, in-use deletion refusal, last-active-verified-role-manager lockout guard. Own /admin/me adds admin_role/effective permissions. Sidebar/menu still17.3 unbuilt, Pair2 presence unconfirmed; no trial/restore screen from catalog labels. Built editor. Earlier unbuilt notes superseded only for17.2.
Latest B17.3 (Pair1):GET /api/v1/admin/menu built, active verified administrator; role-filtered translated group/title/Lucide/localURL/order/parent, no role→empty.59 permissions,34 sidebar screens; tabs/actions no URLs. Queue-size page/permission removed, Horizon instead. B17.4+ business/viewer unbuilt; menu≠working destination, Pair2 availability unconfirmed. Menu states.