Repository navigation
Command layer
How the command layer works as built: one dispatcher behind every front end, the checks it runs, what it audits, and the first commands. The local console is the only front end so far; the web console, the player portal and in-game commands are on Command layer design.
An admin action is a command: a definition naming its parameters, its permission, whether it's console-only, and what it runs. A front end hands the dispatcher one line of text and the actor who typed it, and gets one reply back.
flowchart TD
CON["Local console"] -->|"a line, as the console actor"| D["Dispatcher"]
D -->|"checks, then runs"| CMD["Command"]
CMD -->|"posts, waits for the reply"| AO["Account owner"]
D -->|"one audit row"| WB["Write-behind queue"]
The dispatcher runs its checks in this order, and stops at the first that fails:
- The line splits into words, double quotes holding a phrase together. An empty line, or one with an open quote, is refused.
-
helplists the commands the actor may run, with their usage. - The command is found by its two-word name, then its one-word name.
- The actor has to hold the command's permission.
- A console-only command is refused from in game.
- A line with control characters or broken text is refused.
- The number of arguments has to fit; the reply shows the usage when it doesn't.
- Each argument passes its parameter's own check.
- The command runs. One that throws is logged and answered as failed.
A command ends one of four ways: done, refused (understood and declined), denied (for want of a permission, or console-only), or failed. The permission check comes before the argument checks, so an actor without the permission learns only that it's denied.
Every command that resolves leaves one audit row, denials included: the time, the actor, the front end, the action, its target, the other arguments, the address and the outcome. Rows go through the write-behind queue into the ops schema, one after another in order, and each value is cut to its column's width so a row can't fail to save. An empty line, a line that doesn't parse, an unknown command and help leave none.
A secret stays out of the audit, the reply and the log. A value is recorded only when its parameter isn't secret and the value passes that parameter's check, so a password typed into the email slot isn't recorded either. A usage line shows parameter names, never values.
Command layer commands lists every command: its usage, the permission it needs, whether it's console-only and what it does. It's generated from the server's command list, BuiltinCommands, which the server registers its commands from too, so the page can't drift from what the server runs. help at the console lists the ones the actor typing it may run. help, a refused argument count and the page all show the same usage line.
The arguments have fixed limits: an email is at most 254 characters and has to look like an address, a password is 1 to 128 characters, and a suspension's reason is at most 200. account suspend takes a number of hours or forever, and kicks the account's session if it's online. account create stores a random salt and an SRP6 verifier from the email in lower case. Each command's answer waits for the owner, and for its commit where it writes.
The local console reads each line from the server's standard input and dispatches it as the actor console, which holds every permission. It runs when Cli:Enabled is on, the default, and input isn't redirected. Host has where it starts.
In game and the web are front ends the dispatcher already knows by name, with no code behind them yet.
| Setting | Default | Sets |
|---|---|---|
Cli:Enabled |
on | Whether the server reads commands from its console |
The field limits above are fixed in code.
- Console-only commands are refused only from in game; decide how the web front end is treated before it's built.
-
helplists console-only commands to an in-game actor who holds their permission. - Roles and in-game GM commands arrive after the first stage, so the console actor's every-permission is the only grant.
| Piece | Path |
|---|---|
| The dispatcher, definitions, actors and the line splitter | Source/NexusTomorrow.Commands/ |
The account and server commands, and the list the server registers (BuiltinCommands.cs) |
Source/NexusTomorrow.Commands/Builtin/ |
| The console front end | Source/NexusTomorrow.Server/ConsoleFrontEnd.cs |
| The audit row | Source/NexusTomorrow.Persistence/Ops/ |
| Tests | Tests/NexusTomorrow.Commands.Tests/ |
Start here
How the server works
- Server core design
- Host
- Gateway
- Owners
- Persistence
- Command layer
- Harness
- Map scheduler design
- Timer wheel design
The protocol
Working on it