Repository navigation
Command layer dispatcher
The dispatcher: the checks it runs on every command line, the four ways a command ends, the audit it writes, and the limits on the first commands' arguments. Every command is listed on the generated Command layer commands, and how the layer fits the server is on Command layer.
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.
The permission check comes before the argument checks, so an actor without the permission learns only that it's denied. help, a refused argument count and the commands page all show the same usage line.
| Outcome | Means |
|---|---|
| Done | The command ran |
| Refused | Understood and declined, by the command or its owner |
| Denied | For want of a permission, or console-only |
| Failed | The command threw |
Every command that resolves leaves one 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.
| Argument | Limit |
|---|---|
| An email | At most 254 characters, and it has to look like an address |
| A password | 1 to 128 characters; quote one that has spaces |
| A suspension's length | A number of hours, or forever
|
| A suspension's reason | At most 200 characters |
account create stores a random salt and an SRP6 verifier from the email in lower case, and account suspend kicks the account's session if it's online. Each command's answer waits for the owner, and for its commit where it writes.
| Front end | Holds |
|---|---|
| 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 |
| In game, the web | Known to the dispatcher by name, with no code behind them yet |
- Console-only commands are refused only from in game; how the web front end is treated is decided before it's built.
-
helplists console-only commands to an in-game actor who holds their permission. - The argument limits are fixed in code.
| 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