#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.9 onward mostly unbuilt; B17.8 user billing Parts 1–2 built 2026-10-30 — see Admin — User billing, 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)
Update 2026-10-26 (Pair 1, Vishal): V8 requirement The four add-on screens (Premium Hosting Care, WP Toolkit, Reseller panel, Log monitoring) are now one sidebar item, System Add-ons (
/admin/system-addons, no group heading). One permissionsystem-addonsreplaceshosting-care,addons.wp-toolkit,addons.resellerandaddons.log-monitoring. The user-details tab Premium Hosting Care stays. Now 51 admin permissions, 22 sidebar screens. Screen spec: section Admin — System Add-ons at the end of this page. Update 2026-10-23 (Pair 1, Vishal): V8 requirement Referral Settings is no longer a sidebar item. Marketing → Referrals (/admin/referrals) is one screen with two tabs: Referred users · Settings (/admin/referrals/settings, no sidebar item). Thereferrals.settingspermission is removed; the settings tab usesreferralsview (read) / manage (save). API108–109 URLs and responses are unchanged. Now 54 admin permissions, 25 sidebar screens. Update 2026-10-27 (Pair 1): Customers is renamed User Management (Users, Deleted users). A new Managed Servers section (after Billing & Plans) holds Server Plans (moved out of Integrations; new path/admin/managed-servers/plans) and a new Managed Server Settings screen (API166): the unpaid-credit days — due / retention / deletion, normal and trial, each 1–30 days (defaults 4/3/7 and 2/2/4). A server that's already counting down keeps its dates. Admin roles that had Server Plans get both screens.
Regrouped 2026-10-21 (Pair 1, Vishal — data only, API59
/admin/menu). V8 requirement The sidebar now has 11 sections, in this order: Dashboard · Customers · Roles & permissions · Servers · Billing & Plans · Marketing · Integrations · System Addons · Settings · Admin activity · Error monitor. A section with one screen has no heading (group_title: null) — render the item on its own. Group keys changed (users→customers,plans→billing,referrals+codes→marketing,hosting-care→addons, newadmin-roles,admin-activity) andorderwas renumbered — the frontend must keep reading the menu from the API, never hard-code it. "Admin Roles & Permissions" is now "Roles & Permissions"; Billing settings is no longer under Site settings. Removed (not in V8): Plan overview, ServerAvatar DNS, White label DNS — do not build them. Catalog: 53 permissions, 27 sidebar screens. The table below is the older 2026-10-08 grouping, kept for history.
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 | |
| 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 |
Removed 2026-10-21 (Pair 1, Vishal — not in V8): the admin alerts permission and its /admin/alerts sidebar screen are gone; no screen or API was ever built behind it. Do not build an admin Alerts screen. The admin Slack webhook (17.19) and the users' own server alerts (9.28 / 11.13) stay. Catalog now 56 permissions, 30 sidebar screens. Older note: New — no item in 17.1–17.23 covers this. 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 |
| 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, | 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 (now Billing & Plans) | Plans & feature 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 was where Tolt's keys (18.4) would land — 18.4 is not in V8 (Pair 1, 2026-10-31), so no Tolt fields |
| 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 — since 2026-10-26 one screen, System Add-ons (17.24), see the section at the end | 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 and IP whitelist — Pair 1, 2026-10-31: status, turn off, remove an IP only (no admin turn-on, no backup codes, no adding IPs — unlike 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. Parts 1–2 built 2026-10-30 (Pair 1) — payments, receipts, credit history, managed-server charges, promo codes used, plus add / edit payment (with Refunded). Payments are records only: credits are set from Edit user (paid / free new totals). See Admin — User billing |
| 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 | Users → user → Organizations → one organization | Revised 2026-10-16 (Pair 1, Vishal): no separate admin list of all organizations. The organization's tabs live under the user's Organizations tab (17.7): Members, Servers, Charges, Deleted servers (with restore), Subscription, Backups — permissions users.organizations.members / .servers / .charges / .deleted-servers / .subscription / .backups (view / manage). Endpoints: none yet; members can be built now, charges + subscription with Phase 7, servers / deleted servers / backups with Phase 8. Update 2026-10-22 (Pair 1 status): the organization Servers and Deleted servers tabs are now built (with 17.12 Part 1); charges, subscription, backups and deleted-server restore are still to come — keep restore hidden (see the conflict below). Catalog 59 permissions, 33 sidebar screens | No Admin → Organizations sidebar item. In the user's Organizations tab, a row opens the organization with these tabs (show only tabs the sidebar/permissions allow; see D-62). Conflict Deleted servers + restore — see the callout below |
#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. ✅ Part 1 backend built 2026-10-17 (Pair 1) — list, details, edit, deleted list; live parts later — see Admin — Servers Part 1 |
| 17.13 | Move a server | Move server action | To another account or organization (as V7) — backend built 2026-10-23 (API138, see the section at the end of this page) | 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 | The company billing details are what appear on every receipt (6.2), so changing them changes documents customers keep. ✅ Backend built 2026-10-16 (Pair 1) — see Admin — Site settings |
| 17.18 | Server Plans (was: Cloud providers & price list) | Admin → Managed Servers → Server Plans (moved from Integrations 2026-10-27) | Providers on / off, regions, sizes and managed-server prices (6.8) — backend built 2026-10-23 (API139–145, see the section at the end of this page) | This is the screen behind the managed-server pricing the user never sees (D-36). Corrected 2026-10-23: these are ServerAvatar's own provider accounts, used only for managed servers. They are separate from customers' cloud accounts, so switching one off does not change the user's Add server wizard |
| 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. ✅ Backend built 2026-10-17 (Pair 1) — see Admin — General settings |
| 17.20 | Integration keys | Admin → Integrations. ✅ Backend built (Pair 1): social login, Turnstile, payment gateways 2026-10-14; SMTP + test mail 2026-10-15; cloud platforms still to confirm — 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~~ Removed 2026-10-21 (no admin DNS screens in V8) | 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~~ Removed 2026-10-21 (no admin DNS screens in V8) | 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. ✅ Backend built 2026-10-16 (Pair 1) — see Admin — Error monitor |
#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 (17.11 itself is Not in V8 since 2026-10-16). 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(removed 2026-10-16 — useGET /api/v1/account/admin-accessis_administratorfrom login/profile) (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(removed 2026-10-16 — on entry loadGET /api/v1/admin/meGET /admin/menu; 401/403 there = not an active verified administrator → back to user panel);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.
(removed 2026-10-16 — no per-permission list for the frontend); preserve old identity fields. No role means no assumed business access. Separate from organization permissions, no global policy bypass.GET /api/v1/admin/menow addsadmin_roleand effectivepermissions- 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.
-33 screen entries possible for SuperAdmin (34 before B17.11 removed Organizations, 2026-10-16), 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. 53 permissions total (59 before B17.11, 2026-10-16); 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;(superseded 2026-10-16 — allowed now; see note at the end) if the API still answers 403admin_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;(superseded 2026-10-16 — allowed now) a 403admin_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(2026-10-16: other admins allowed; own account →admin_target_protectedlogin_as_self, hide the button on your own row) · ✖ 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 SMTP · Social login · Turnstile · Payment gateways (SMTP built 2026-10-15, see below; 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).
Admin entry from the profile (Pair 1, 2026-10-15): GET /account/profile now includes role + is_administrator: true for administrators on a login token (customers and personal API tokens get neither key). Use it to show the Admin panel link in the user menu. Still verify on entry with — removed 2026-10-16; entry is checked by loading GET /admin/meGET /admin/menu.
#Admin — Integration keys: SMTP + test email (B17.20 Part 2, backend built 2026-10-15)
- Backend: Pair 1 API89–92. Permission:
integrations.smtpview / manage. i18n:admin.integrations.smtp.*. - View (API89): shows which settings are in use — Saved settings (
source: database) or Server defaults (source: env, until an admin saves some) — with host, port, encryption, username, password Saved / Not set (never shown), from address, from name. - Save (API90) form: host (name or IP only — no
smtp://, port or path), port (1–65535), encryption (SSL usually 465 / TLS (STARTTLS) usually 587 / None — internal relays only), username (optional), password (optional; empty keeps the saved one), from address, from name. ✔TOAST"SMTP settings saved." — used from the next email, no restart. ✖ 422 field errors inline. - Send test email (API91)
MODAL: email address → ✔TOAST"Test email sent to {email}." ✖ 422 short reason shown as is (server not reachable, login rejected, timeout, wrong encryption, other server error). Limit 5 per minute → wait message. - Use server defaults (API92)
CONFIRM("Saved SMTP settings will be removed and emails will use the server defaults") →TOAST"Saved SMTP settings removed. Emails now use the server defaults." → view shows Server defaults. - Done when: source badge, save validation, password write-only, test email success + every failure reason, reset to defaults and view/manage permission pass.
#Admin — Site settings (B17.17 backend built)
🆕 Route/navigation: Admin menu → Settings (/admin/settings, follow the menu URL) → tabs Basic · Billing details. Backend: Pair 1 API93–96 (+ public API97). Permission: site-settings view/manage (Basic), site-settings.billing view/manage (Billing details); hide Save for view-only (permissions from /admin/menu). i18n: admin.settings.*.
- Basic (API93–94,
multipart/form-data): name, tag line, brand colour (hex; the frontend builds the palette — no outside API), logo / icon / favicon uploads (png, jpg, webp, ico ≤ 2 MB; preview + Remove), custom header / footer code (max 20,000 chars each, as V7), Google Analytics ID, privacy / terms / refund links (required), GDPR link (optional), social links (up to 10 platform → URL rows). ✔TOAST"Site settings saved." ✖ 422 inline. - Billing details (API95–96): company name, email, address, city, region + code, country + 2-letter code, postal code, one GST number (V7's second "new GST number" is not in V8 — Pair 1, 2026-10-16), VAT ID, tax % (0–100) and up to 2 extra tax lines (name + value, both or neither). Help text: "This tax % is added at checkout" — changing it changes what customers pay. ✔
TOAST"Billing details saved." - Public site details (API97, no login): the frontend loads name, tag line, brand colour, header/footer code, Analytics ID and policy/social links before login (login page, layout, footer links). Never billing details. Cache briefly; fall back to built-in defaults if it fails.
- Done when: both tabs view/manage, uploads + remove, colour → palette, social link rows, validation, tax help text, public settings on the login page with fallback.
#Admin — Edit a user (B17.6, Pair 1 API98, 2026-10-16)
🆕 Route/navigation: Admin → Users → one user → Edit (MODAL or /admin/users/{id}/edit). Backend: Pair 1 API98 PATCH /admin/users/{id}. Permission: users manage. Works on any account — including the admin's own and other administrators (unlike Ban/Delete, which stay blocked for them). i18n: admin.users.edit.*.
- Fields (send only what changed; all or nothing): name, mobile, country, region, timezone (same rules as the user's own profile) · email (changed at once, no confirmation link; old and new address both get an email) · new password (logs the user out everywhere; never shown) · role Customer / Administrator · admin role (only for administrators; Customer clears it) · status Active (also marks email verified) / Pending / Banned (logs out everywhere).
- Credits (added 2026-10-30, API98): Paid credits and Free credits fields, pre-filled with the user's current balances, where the admin types the new total (2 decimals, may be negative, works for banned users). Promo credits are shown read-only (can't be set here). Confirm text: "Paid credits will change from $old to $new." ✖ 422 "Enter an amount with at most 2 decimal places, for example 25 or -10.50." The change shows in the user's Credit history as an admin adjustment, with the admin's name. No reason field in the API.
- Not shown: company size, industry, management experience, "heard about us" — the API accepts them, but V8 has no About-you questions anywhere (Bhavik D1). Leave them out of the form.
- Confirm text for risky changes: email ("changed immediately, both addresses are emailed"), password and Banned ("the user is logged out of every device"), role → Customer ("removes admin access").
- ✔ 200
TOAST"User details updated." → user page refreshed. ✖ 422 inline field errors · "A customer can't have an admin role. Make them an administrator first." ·admin_role_lockout"At least one active administrator must be able to manage admin roles." (nothing saved). - The user's own activity log shows these changes as done by an admin; the admin activity log records one "Updated user" entry.
- Done when: partial save, each field's rules, email/password/status side-effect confirms, role ↔ admin-role rules, lockout refusal and permission hide/deny pass.
#Admin — User billing (B17.8 Parts 1–2 built)
🆕 Route/navigation: Admin → Users → one user → Billing area with tabs Payments · Credit history · Charges · Promo codes used; a receipt opens from a succeeded payment. Backend: Pair 1 API167–171 (read, Part 1) + API172–173 (add / edit payment, Part 2), 2026-10-30. Permissions (view, per tab): Payments + Credit history users.transactions · Receipt users.invoices · Charges users.charges · Promo codes used users.codes — hide a tab the admin can't view. Works for banned users too. i18n: admin.users.billing.*.
- Payments (API167): the user's credit payments, as on their own history (no checkout links): amount (USD, 2 decimals), charged amount + currency, gateway, status, review reason when waiting for review. Filter by status; 10 per page. Receipt only on succeeded payments (API168) — the same receipt the user sees.
- Credit history (API169): every credit change — payments, promo codes, expired promo credits, managed-server and Premium Hosting Care charges, admin adjustments (shows which admin). Signed paid / free / promo columns. Filters: type (credit / debit / expiry), source, date from–to. Payment lines link to the payment.
- Charges (API170): managed-server charges, one row per server and month, with this month / filtered / all time totals; filters year, month, search (server name or IP). Plan charges come later (Phase 7).
- Promo codes used (API171): successful uses only, newest first: code, type, value, the payment it was used on (discount) or the credits given and their balance + expiry (free credits); a deleted code is marked "Deleted".
- Add payment (Part 2, API172,
users.transactionsmanage)MODALon the Payments tab — records a payment, e.g. one paid outside the website. It never changes the user's credits (say so in the modal; credits are set from Edit user). Fields: gateway (Stripe / PayPal / Instamojo), status (Succeeded / Failed / Canceled / Expired), service (optional, 255), credits bought, discount % + $, base $, tax % + $, payable $, currency (USD / INR), charged amount, exchange rate (only for INR or an Indian customer on PayPal; empty = today's rate from Billing Settings), gateway payment ID + paid date (both required when Succeeded). The amounts must add up (base = credits − discount, payable = base + tax, charged = payable × rate) — show the sums live, the backend checks them to within 0.01. ✔TOAST"Payment added." → row appears (marked manual); a succeeded one gets a receipt the user can download. ✖ 422 field errors (incl. "amounts don't add up", missing rate, gateway never set up). - Edit payment (API173)
MODAL— any payment of the user, full form pre-filled; extra status Refunded (only on a payment that succeeded) needs refund ID, refund reason (1,000) and refund date (not before the paid date). Credits never change, not even on a refund; billing details and receipt / invoice numbers never change; a refunded payment no longer offers its receipt. ✔TOAST"Payment updated." ✖ 409payment_busy"The gateway is still processing this payment. Try again later." (gateway payments in progress; manual ones can always be edited) · 404 not this user's payment. Use aCONFIRMbefore saving Refunded. - Not yet: plan charges and plan invoices (Phase 7), redeem codes used (17.16). Credits are set from Edit user.
- Empty states per tab ("No payments yet", "No credit changes yet", "No charges yet", "No promo codes used"); ✖ 422 bad filter → reset filters.
- Done when: four tabs + receipt load per permission, filters and paging work, admin adjustments show the admin, deleted codes are marked.
#Admin — Error monitor (B17.23 backend built)
🆕 Route/navigation: Admin menu → Debugging → Error monitor (/admin/debugging/errors, follow the menu URL) → one error (/admin/debugging/errors/{id}). Backend: Pair 1 API99–101. Permission: debugging.error-monitor view (list/view) / manage (resolve). i18n: admin.errors.monitor.*.
- List (API99): type (Request / Job / Command), method + path or job/command name, error class, short message (300 chars), file, status Open / Resolved, how often it happened, first seen, last seen. Filters: status (Open default / Resolved / All), type, search, day; newest first; 10 per page (max 50). Empty → "No errors — all good."
- Detail (API100): full message, route, user (if logged in), IP, request input (secrets already shown as
[removed]), user agent, top 15 stack lines (file, line, call). Show code-like data in monospace; never try to un-hide removed values. 404 → "This error was already cleaned up" (errors are kept 2 days). - Resolve (API101) →
TOAST"Error marked as resolved." (shows who and when). 422 already resolved → refresh. If the same error happens again it reopens by itself — say so in help text. - Done when: filters/search/pagination, detail incl. trace, resolve + already-resolved, 404 after clean-up, view vs manage pass.
Organization Members tab built (Pair 1, 2026-10-16, API102): Users → user → Organizations → one organization → Members = GET /admin/users/{user}/organizations/{organization}/members — view only (same list as the organization's members page, pending members included); 404 if the user is not in that organization. users.organizations.members is now view-only (no manage buttons). Other organization tabs still wait for Phases 7–8.
ipinfo.io token (Pair 2, 2026-10-16): moved into the admin integration keys — reversed 2026-10-17: ipinfo.io's free API is used without a key; no ipinfo field in Admin → Integrations.
#Admin — General settings (B17.19 backend built)
🆕 Route/navigation: Admin menu → Settings → General (/admin/settings/general, follow the menu URL) with blocks Display message · Referral program · Other settings (Slack). Backend: Pair 1 API103–113. Permissions: settings.display-message, referrals.settings, settings.other (view/manage each; hide blocks/buttons per /admin/menu permissions). User settings, temporary domain and support email are not in V8 (removed; now 57 permissions, 31 sidebar screens). i18n: admin.settings.general.*.
- Display message (API103–105): one text box (max 1,000) → Save →
TOAST"Display message saved."; RemoveCONFIRM→TOAST"Display message removed." Shown at once to every user (see user banner below). - Trial mode (API106–107): Conflict Do not build this toggle. V8 has no trial (Bhavik 2026-10-09); the backend still keeps an on/off setting — existing conflict D-56.
- Referral program (API108–109) — moved 2026-10-23: this block now lives on Marketing → Referrals → Settings tab (
/admin/referrals/settings), permissionreferrals(view/manage), not on General settings. Fields and rules unchanged: on/off + referrer's credit, new user's credit, minimum payment (USD, 2 decimals, > 0, max 100,000; all three required when on). Save →TOAST"Referral settings saved." Used by the referral feature (Phase 18, not built). - Slack webhook for admin alerts (API110–113): shows Saved (…last 4) / Not set — never the URL. Save (
https://hooks.slack.com/services/…) →TOAST; Send test message (5/min) →TOAST"Test message sent to Slack." ✖ "Save a Slack webhook before sending a test message." / "The test message could not be sent…"; RemoveCONFIRM→TOAST. - User-side banner: the public site settings (API97) now include
display_message— show it as a dismissible-per-session banner at the top of every page (incl. login) when set; plain text only (no HTML). - Done when: each block view/manage, validation, Slack write-only + test success/failure, referral required-when-on, banner appears/disappears for users, no trial toggle anywhere.
#Admin — Servers Part 1 (B17.12 backend built)
🆕 Route/navigation: Admin menu → Servers (/admin/servers) → one server (/admin/servers/{id}); also tabs under Users → user → Servers, and user → organization → Servers / Deleted servers. Backend: Pair 1 API114–119 (from Central's records — no live server data yet). Permissions: servers view (list/view), servers.settings manage (edit), users.servers, users.organizations.servers, users.organizations.deleted-servers view. i18n: admin.servers.*.
- List (API114): name, hostname, IP, status, source, provider, managed, organization, created. Filters: search (name/hostname/IP or exact id), status, source, provider (DigitalOcean / Vultr / Linode / Hetzner / Lightsail), managed, organization, owner; Deleted toggle shows only deleted servers (newest deleted first); sort created / name / deleted date; 10 per page (max 100). Pending installs are listed too.
- View (API115): the server record (also for deleted servers). 404 → not found.
- Edit (API116)
MODAL: name (required), hostname, public IP (must not be used by another server). Help text: "If the panel uses the default nip.io address, it moves to the new IP; a custom domain stays." ✔TOAST→ refreshed details. - User tabs (API117–119): user's Servers (servers of organizations they own), organization Servers, organization Deleted servers — read-only lists, 404 if the user is not in that organization.
- Live parts: now built — see Admin — Servers Part 2 below (2026-10-22).
- Conflict D-63 still open: Pair 1 keeps a Deleted servers list (admin). Update 2026-10-26: admin Restore is now built (API153,
users.organizations.deleted-serversmanage, same checks and errors as the owner restore 9.6, rows carryrestorable, no admin delete-permanently, no email). Still no screen written until Bhavik decides (D-63 / pending 95). Bhavik's rule says deleted servers + restore are not in V8 — the frontend does not spec the Deleted toggle/tab until Bhavik decides. - Note (user side): servers are now soft deleted — a deleted server simply disappears from the user's lists; nothing new to show.
- Done when: list filters/sort/pagination, view, edit validation + IP-in-use error, user/org tabs + 404, permissions; deleted views only if D-63 allows.
#Admin — Servers Part 2: live server screens (B17.12, backend built 2026-10-22)
🆕 Route/navigation: Admin menu → Servers → one server (/admin/servers/{id}) → tabs Overview · Services · Applications · Databases · System users · Logs, plus Check now and Reboot actions. Show only the tabs/actions the admin's permissions allow. Backend: Pair 1 API120–137 (live through the server's panel, same data as the user's server screens). i18n: admin.servers.*, common.*.
- Server must be Ready: if not, every live tab shows "This server is not ready yet" (409
server_not_ready); the server details (Part 1) still load. Deleted/unknown → 404. - Check now (API120,
serversview): re-checks the panel and refreshes the details →TOAST; shows whether it answered. - Overview (API121–124,
serversview): facts (hostname, OS, kernel, IP, CPU, memory, disk, timezone), live usage and load, usage history chart, running processes (view only — no kill). - Services (API125–127,
servers.services): list with status; Test config (view permission, changes nothing) → result; Start / Stop / Restart / Reload / Enable / Disable (manage) →CONFIRMfor stop/disable → refreshed row +TOAST. Only show actions the row lists; protected services show no destructive actions. - Applications (API128–129,
servers.applicationsview): list (search/filter/sort/paging) and one application's details. View only — no create or change. - Databases (API130,
servers.databasesview only): list only. - System users (API131–132,
servers.system-users): list; passwords are never shown (always empty for admins). SSH on/off toggle (manage) →CONFIRM→ refreshed row. - Reboot (API133–135,
servers.settings): shows a pending reboot if one is scheduled. Reboot (manage)MODAL: now or in 1–60 minutes →TOAST+ pending banner; Cancel pending reboot →CONFIRM. Panel reboot here; reboot through the cloud provider is built too (API163, 2026-10-27) — a separate action that works when the panel can't be reached. Still not built: WordPress magic login. - Logs (API136–137,
servers.logsview only): list of log sources → open one to read. No clear, no download. - Errors: same as the user's server panel — show Central's message, plus the cause line (
detail) and "Server says: …" when present (oss_unreachable,oss_tls_changed,oss_forbidden, …). - Permissions: new admin permissions
servers.databases,servers.system-users,servers.logs(catalog now 55). - Done when: every tab loads/empty/error/not-ready state, each action with confirm + toast, hidden tabs/actions without permission, passwords never rendered, reboot schedule/cancel.
#Admin — Move a server (B17.13, backend built 2026-10-23)
V8 requirement Pair 1 built 17.13 (Vishal, 2026-10-23) as one action that covers both V7 transfers. Endpoint: POST /admin/servers/{id}/move (API138). Permission: servers.move (manage). Show the action only with that permission.
Where: Admin → Servers → server details → Move server button (next to the other server actions).
Screen — Move server MODAL:
| Field | Rules (backend) | UI |
|---|---|---|
| Move to | — | Two choices: Another organization of the same owner · Another account |
| Account email | Only for Another account. Valid email, max 255. Must be an existing account that is not suspended | Text field. When it's empty the move stays inside the current owner's account. The current owner's own email also means "same account" |
| Organization | Required. Must exist and must not be the server's current organization. Without email: owned by the current owner. With email: owned by that account | Select of that account's organizations, with the current organization left out |
- Warning shown in the modal for a cloud server: "This server will become a Custom server. Its link to the cloud account is removed, so deleting it from Central will no longer delete it at the provider. Nothing changes on the server or its panel."
- Confirm step
CONFIRM: names both sides — from (current owner email · organization) to (new owner email · organization). - ✔ 200 →
TOASTwith the backend message (e.g. "Server moved to Priya's Org.") → the server details page reloads and shows the new organization and owner (source label "Custom server" for a former cloud server). - ✖ 422 → show the field error under the field: email "No account uses this email address." / "This account is suspended."; organization "This organization doesn't belong to the selected account." / "The server is already in this organization."
- ✖ 409
server_move_managed→ "Managed servers can't be moved yet." (for a managed server, disable the button with this text as a tooltip). - ✖ 409
server_busy→ "Wait until the server has finished setting up, then move it." (also disable the button while the server is creating / installing / connecting). - ✖ 404 → "Server not found." and go back to the servers list.
i18n: admin.servers.move.*. Later (backend): plan / server-limit checks on the new account (Phase 7); shared-server members (4.6) — no UI for these yet.
#Admin — Server Plans (B17.18, backend built 2026-10-23)
V8 requirement Pair 1 built the admin side of 17.18 (Vishal, 2026-10-23, API139–145). What it is: ServerAvatar's own cloud accounts and the managed-server price list. It is not the customers' cloud accounts (those are U11 Integrations), and it does not change the user's Add server wizard. Permission: plans.cloud-prices (view = see, manage = change). Where: Admin → Integrations → Server Plans (/admin/plans/cloud-prices, follow the menu URL). i18n: admin.serverPlans.*.
Screen 1 — Providers list PAGE (API139): always four rows in this order: DigitalOcean, Vultr, Linode, Hetzner (no Lightsail). Each row shows the name, Connected / Not connected, Offered to customers on/off, plans saved / visible, and last updated.
- Row actions (manage only): Connect / Edit → Screen 2. Remove (connected only) →
CONFIRM"Remove? Its key is cleared and it is hidden; saved plans are kept for a later reconnect." → TOAST"Provider removed." (404 → "This provider is not connected.") - Manage plans (connected only) → Screen 3.
Screen 2 — Connect / edit provider MODAL (API140):
| Field | Rules | UI |
|---|---|---|
| API token | Required to connect, max 500. Leave empty when editing to keep the saved key | Password field. Never show the saved key, only "Saved key in use" |
| Offered to customers | Required on/off | Switch |
- Saving a new key checks it with the provider first: show a loading state on Save.
- ✔
TOAST"Provider saved." → list refreshes. Reconnecting a removed provider brings back its saved plans. - ✖ 422 under the field: "The provider did not accept this API token." / "Enter the API token for this provider."
Screen 3 — Plans of a provider PAGE (API142–145):
- Region select (live from the provider, API142). Show a loading state; if the call fails, show an error with Retry.
- Sizes table for the chosen region (live, cheapest first, API143), with columns: Use (tick) · type · cores · RAM (MB → show GB) · disk (GB) · bandwidth (TB) · provider cost (
server_price+currency, read-only) · Customer price / month (USD) · Popular · Recommended. Rows already saved come pre-ticked with their values. - Currency note: the provider cost is in the provider account's currency (a Hetzner account can be EUR). The customer price is always USD. Show both labels clearly and never convert.
- Save region (manage only) → sends only the ticked rows (API145). Unticked sizes are hidden, never deleted; saving with nothing ticked hides the whole region. Use a
CONFIRMfor the empty case: "Hide every plan in this region?"- Customer price: required for ticked rows, > 0, max 99,999.99, 2 decimals. Validate in the form first.
- ✔
TOAST"Server plans saved." → table refreshes. - ✖ 422: "This region is not available at the provider." / "This size is not offered in this region." (show it on the row).
- Saved plans summary (API144): visible plans grouped by region, read-only, as a quick overview under the editor.
- View-only admins see every screen with all inputs and buttons hidden.
#Admin — System Add-ons (B17.24, backend built 2026-10-26)
V8 requirement Pair 1 built 17.24 (Vishal, 2026-10-26, API146–152). Not in V7: admins create the add-ons themselves (WP Toolkit, Reseller panel, Premium Hosting Care, Log monitoring and others) on one screen, and users see the active ones. Permission: system-addons (view / manage). Where: Admin sidebar → System Add-ons (/admin/system-addons, follow the menu URL). i18n: admin.systemAddons.*. Buying add-ons comes later with billing. There is no purchase screen yet.
Screen 1 — Add-ons list PAGE (API146):
- Search by name or label. Filters: Type (Recurring / Lifetime), Status (On / Off). Sort: label A–Z (default) or newest. 10 per page, max 50.
- Columns: icon + label (name in small text), type, price (recurring: base price per month plus the cycles; lifetime: one-time price, both in USD), discounts count, On/Off switch, actions.
- Deleted add-ons are not listed. Empty state: "No add-ons yet." with Create add-on (manage only).
- On/Off switch (API150, manage only) →
TOAST"Add-on turned on." / "Add-on turned off."
Screen 2 — Create / edit add-on PAGE or large MODAL (API147 / API149):
| Field | Rules (backend) | UI |
|---|---|---|
| Name (key) | Required on create. a-z, 0-9, _, max 100. Unique, including deleted add-ons. Can't be changed later | Text field, shown read-only when editing |
| Label | Required, max 100 | Text field |
| Description | Optional, max 2,000 | Textarea |
| Icon | Optional Lucide icon name, max 60 | Icon picker or text field with preview |
| Type | Required: Recurring / Lifetime | Radio. Switching to Lifetime removes the cycles |
| Base price (USD) | Required, > 0, max 99,999.99, 2 decimals. Recurring = per month; lifetime = one-time | Number field with the right hint |
| Billing cycles | Recurring only: 1–12 rows of name (a-z0-9_, max 50), label (max 50), months (1–120). Name and months unique | Repeater rows. Show each cycle's price live as base price × months (display only, the backend works it out) |
| Discounts | Optional: up to 20 promo codes of type discount that are on and not expired | Multi-select of eligible promo codes. Tell the admin the code, percentage, usage limit and expiry are copied now, so later edits to the promo code won't change them. On edit, leaving it untouched keeps the saved copies |
| Active | Create only; default off | Switch. When editing, on/off uses the list switch instead |
- ✔ Create →
TOAST"Add-on created." → list. ✔ Edit →TOAST"Add-on updated." - ✖ 422 under the field: "This add-on name is already used (it may have been deleted). Choose another name." / "Choose discount promo codes that are turned on and not expired."
- ✖ 404 → "Add-on not found." → list.
Delete (API151, manage only) → TYPE-TO-CONFIRM the label: "Delete this add-on? It disappears from the admin and user lists, and its name can't be reused. This can't be undone." → TOAST "Add-on deleted."
User side (API152, any logged-in user): active add-ons sorted by label, with icon, label, description, type, base price and cycle prices. Discounts are not shown. This feeds the user U16 Add-ons list. Buy / renew buttons wait for billing.
#Admin — GST LUT periods (B6.7, backend built 2026-10-26 — Pair 2)
V8 requirement The LUT (Letter of Undertaking) number printed on export receipts. Where: Admin → Site settings → Billing area, a LUT periods block. Permission: site-settings.billing (view = list, manage = add / change / delete). i18n: admin.billing.lut.*.
- List (API91): one row per period, newest first, showing valid from, valid to, LUT number and LUT date. Not paginated.
- Add / Edit
MODAL(API92 / API93):- Fields: Valid from and Valid to (dates, inclusive; to must be on or after from), LUT number (required, max 64, letters, digits,
/and-; saved in upper case), LUT date. - ✔
TOAST. ✖ 422 if the period overlaps another one (shown under Valid from) or a field is invalid.
- Fields: Valid from and Valid to (dates, inclusive; to must be on or after from), LUT number (required, max 64, letters, digits,
- Delete (API94) →
CONFIRM→TOAST. ✖ 404 → refresh the list.