In-client /admin command panel for admins #117

Merged
marco merged 1 commit from feat/admin-command-panel into main 2026-07-20 23:40:42 +02:00
Collaborator

A discoverable admin/dev tooling panel, opened with the /admin chat command, shown only to accounts with the admin claim. It lists the GM commands and prefills them into the chat so a non-technical operator can use them.

How it works

  • Server-authoritative admin signal: the server sends an AdminCommandCatalog on connect only to admins (isAdmin from the signed JWT claim). The client shows the panel only if it received one. No client-side JWT decoding; every command is still authorized per call by its CanExecute — a forged/force-opened panel cannot escalate.
  • Auto from the command classes: BaseCommand gains abstract Usage/Description, so a new command cannot ship without them and appears in the panel automatically. CommandRegistry.AdminCatalog projects the auto-discovered GM commands.
  • Client: /admin toggles the panel; clicking a command prefills /name into the chat, ready for its arguments. A /admin hint shows in the HUD for admins.

Reworked onto current main (this replaces the original branch)

The original branch predated #104 and #119; it has been rebuilt on top of them:

  • Gump API: AdminPanel is now a Gump composed from elements, not hand-drawn — plus a new reusable GumpCard element (a clickable, hover-aware list row) for future vendor/quest/command lists.
  • Decomposed client (#119): the wiring lives in the focused components — ServerMessageDispatcher applies the catalog, GameInputController routes /admin + panel clicks, WorldRenderer draws the panel + HUD hint. Nothing was added to GameScreen.
  • ProtocolVersion → 4 (new AdminCommandCatalog wire message).
  • Build vs main: /clearbag (from #104) now implements the new abstract Usage/Description, so the whole solution builds.

Verification

  • Whole-solution dotnet build: 0 warnings; csharpier check clean; dotnet test: 326 passing (added: catalog is complete/sorted with metadata; AdminCommandCatalog protocol round-trip).

Definition of Done

  • /admin opens a panel listing every GM command; clicking one prefills /<name> into the chat.
  • A non-admin never receives AdminCommandCatalog; the panel stays empty and /admin is a no-op for them.
  • Every GmCommand has a Usage/Description (compiler-enforced via the abstract members).
  • Whole solution builds, 0 warnings; dotnet test green.
  • Manual smoke test (just dev as an admin): /admin opens the panel; clicking /give prefills /give ; a non-admin sees no /admin hint and the panel never appears.
A discoverable admin/dev tooling panel, opened with the `/admin` chat command, shown only to accounts with the `admin` claim. It lists the GM commands and prefills them into the chat so a non-technical operator can use them. ## How it works - **Server-authoritative admin signal**: the server sends an `AdminCommandCatalog` on connect **only** to admins (`isAdmin` from the signed JWT claim). The client shows the panel only if it received one. No client-side JWT decoding; every command is still authorized per call by its `CanExecute` — a forged/force-opened panel cannot escalate. - **Auto from the command classes**: `BaseCommand` gains abstract `Usage`/`Description`, so a new command *cannot* ship without them and appears in the panel automatically. `CommandRegistry.AdminCatalog` projects the auto-discovered GM commands. - **Client**: `/admin` toggles the panel; clicking a command prefills `/name ` into the chat, ready for its arguments. A `/admin` hint shows in the HUD for admins. ## Reworked onto current `main` (this replaces the original branch) The original branch predated #104 and #119; it has been rebuilt on top of them: - **Gump API**: `AdminPanel` is now a `Gump` composed from elements, not hand-drawn — plus a new reusable `GumpCard` element (a clickable, hover-aware list row) for future vendor/quest/command lists. - **Decomposed client (#119)**: the wiring lives in the focused components — `ServerMessageDispatcher` applies the catalog, `GameInputController` routes `/admin` + panel clicks, `WorldRenderer` draws the panel + HUD hint. Nothing was added to `GameScreen`. - **`ProtocolVersion` → 4** (new `AdminCommandCatalog` wire message). - **Build vs `main`**: `/clearbag` (from #104) now implements the new abstract `Usage`/`Description`, so the whole solution builds. ## Verification - Whole-solution `dotnet build`: 0 warnings; `csharpier check` clean; `dotnet test`: **326 passing** (added: catalog is complete/sorted with metadata; `AdminCommandCatalog` protocol round-trip). ## Definition of Done - [x] `/admin` opens a panel listing every GM command; clicking one prefills `/<name> ` into the chat. - [x] A non-admin never receives `AdminCommandCatalog`; the panel stays empty and `/admin` is a no-op for them. - [x] Every `GmCommand` has a `Usage`/`Description` (compiler-enforced via the abstract members). - [x] Whole solution builds, 0 warnings; `dotnet test` green. - [ ] **Manual smoke test** (`just dev` as an admin): `/admin` opens the panel; clicking `/give` prefills `/give `; a non-admin sees no `/admin` hint and the panel never appears.
panda force-pushed feat/admin-command-panel from 73acf85d78
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m34s
to f9ba26c4dc
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m29s
2026-07-20 21:45:38 +02:00
Compare
panda force-pushed feat/admin-command-panel from f9ba26c4dc
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m29s
to c0dfb14fac
All checks were successful
ci / Lint & Test (pull_request) Successful in 2m3s
2026-07-20 22:03:28 +02:00
Compare
panda force-pushed feat/admin-command-panel from c0dfb14fac
All checks were successful
ci / Lint & Test (pull_request) Successful in 2m3s
to 55a4004f32
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m31s
2026-07-20 22:19:58 +02:00
Compare
marco force-pushed feat/admin-command-panel from 55a4004f32
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m31s
to 505db09a41
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m27s
2026-07-20 23:18:18 +02:00
Compare
marco force-pushed feat/admin-command-panel from 505db09a41
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m27s
to 33deacffa7
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m39s
2026-07-20 23:30:18 +02:00
Compare
marco force-pushed feat/admin-command-panel from 33deacffa7
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m39s
to b2c7dc5c90
All checks were successful
ci / Lint & Test (pull_request) Successful in 1m32s
2026-07-20 23:38:21 +02:00
Compare
marco merged commit cc63b64ef0 into main 2026-07-20 23:40:42 +02:00
marco deleted branch feat/admin-command-panel 2026-07-20 23:40:42 +02:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marco/IsoMmo!117
No description provided.