#FE: Admin panel screens (from backend Phase 17)
Frontend spec for backend Phase 17 — Admin panel — requirements complete 2026-10-08 (Pair 1); B17.1 backend access built2026-10-12, B17.2/B17.2a backend built; B17.3 sidebar backend built; B17.4 activity backend built; B17.6 users + B17.7 user details backend built (servers tab waits for Phase 8); B17.5 and B17.8 onward unbuilt, same flow as V7. The numbering gap in front of it closed the same day: Phases 14–16 are the three add-ons (Premium Hosting Care, Reseller panel, WP Toolkit), all now written, so 17 follows a complete run. V8 requirement The first admin phase the backend has published. Every admin screen on this site until now was a guess from V7; 17.1–17.23 replace that with rules.
i18n namespaces: admin.*, admin.users.*, admin.organizations.*, admin.servers.*, admin.settings.*, admin.errors.*.
#A. Getting in, and what you can see
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.1 | Admin sign-in | No new screen | As V7: an admin is a normal user account marked administrator — same login and the same token. Admin screens are refused for everyone else | So there is no second login page, and that is the useful part: the admin area is a section of the same app, reached by a user who happens to be an administrator. The refusal must be a clean not-for-you result, never a login prompt — a signed-in non-admin who reaches an admin address is not a session problem |
| 17.2 | Admin roles & permissions | Admin → Roles | Rewritten 2026-10-08. The admin permissions live in their own tables and seeder, separate from organization permissions, but in the same style as 4.9–4.11: one permission per admin feature, with view / manage. Admins create roles and set view / manage per permission. One role per admin. Every admin route checks its permission, including site settings, roles and DNS, which V7 left open. And the group list is now published — see the table below | Two lists, one component. The admin matrix is a different catalog from the organization one but has the same shape, so build the matrix once and point it at either. One role per admin means a picker, not a multi-select — the same rule as organization members. And the backend closing V7's three unguarded routes is worth honouring literally: no admin screen renders before its permission is known |
| 17.2a | Separate sensitive permissions | Roles list/detail/assignments read-only vs role changes | Clarified2026-10-12: Login as user remains its own manage-only permission. Admin roles & permissions has view and manage: view reads roles, permissions and admin-role assignments; manage creates/edits/deletes roles and assigns them. Users: manage grants neither | Read-only viewers see no mutation controls; managers get allowed changes. Future matrix uses catalog row shapes, no invented permission keys or endpoints; feature still unbuilt |
| 17.3 | Admin permission seeder & sidebar | Admin sidebar | Rewritten 2026-10-08, as 4.11: the admin seeder holds every admin permission with title, icon (a Lucide name), url, order and a parent group, synced by name + level and safe on every deploy. The sidebar shows only what the role can view, sorted by order | So the sidebar is data, not a constant — two admins see different menus, and the frontend cannot hard-code it or reorder it. A role with one permission must still produce a sensible panel, which means the landing page has to be "the first thing you can see", not a fixed dashboard. Same icon handling as the user side: resolve a Lucide name with a fallback when it is unknown |
| 17.4 | Admin activity log | Admin → Activity log | As V7: who did what, to which user / organization / server, and when | The target matters as much as the actor here, so each row preserves the target name; only link when a live authorized destination exists, otherwise plain snapshot text. This is the screen that answers "who changed this account", so it needs filtering by admin and by target |
#The admin permission groups (17.2, published 2026-10-08)
V7's groups, updated for V8. This is the admin sidebar's shape and the row list of the admin role matrix.
| Group | What it holds | Frontend notes |
|---|---|---|
| Dashboard | 17.5 | |
| User management | Users, roles & permissions, admin activity, deleted users, transactions. Per user: panel, status, account, log in as user, delete, create, organizations, servers, 2FA, IP whitelist, transactions, charges, invoices, login history, promo / redeem codes, plan, extra servers, Premium Hosting Care | By far the largest group, and it confirms that a single user's page is permission-gated item by item — so an admin can be allowed to see a user without being allowed to log in as them, or to touch their 2FA. That is the right granularity for the sharpest controls on 17.7 and 17.10, and it means those buttons are individually guarded, not covered by one "users" tick |
| Organizations | Panel, update, delete, members, servers, charges, deleted servers + restore, plan, backups | The deleted servers + restore entry is the same item flagged in the conflict below — it now appears as a named permission, which makes it harder to read as an oversight |
| Servers | Panel, details, overview, password login, apps, services, plan, settings, move server | "Password login" is new on this page and unexplained Open question — 17.12 never mentioned it. Move server confirms 17.13 |
| Premium Hosting Care | Its own group | So 14.9's subscription list and per-user edit have a real home in the sidebar, not just a corner of the user page |
| Alerts | Server usage, load averages | New — no item in 17.1–17.23 covers this Open question. An admin-side view of server usage and load alerts is a screen this spec has not described anywhere; it is presumably the administrative side of the per-server alert limits (9.28 / 11.13) |
| Referrals | Users, settings | This answers a complaint this spec made an hour earlier. FE: Referral & Affiliate objected that 18.9's top-referrers list sat awkwardly inside 17.19's general settings. It does not: Referrals is its own admin group with a users screen and a settings screen. The report gets its own page after all |
| Codes | Promo, redeem | Matches 17.17 / 17.18 |
| DNS | ServerAvatar DNS; White label DNS (view) | Exactly the split written on 2026-10-08 — and the view marking on the White label half is now a permission, confirming admins only look |
| Site settings | Basic, billing details, billing settings | |
| Integrations | SMTP, payment, social, cloud platforms | Three of these are deliberately absent from the frontend doc. Bhavik removed Admin sign-in keys and Admin notifications & mail on purpose and said never to re-add them. The backend having permissions for SMTP and social keys does not reverse that — it is recorded here and not proposed for the flow doc |
| Plans | Plans & feature list, plan overview, cloud provider price list | Matches 17.14–17.16 |
| Settings | User, trial, display message, temporary domain, other, settings from other phases | The "settings from other phases" catch-all is where Tolt's keys (18.4) and similar land |
| Debugging | Error monitor | Queue-size page/permission removed2026-10-12; Horizon is used instead. No new Central queue-health screen |
| Add-ons | WP Toolkit, Reseller panel, Log Monitoring | So the admin halves of Phases 13, 15 and 16 — grant / remove, per-user cycle and price, licence lists — sit in one add-ons area, rather than being scattered. Premium Hosting Care is the exception: it has its own group above |
#B. Dashboard
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.5 | Admin dashboard | Admin → Dashboard | As V7: totals, a transaction summary, server and transaction charts, and breakdowns by web server, provider and OS | Numbers and charts only — nothing to act on — so it can load in pieces and should never block on its slowest panel. The breakdowns are the one part with real operational use (which OS and web server the fleet actually runs), so they deserve to be readable rather than decorative |
#C. Users
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.6 | Users | Admin → Users | List, search, create, view, stats, status (active / pending / banned), delete, deleted users, referred users (as V7). ✅ Backend built 2026-10-12 (Pair 1) | Updated 2026-10-12: statuses are active (email verified), pending (email not verified yet) and banned (admin act) — no "locked" here; plan locking stays a Plans (7.12) matter. The list must name the status in words, not just colour the row. See Admin — Users. Deleted users is a separate list, which implies deletion here is recoverable or at least inspectable |
| 17.7 | User details | Admin → Users → one user | Their servers, organizations, login and activity history, 2FA (on / off, backup codes) and IP whitelist (as V7). ✅ Backend built 2026-10-12 (Pair 1) — servers tab waits for Phase 8; see Admin — User details | The 2FA and IP-whitelist controls are the sharpest things on this page: an admin turning off someone's 2FA is a security event, so it needs a confirm that says what it does, and it must land in the activity log (17.4). Backup codes must never be displayed here — the user's own screens already show them once (9.21's rule), and an admin does not need to see them |
| 17.8 | User billing | Same page, billing area | Transactions (add / edit), charges, invoices, and promo and redeem codes used (as V7) | Adding and editing a transaction by hand is money changing without a payment, so both need a reason field in the confirm and an activity-log entry. Charges and invoices are read-only history, so keep them visually separate from the two actions that write |
| 17.9 | User plan | Same page, plan area | A custom plan for one user (7.20), add-ons, the managed-server limit (6.9), the managed services pack, and extra servers (7.21 — extra slots for the user's own servers; limit = plan + extra; not counted in downgrade checks; kept when the plan changes; managed servers counted separately). Changes are logged | This is where the limits this spec has been tracking are actually set, so the screen must show the arithmetic rather than a single number: plan limit + extra servers, with the managed-server limit as a separate figure. Four different grants in one place (custom plan, add-ons, managed limit, extras) is easy to confuse — label each with what it affects |
| 17.10 | Log in as user | Log in as user action | As V7. Guarded on its own since 2026-10-08 (17.2a): a separate, manage-only permission — Users: manage does not include it | The most powerful button in the product. It needs a confirm naming the user, a visible indication while it is in effect, and a way back — and it must be in the activity log. Nothing here should be silent. And it now has its own permission, which is exactly right: the button should be absent, not disabled, for an admin who may edit users but not impersonate them — a disabled version of this control is an invitation |
#D. Organizations
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.11 | Organizations | Admin → Organizations | List, view, update, delete, members, servers, deleted servers & restore, backups (as V7) | Mostly a read-and-repair screen. One row needs a decision — see the conflict below: deleted servers & restore appears here on the admin side, while Bhavik ruled the feature is not in V8 |
#E. Servers
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.12 | Servers | Admin → Servers | List, usage and load, details, services (with the config test), apps (WordPress magic login), databases, system users (SSH on / off), reboot through the cloud provider — through the OSS API where the feature is in OSS (as V7). Install logs were removed on 2026-10-08: not in V8 | The same screens as the user's server panel (Phase 9), with the same dependency: if the panel is unreachable, most of this page is unavailable and must say so. One admin-only extra stands out: reboot through the provider, which does not go through OSS and therefore works when the panel does not. Install logs went the other way on 2026-10-08 — they were in the first version of this item and are now explicitly out of V8, so there is no log viewer to build and support reads the install's own progress and failure reason (8.9) instead |
| 17.13 | Move a server | Move server action | To another account or organization (as V7) | This settles the server-transfer question V8 requirement: it is an admin action, with no user-facing request flow — exactly the rule Bhavik set on 2026-10-07, so backend and frontend now agree. The confirm must name both sides (from whom, to whom), because the owner changes and with them the plan that governs the server |
#F. Plans, codes and billing
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.14 | Plans & feature list | Admin → Plans | Phase 7 (7.1, 7.2, and the 7.24 overview) | Already specced on FE: Plans & subscription from the Phase 7 side — nothing new here, which is the point: the admin plan editor and the user's plan page read the same catalogue |
| 17.15 | Promo codes | Admin → Promo codes | Create, on / off, delete (as V7, 7.13). ✅ Backend built 2026-10-14 (Pair 1) — see Admin — Promo codes | |
| 17.16 | Redeem codes | Admin → Redeem codes | Batches, codes, who used them, download, on / off (as V7, 7.23) | A batch is the unit, so the list is batches with codes inside — not thousands of rows. Download is the practical action, and "who used them" is the audit |
#G. Settings
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 17.17 | Site settings | Admin → Settings | Basic details and the company billing details (as V7) | The company billing details are what appear on every receipt (6.2), so changing them changes documents customers keep |
| 17.18 | Cloud providers & price list | Admin → Providers | Providers on / off, regions, sizes and managed-server prices (6.8) | This is the screen behind the managed-server pricing the user never sees (D-36), and behind which providers appear in the add-server wizard — so switching a provider off is a change users will notice immediately |
| 17.19 | General settings | Admin → General | Billing, trial mode (the backend still has this setting although V8 has no trial — Bhavik, 2026-10-09; see the conflict on FE: Plans & subscription), user, the referral program, a display message (banner) and the temporary domain (as V7). Filled in by 18.9 (2026-10-08): the referral settings are on / off, the new user's credit, the referrer's credit and the minimum payment — plus a top-referrers list | The display message is a frontend feature hiding in a settings list — a banner the admin can put in front of every user, which needs a home in the user-side layout. The referral program being here confirms it survives in V8, which the user-side referral section had been carrying from V7 without backing — and 18.9 now names its four fields — and 17.2 (an hour later) settles where they live. This spec objected that the top-referrers list was a report stranded in a settings page; it is not. Referrals is its own admin group, with a users screen and a settings screen, so the league table has its own page and only the four numeric settings stay in this area. The objection is withdrawn. See FE: Referral & Affiliate |
| 17.20 | Integration keys | Admin → Integrations. ✅ Part 1 backend built 2026-10-14 (Pair 1): social login, Turnstile, payment gateways — SMTP next — see Admin — Integration keys | SMTP + test mail (11.1), social login + Turnstile (Phase 2), payment gateways (6.1), cloud platforms (as V7) | Every field here is a secret: write-only, masked, never read back, with a visible replace action — the same rule as the White label keys (12.10). The test mail is the only honest proof the mail settings work |
| 17.21 | ServerAvatar's own DNS | Admin → DNS | Split out on 2026-10-08. ServerAvatar's own provider accounts (DNSimple / Route53, keys encrypted) and domains, managed by admins — V7's temporary, phpMyAdmin and file-manager types. Legacy only in V8: used to update old V7 records when a server's IP changes (9.29) and delete them when the app or server goes. Admins cannot add new ServerAvatar temporary domains — new apps get <app>.<server-ip>.nip.io with HTTPS from OSS (10.1) | This answers a question open on this site since Phase 10 — where a new app's temporary domain comes from. It is nip.io from OSS, not Central's DNS. So this screen is maintenance of the past: it keeps V7's domains resolving and has no "add" action at all, which is unusual enough to say on the screen rather than leaving an admin hunting for the button |
| 17.21a | A White label owner's DNS | Admin → the owner — read-only | New item 2026-10-08: each White label owner has their own DNS provider and domains, set by them in their own White label setup (12.10a) — not managed in the admin panel and not ServerAvatar's keys. It serves that owner's customers' temporary domains, as V7. Admins can only view it, for support | This corrects what this page said yesterday, which treated White label domains as something ServerAvatar's DNS served. They are not: the owner's DNS is the owner's, and the admin side only looks. So the admin view is read-only with no controls — and it must be obvious that these are someone else's credentials and records, not ServerAvatar's |
| 17.22 | Settings owned by other phases | Same area | Managed-server timing days and limit default (Phase 6), plan expiry days and reminder weekdays (7.10–7.12), the partner list for the free managed server (8.6 / 12.12), the default manage domain (Phase 12), announcements (Phase 11) | Useful as a map: five numbers and lists this spec has described as "an admin setting" all live here. The partner list is the one that answers a real gap — it is how the free managed server (D-41) is actually gated |
| 17.23 | Error monitor | Admin → Errors | As V7: caught errors saved with page or command, request details and message; admins list, open and mark resolved; old entries cleared automatically (V7: 2 days). Passwords, tokens and keys are stripped from request details before saving | A support screen, and the stripping rule is the part to respect on screen too: never render a raw request body as if it were safe. "Mark resolved" is the only action, so the list is a queue — and the automatic clear-out means the screen should say how long entries live, or admins will think they lost something |
#What this phase answers
| Open item | Answer |
|---|---|
| The whole admin side — every admin page on this site was a V7 guess, and the frontend doc keeps its admin sections as proposals | Now specified (17.1–17.23) V8 requirement, so the proposals can be checked against real rules |
| Is there a separate admin login? | No — 17.1. An admin is an ordinary account marked administrator, same login and token |
| How do V7's admin permissions become view / manage? | Answered 2026-10-08 (17.2 Existing users): a V7 list or panel permission becomes view; a create / update / delete / status action becomes manage — user-list, user-panel, account → Users (view); user-status, create, user-account-delete → Users (manage); and the same split for transactions, charges, promo codes, DNS, organizations and deleted servers. user-account-login → Login as user, role-permissions → Admin roles & permissions. No admin loses access. Worth comparing with the organization side: Phase 4's mapping had to widen access where V7 was finer, and lists the widened cases in a report. This one does not — V7's admin permissions were already action-shaped, so they split cleanly into view and manage. The admin migration is the more precise of the two |
| Server transfer | Answered — 17.13: an admin moves a server to another account or organization, with no user request flow. This matches Bhavik's 2026-10-07 rule exactly, so the two now agree |
| Where does a new app's temporary domain come from? | nip.io from OSS — <app>.<server-ip>.nip.io with HTTPS (10.1, 17.21). And there are two separate DNS settings, clarified 2026-10-08: ServerAvatar's own (admin, legacy only, no new domains) and each White label owner's own (theirs, set in White label, admin view-only) |
| How is the free managed server gated? | A partner list in the admin settings (17.22, with 8.6 / 12.12) — one more piece of D-41 |
| Does the referral program survive V8? | Yes — it is an admin setting in 17.19, which gives the user-side referral screens their first backing |
| Are affiliates dropped? | From Central, yes — entirely. Answered by Phase 18 on 2026-10-08, and it corrects what this row said a few hours earlier. The morning's note said the admin side was dropped "but the user-side affiliate is kept", which this spec read as the user keeping an affiliate area. Phase 18 (18.3) says Central has no affiliate dashboard, no commission slabs and no payouts — the affiliate programme runs in Tolt, an outside service. "Kept" means affiliates keep earning, not that they get a screen here. So nobody gets an affiliate screen, user or admin, and V7's built-in programme (apply form, approval, slabs, PayPal payouts, banners, custom links) is not in V8. The one thing Central still does is invisible: it saves the Tolt code at sign-up and sends it with Stripe payments. At 09:19 the backend tightened its own wording to match — 17's not-in-V8 list now reads "the user-side affiliate is kept — Phase 18, via Tolt", which is the same clarification, in its words rather than this spec's. See FE: Referral & Affiliate |
| Are support tickets dropped? | Yes — entirely, decided 2026-10-08. Both docs now say support tickets are not in V8: there is no Support phase, the three support-ticket emails and two notifications are dropped (Phase 11), and V7's support permission has no key in 4.9. So nothing anywhere should leave room for a ticket screen |
| "Free forever" and the sign-up "free Pro server" | Confirmed not in V8 (17's not-in-V8 list), consistent with 7.21's extra servers |
#Still open after this phase
| # | Question |
|---|---|
| D-50 | What does the admin panel look like? Narrowed on 2026-10-08: 17.2 and 17.3 now specify the navigation — fifteen published groups, built from the admin's own seeder with title, Lucide icon, url and order, showing only what the role can view. What is still unwritten is the shell: whether the admin area is a section of the same app or its own layout, and where an admin with a single permission lands. So the menu is answered and the frame is not. The frontend doc keeps its admin sections as proposals |
| — | The migration reports need a home — and there are now two of them. V7 admins with several roles become one combined role (e.g. "Support + Billing"), shared where the sets match, and "the migration report lists every combined role created" Open question. On the organization side (4.9) a second report lists the roles whose access was widened because V7 was finer. Two generated reports, no screen named for either, and both are things somebody needs to read once, soon after the move — which argues for one place rather than two |
| — | 17.11's deleted servers & restore contradicts Bhavik's 2026-10-07 rule Conflict — see the callout above. Admin-only may be a different decision from user-facing |
| — | Old V7 temporary domains must stay registered and paid, which the backend calls a company task (17.21 Existing users) Open question — no screen, but if one lapses the apps using it break, and nothing says who would see that |
| — |
#Admin — Discover and enter (B17.1 backend built)
🆕 Route/navigation: normal Login → existing user panel → proposed “Open Admin Panel” control → /admin guarded entry/identity state. This is an entry screen, not a working dashboard/sidebar. Backend: Pair1 API49–50, B17.1 built; Pair2 availability not reported. Permission: active login; guarded entry additionally requires verified email and exact administrator identity; no organization-policy bypass. i18n: admin.access.*, admin.errors.*, common.*.
- Reuse normal password/social/2FA/IP/refresh/logout flows; no separate admin sign-in credentials, keys or token. Existing login/profile response fields unchanged, so do not expect an admin flag embedded there.
- Discover with
GET /api/v1/account/admin-access(own account only, no target/query/body selection).200{data:{role,is_administrator}}, machine keys. Customers→false→ordinary panel without entry control. Active unverified administrators may get true→entry control may show, but protected entry will still require verification. Never translate role key before comparison or normalize unknown case/space variants into admin rights. - On entry call
GET /api/v1/admin/me;200{data:{is_administrator:true,user:{id,name,email,status,email_verified,email_verified_at,created_at}}}. Show only own identity and clear “Admin features not available yet” entry state; no dashboard counts, action cards or role-derived sidebar invented. No business endpoint/promotion/edit-role UI exists. 4.401unauthenticated→normal Login;403admin_access_denied→safe refusal/back to user panel;403email_not_verified→existing verification flow then retry;403account_banned→support refusal;403api_token_not_allowed→panel login, not token substitution.429 shared60/min/account→respect Retry-After. Network/error state→safe retry/back, never grant entry from stale flag. - Both responses private/no-store. Reset discovery/identity on logout or account change; current role/status/verification can revoke access with an existing token. On subsequent denial clear admin context; do not keep protected data visible from cached true flag. Flag means navigation eligibility, NOT every-feature authorization.
- Done when: customer hidden/direct-route refusal, verified admin identity, unverified discovery+entry denial/verification retry, session expiry/banned/token/rate-limit/network states and role-removal after discovery all work without exposing another user. B17.2 permissions and lockout guards now backend-built; B17.3 sidebar and B17.4 viewer now backend-built. No real account automatically promoted; operator-only marking is not a frontend action. Backend reports1501 tests/9118 assertions,96 admin/role tests,36 live checks and quality/fresh-install passes; not rerun by docs sync.
Build boundary: administrator identity ≠ staff feature role. No “Users manage permits Login as user” inference, no permission catalog/menu API invented, no bypass of organization access, and no removed admin sign-in-key/settings section restored.
#Admin — Read-only roles and role management (B17.2a clarification; unbuilt)
🆕 Proposed route/navigation: Admin → staff Roles (/admin/roles, list/detail/assignments); proposed path, no API endpoint/catalog key published. i18n: admin.roles.*, admin.permissions.*, admin.errors.*. Separate from organization roles. B17.1 identity grants no permission to this feature.
- With Admin roles & permissions view: list roles→select role→read its permission flags and see which admin holds which role. Hide create/edit/delete/assign controls; do not expose writable forms or submit mutations from a read-only page.
- With manage: allow create/edit/delete roles and assign them, one staff role/admin; use future backend rules/catalog, not hardcoded organization keys. Last-privileged-role/self-edit guards and mutation confirmation/error contracts remain unpublished/unbuilt; do not claim safeguards implemented.
- Users: manage alone cannot view/manage these roles or Login as user. Login as user stays separately manage-only, not a view flag and not included by staff-role viewing.
- States: checking permission/loading/roles/empty/read-only detail/assignment list/denied/revoked/session expired/retry; manager form/saving/validation/result remain proposed pending real contracts. Permission loss removes controls and preserves denial, no browser-only authorization.
- Done when: future catalog defines exact keys/endpoints, view list/detail/assignments succeeds while every mutation denied, manage changes work with published safeguards, Users-manage-only cannot enter, impersonation remains independent, locale/error/empty/revocation cases pass. B17.2/17.3 still not built; no new product conflict.
#Admin — Built staff role editor and assignments (B17.2/17.2a)
🆕 Routes/navigation: Admin → /admin/roles list → proposed /admin/roles/{id} detail/editor; assignments on staff-role page (/admin/administrators, proposed). i18n: admin.roles.*, admin.permissions.*, admin.errors.*. Pair1 built API51–58; Pair2 availability unconfirmed. Active verified administrator login; reads require admin-roles view, writes manage. Customers/tokens/banned/unverified refused; discovery flag alone grants no feature access.
GET /api/v1/admin/menow addsadmin_roleand effectivepermissions; preserve old identity fields. No role means no assumed business access. Separate from organization permissions, no global policy bypass.- Catalog
GET /admin/permissions:59 entries sorted order, translated title,name/group/parent/requires/can_view/can_manage/order. Render allowed checkbox shapes; only Login as user manage-only, four read-only areas view-only. Admin roles view+manage. Don't use normalized savedview:trueon manage-only rows as a selectable View control. Menu icon/url NOT published until17.3; catalog entries don't prove corresponding business screens built. No trial or Deleted servers/Restore UI re-added from catalog labels. - List
GET /admin/roles: fixed Super Admin first, then custom names/counts;GET /admin/roles/{id}permissions/detail. Fixed role clearly read-only, no edit/delete. List administratorsGET /admin/administrators:name/email/status/verified/assigned role or None; read-only viewers see assignments but no controls. Customers never included. - Create
POST /admin/roles: name required≤50, unique including Super Admin; permissions required array (can empty)≤200, unique known names, optional boolean view/manage. Neither=true ignored;manage includes view; parents automatically get view.201→created detail/list refresh. Don't mutate organization roles or auto grant new permissions to custom roles. - Update
PATCH /admin/roles/{id}: optional name;permissionsreplaces WHOLE set. Keep complete selected set; omission preserves permissions, empty removes all.200→returned detail/list. Role manager may lose own permissions; refresh effective access afterwards. No published version/conflict field—do not invent one. - Delete
DELETE /admin/roles/{id}: proposed naming confirmation→200 result/list.422admin_role_in_usewith count→assign admins elsewhere first;422admin_role_fixed→immutable Super Admin;422admin_role_lockout→must retain an active verified role manager. No force delete or bypass. - Assign
PUT /admin/administrators/{user_id}/role{admin_role_id:ID|null}: change/remove one role; same role no-op.200→returned assignment,refresh own effective permissions if affected.404 customer/missing user→reload, not promotion.422 unknown role inline; lockout refusal retains assignments. No UI for operator-only first Super Admin/promotion. - Loading/empty/list/detail/read-only/editing/saving/deleting/assigning/success; field422 preserves edits; fixed/in-use/lockout translated refusal;404 reload;401 normalLogin;403 denied/verification/banned/token;429 wait/retry. Prevent duplicate submissions, on failures don't optimistically erase roles/assignments. Separate admin activity shown by B17.4; personal/organization activity unchanged.
- Done when: view reads only, manage changes, catalog shape/parent normalization/full replacement, fixed/in-use/customer restrictions, last-manager refusal and competing demotion result handling, self-revocation/refresh,empty/error/locale cases pass. Backend reports1545 tests,Pint/PHPStan,26 actualHTTPS/MariaDB checks incl mutual-demotion race; not rerun here.17.3 menu/sidebar still unbuilt; no real account promoted.
Latest built rules above supersede earlier unbuilt/API-pending notes for17.2 only.
#Admin — Role-filtered sidebar (B17.3 backend built)
🆕 Route/navigation: /admin shell → own admin sidebar. Backend: Pair1 API59 GET /api/v1/admin/menu; no input. Permission: active verified administrator login;customers/API tokens refused. i18n: admin.navigation.*, admin.errors.*; labels title/group_title already translated by Accept-Language.
-200 {data:[{name,title,icon,url,group,group_title,parent,order}]}. Render returned screen items by order, grouped by translated group_title; derive nested parent relationships by name. Map returned Lucide names through safe icon lookup with fallback; use provided local /admin path, not inferred route from permission key. Preserve all metadata; don't merge organization menus.
-34 screen entries possible for SuperAdmin, not a fixed visible count for everyone. No staff role→200 empty list: “No admin pages are available for your role”, normal-panel back link. Empty is not a failed request or grant to all pages.59 permissions total; tabs/actions(no url) stay out of sidebar but remain role-editor permissions. Login as user is not navigation.
-Loading skeleton→menu/empty;network error→retry/back, no static full-menu fallback;401→normalLogin;403 admin_access_denied/verification/banned/token→safe refusal/existing verification as appropriate;429 respect wait. Private/no-store; refresh after role/locale changes, clear on logout/account change. A stale item never overrides destination denial; subsequent revocation clears admin context.
-Navigation only: endpoint/menu availability does NOT build dashboard/users/settings/etc. B17.5 onward remain unbuilt; present unavailable destination states until screen/contract exists. No trial or Deleted servers/Restore product flows inferred from catalog/menu. Queue-size page + debugging.queue removed; Horizon replaces it, no fabricated Horizon automatic-login link/access entitlement.
- Done when: own-role filtering/SuperAdmin/empty role, translated grouping/order/parents/icons, role/locale refresh, denied/expired/retry states and safe-local routing pass without revealing cached other-user menus; destination authorization independent. Pair2 code availability unconfirmed; no claim frontend implementation/real-account promotion. Sidebar specification only; backend menu built.
B17.3 notes above supersede earlier menu/API-unbuilt wording. B17.4 viewer now backend-built; B17.5+ business screens still wait.
#Admin — Activity list and filters (B17.4 backend built)
🆕 Route/navigation: Admin menu → Activity log (/admin/activity, follow menu URL); read-only table. Backend: Pair1 API60 GET /api/v1/admin/activity. Permission: active verified administrator login + admin-activity view;SuperAdmin allowed;personal tokens/customer/banned refused. i18n: admin.activity.*, admin.errors.*;description/labels/filter options translated by Accept-Language. Pair2 availability unconfirmed.
- Newest-first rows: Time,Admin name snapshot,Type/Action labels,Description,Target(type/name),IP,Browser/Platform. Admin/target history survives deletion; actor.id may be null,subject may be null. Preserve snapshot names, no fake live links/unknown-person errors. Only link known authorized existing destinations; missing targets show plain text. No raw property/secret/request dump or invented detail/export/mutation control.
- Query
pageinteger≥1,per_page1–50 default10;type,actioncreate/update/delete,actor_idfrom admins;subject_typeuser/organization/server/admin_role, required with integersubject_id;from/toinclusiveYYYY-MM-DD,ordered range;search≤100 actor OR target name. Combine filters, resetpage1 on change;Clear returns unfiltered list. Don't turn name search into email/IP search or invent target autocomplete API. -200data/links/meta/filters. Dropdowns fromfilters.types/actions/admins, not hardcoded available event sets. Page controls follow pagination metadata; scoped configured API for requests, not blindly use example host. Translated labels refreshed with locale; numeric/date display through locale formatting. -Loading/table/emptylog/no matches/filter validation/retry;422 inline filter error preserves valid selections (subject_type required with ID,invaliddaterange);401→Login;403admin_permission_denied→safe refusal/back, verification/banned/token as standard;429shared60/min→Retry-After. Private/no-store,clear on account/logout/access loss;do not expose cached other-admin rows. -Only admin-panel actions, separate from account/organization feeds; staff-role events now appear here, not personal scope. Admin role manager without admin-activity view cannot read this page. No permission bypass, retention-period promise or claim all business actions already implemented. - Done when: allowed/denied/table/snapshotnulls,allcombinedfilters+date/searchlimits,pagination/empty/validation/locale/currentaccess/retry/privacy pass; existing account/org activity unaffected. Backend reports built but publishes no new final test count for17.4; don't relabel17.2 checks as17.4 verification. Businessscreens17.5+ stillunbuilt.
#Admin — Users: list, create, ban, delete (B17.6 backend built)
🆕 Route/navigation: Admin menu → Users (/admin/users, follow the menu URL) · one user /admin/users/{id} (details tabs: B17.7 below) · Deleted users /admin/users/deleted · Referred users /admin/users/referred. Backend: Pair 1 API61–68 (/api/v1/admin/users…). Permission: active verified administrator; users view (list/counts/view), users manage (create/ban/unban/verify/delete), users.deleted view (deleted list), referrals view (referred list); Super Admin passes. i18n: admin.users.*, admin.errors.*. Pair 2 availability unconfirmed.
- Counts row (API62): total, active, pending, banned, administrators, new in last 30 days, deleted — numbers from the API, locale-formatted.
- List (API61): name, email, status (Active / Pending / Banned — use
status_label), role (customer / administrator + admin role), referral code, organizations count, last login, signed up. Filters: search (name/email contains, or exact ID), status, role, referral code, sign-up date range; sort by signed up / name / email, asc/desc; 10 per page (max 50). Filter change → page 1; Clear → all users. Loading / empty / no matches / 422 inline filter error. - View (API63): the same fields on one page. Unknown or deleted user → 404 "not found" page with a link back to Users.
- Create user (API64)
MODAL: name, email, password (min 8), "Mark email as verified" (on by default; off → the user gets the normal verification email). Always a customer — no role picker. ✔TOAST"User created." → user page. ✖ email taken → inline field error, inputs kept. - Ban / Unban / Verify (API65): Ban
CONFIRM(says the user is logged out of every device) →TOAST"User status updated." + status badge refresh. Unban →TOAST. Verify only for Pending → Active. Repeating an action already in effect changes nothing. - Delete user (API66)
TYPE-TO-CONFIRMwith optional reason (max 1000): says owned organizations are deleted (members lose access), memberships removed, wallet/payments/cards closed, user logged out, the email can sign up again. The user's own delete protection does not block an admin; banned users can be deleted. ✔TOAST"User deleted." → Users list. ✖ 409 user owes money / open payment → show the backend message, nothing deleted. - Protected targets: hide Ban/Delete on your own row and on administrators; if the API still answers 403
admin_target_protected→ "You cannot ban or delete your own account or another administrator." - Deleted users (API67): name, email, reason, deleted by (Self / Admin), server count, deleted at; search, deleted-by filter, deletion date range, pagination. Read-only — no restore.
- Referred users (API68): same table/filters as the list; search also matches the referral code. Read-only.
- Errors/states: 401→Login; 403
admin_permission_denied→refusal/back (manage buttons hidden for view-only roles); 429 (60/min)→wait/retry; private/no-store, clear cached rows on logout/access loss. Every admin action is shown in Admin → Activity log with the user as target. - Done when: counts/list/filters/sort/pagination, view + 404, create (verified on/off, email taken), ban/unban/verify, delete (reason, 409 debt/open payment), self/administrator protection, deleted + referred lists, view-only vs manage, locale and error states pass. Backend built by Pair 1 only; no frontend built yet.
#Admin — User details tabs (B17.7 backend built)
🆕 Route/navigation: Admin → Users → one user (/admin/users/{id}) → tabs: Overview (B17.6) · Organizations · Login history · Activity · Two-factor · IP whitelist · Servers (waits for Phase 8 — show "coming soon", no fake data). Show only the tabs the admin's role can view. Backend: Pair 1 API69–76. Permission: active verified administrator + per tab: users.organizations view, users.login-history view, users.activity view (new, view-only; 60 admin permissions now), users.two-factor view/manage, users.ip-whitelist view/manage; Super Admin passes. i18n: admin.users.details.*, admin.errors.*.
- Organizations (API69): name, Owner / member badge, role name, designation, members count, joined date. Read-only list, no pagination. Empty → "Not in any organization."
- Login history (API70): time, IP, browser, platform, method; date range filter; newest first, 10 per page (max 50).
- Activity (API71): the user's own account activity — time, type, action, description, IP, browser/platform; filters type, action, date range; rows with
by_adminshow a "By ServerAvatar admin" badge. Paginated like login history. - Two-factor (API72–73): on/off, method, backup codes as counts only (total / available / used, generated date) — the codes themselves are never shown and admins can't regenerate them. Turn off 2FA
CONFIRM(says the user's 2FA method and backup codes are removed and they get a security email) →TOAST"Two-factor authentication turned off for the user." Already off → button hidden. - IP whitelist (API74–76): on/off + IPs with status Approved / Pending (waiting for the emailed approval link). Turn off whitelist
CONFIRM(removes every IP) →TOAST"IP whitelist turned off for the user." Remove IPCONFIRM→TOAST"IP removed from the user's whitelist." + refreshed list. Admins cannot add IPs (no Add button). - Protected targets: on your own account or another administrator, hide the change buttons; a 403
admin_target_protectedstill shows the refusal message. Unknown/deleted user or IP not belonging to the user → 404 not-found state with a link back. - Effects to show in copy: admin changes behave like the user's own action (same security emails) and appear in the user's activity as done by a ServerAvatar admin, and in Admin → Activity log.
- States: loading/empty/no matches/422 filter error per tab; 401→Login; 403
admin_permission_denied→tab hidden or refusal; 429→wait/retry; private/no-store, clear on logout/access loss. - Done when: per-tab permission visibility, organizations list, both paginated tabs + filters, 2FA counts-only + turn off, whitelist view/turn off/remove IP (+404), protected-target refusals, by-admin badge, Servers tab placeholder and error states pass. Backend built by Pair 1 only; Pair 2 availability unconfirmed.
#Admin — Login as user (B17.10 backend built)
🆕 Route/navigation: Admin → Users → one user → Login as user button (header action, not a sidebar item). Backend: Pair 1 API77 POST /admin/users/{id}/login-as. Permission: users.login-as manage only — "Users: manage" alone is not enough; hide the button without it. i18n: admin.users.loginAs.*.
- Login as user
CONFIRM("You will be signed in as {name}. Their password, 2FA and IP whitelist are skipped.") → ✔ 200 returns a normal login for that user (same shape as Login) + message "You are now logged in as {name}." → open the user panel (Dashboard) with that session. Works for unverified users. - ✖ own account / another administrator → 403
admin_target_protected(button hidden there anyway) · ✖ banned → 403user_banned"This user is banned. Unban them before logging in as them." (offer Unban if the admin may) · ✖ deleted/unknown → 404. - Only the admin activity log records it — not the user's login history or activity, and the user gets no email. The session lasts like a normal login (refresh/logout as usual).
- Open (frontend): the backend has no "return to admin" call. The frontend must not overwrite the admin's own session — e.g. open the user session in a new tab / separate session and show a clear "Logged in as {name} — Log out" banner. Needs Bhavik's decision on the exact behaviour (V7 reference).
- Done when: permission-hidden button, confirm, success → user dashboard in a separate session with banner, banned/protected/404 errors, admin session kept intact.
#Admin — Promo codes (B17.15 backend built)
🆕 Route/navigation: Admin menu → Promo codes (/admin/promo-codes, follow the menu URL). Backend: Pair 1 API78–81. Permission: codes.promo view (list) / manage (create, on/off, delete); hide manage buttons for view-only roles. i18n: admin.promoCodes.*, admin.errors.*.
- List (API78): code, type (Discount / Free credits), value (discount % or credit amount), customer type (All / New / Existing), status (Active / Disabled / Expired / Used up), expires, uses / usage limit, credit valid days (free credits only), created. Search (part of code), filters type / customer type / status, sort created / code / value / uses, asc/desc, 10 per page (max 50). Empty / no matches / 422 filter error. Deleted codes are not listed.
- Create (API79)
MODAL: code (letters, digits,-,_, max 64), type, value (> 0, 2 decimals; discount below 100, free credits max 100000), customer type, on/off (default on), expires in days (optional 1–3650), usage limit (optional 1–1,000,000), credit valid days (required for free credits 1–36500, hidden for discount). Expiry and usage limit can be combined. No description field. ✔TOAST"Promo code created." → list. ✖ code taken (also by a deleted code) → field error "This promo code already exists (it may have been deleted). Choose another code." - After creation only on / off can change — no edit form. Toggle (API80) →
TOAST"Promo code turned on." / "turned off." - Delete (API81)
CONFIRM: says the code can't be used any more, leaves the list, its name stays taken and past payments/redemptions keep showing it; no restore. ✔TOAST"Promo code deleted." ✖ 404 already deleted → refresh list. - Note: customer type New / Existing only matches users whose promo customer type has been set (today by an operator command) — say so in the help text so admins aren't surprised.
- States: loading/empty/validation/saving/toggling/deleting/success; 401→Login; 403
admin_permission_denied; 429 retry. Every create/on/off/delete appears in Admin → Activity log. - Done when: list filters/sort/pagination, create validation per type, duplicate-code error, toggle, delete + 404, view-only vs manage pass.
#Admin — Integration keys, Part 1 (B17.20 backend built)
🆕 Route/navigation: Admin menu → Integrations (/admin/integrations, follow the menu URL) → tabs Social login · Turnstile · Payment gateways (SMTP + test mail = Part 2, not built; cloud platforms — v8 meaning still to be confirmed by the backend, no tab). Backend: Pair 1 API82–88. Permission: integrations.social view/manage (Social login + Turnstile), integrations.payment view/manage (Payment gateways); hide Save/toggles for view-only. i18n: admin.integrations.*.
- Secrets are write-only: the API never returns them — show "Saved" / "Not set" (
*_set,configured) and an empty password field with placeholder "Leave empty to keep the saved value". Never prefill or echo a secret. - Social login (API82–83): one card each for GitHub and Google: on/off, client ID, client secret, and the callback URL (read-only, copy button) to enter in the GitHub/Google app. Save →
TOAST"Social login settings saved." ✖ turning on without both keys → "Add the client ID and client secret before turning this login on." - Turnstile (API84–85): site key + secret key (secret required the first time). Save →
TOAST"Turnstile keys saved." ✖ "Enter the secret key." - Payment gateways (API86–88): one card each for Stripe, PayPal, Instamojo: on/off, active mode (Test / Live), which modes are configured, the gateway's key fields (from
fields, rendered dynamically — don't hard-code), and the webhook URL per configured mode (copy button; changes when that mode's keys change — say so). Save keys for a mode → that mode becomes active →TOAST"Payment gateway settings saved." ✖ "Enter every key for this mode before saving." On/off toggle →TOAST"Payment gateway turned on/off." ✖ active mode has no complete keys → same message, toggle stays off. - States: loading/saving/validation/success; 401→Login; 403
admin_permission_denied; 429 retry. Every save appears in Admin → Activity log (no key values). - Done when: secrets never shown, keep-saved-value behaviour, turn-on guards, mode switching, webhook URL copy, per-permission view/manage pass. This also covers the earlier deferred "Admin → Payment gateways" screen (B6.1).