Command layer design - NexusTomorrow/server GitHub Wiki

design, published verified 2026-10-16

The design for the command layer: every admin action as a typed command, the permission it needs, the owner that runs it and the audit record it leaves, for every front end from the local console to the web. Step 3's first stage builds the layer, the local console and the account commands; the web console, the player portal and in-game commands follow, and the web side's own design stays on Server core design. Roadmap says how far the build has got.

The idea

In short

An admin action is a command that declares its parameters, its permission and the side that owns it. One dispatcher checks the permission on the server, posts the command to its owner, waits for the reply and writes one audit record, whichever front end the command came from. No front end writes state an owner holds.

Why

A permission checked only in a front end is a permission anyone who gets past that front end can skip. One dispatcher behind every front end means one place to check, one place to audit, and the same command doing the same thing from the console, the web or in game. The harness drives the server through these same commands, which is why the layer comes first.

Decisions

Locked

Every admin action is a typed command, declaring its parameters, its permission and its owning side. The in-game GM chat, the web console and a local CLI all dispatch the same commands. The dispatcher checks the permission server-side, refuses a console-only command from in game, posts the command to the owner's message queue, waits for the reply and writes one audit record (actor, front end, action, target, details, address, outcome, denials included). The console never writes state an owner holds, so an online character is changed by its map.

Permissions are the old role-based set, lifted, with one dotted key per command. Built-in roles can't be deleted. Commands too dangerous without a second factor (role changes, bulk deletes, settings) are console-only, since the game client can't do two-factor.

A command ends one of four ways: done, refused by its owner, denied for want of a permission, or failed. Each is audited.

A secret parameter never reaches the audit or a log. A password given to account create is turned into a verifier and dropped.

The audit goes through the write-behind queue into the ops schema, like any other save (Persistence design).

The command layer and the CLI ship with milestone one, because the test harness drives the server through them. The web console and the player portal follow right after.

The first commands

The first stage's front end is the local console, which the host runs as an actor holding every permission (Host design). Roles arrive with in-game commands.

Command Permission Does
account create account.create Creates an account that can log in, from an email and a password
account suspend account.suspend Suspends an account for a number of hours or forever, with a reason, and ends its world session
account unsuspend account.unsuspend Lifts a suspension
server status server.status Reports the accounts online, each owner's queue, the write-behind backlog and whether the database is reachable
help none Lists the commands the actor holds, with their usage

A line that doesn't parse or names no command is refused without an audit record; everything past that point is audited.

Open

  • In-game GM commands, with the old roles lifted, come after the first stage.

Rejected

Idea What killed it
Permission checks only in the console's interface Any account that gets in could grant itself any role. Every command checks its permission on the server

Verification status

Claim Basis
Permission checks, refusals and the audit Designed; held by the dispatcher's own tests as it's built

Open questions