Skip to content

Commands

Catalog, under Actions: Commands (with command_type:read, covered by every viewer’s *:read floor) is the fleet’s “do” catalog: the directory of what a component can be told. The other catalogs name what the fleet knows (a property is a value, a metric is a quantity) and what happened (an event is an occurrence); a command type names an instruction (set-input, reboot) and carries the two facts that belong to the driver, not the abstract signal: the target it sets and the settle window the device needs to act. The name is its canonical identifier, a single lowercase kebab segment.

A command type is used in two moves, and this page walks both: the catalog names the instruction, and issuing records an invocation typed by it, which a settleable command then reconciles against what the device reports (commands).

The console page lives at /command-types, and the nav says why: the address reserves /commands for the command history surface when it lands, so the catalog keeps the type-named route.

The catalog is fleet-wide reference data, not a scoped resource, so every command type is visible to every reader; the write gates decide who may change it.

  • The directory lists every command type sorted by name, each showing its name (the canonical identifier, with its label on the line above it), target (the property or metric it sets, labelled with its lane, or fire-and-forget), settle window (seconds), and origin (official or custom). name filters by the name or its label; official narrows the list.

  • The target is two-armed: a settleable command names the value it sets in exactly one lane, a property (set-input targets video-input) or a metric (a volume command targets a numeric level), never both. A command with no target is fire-and-forget (reboot): it records that it was told, with no value to settle. The create and edit forms offer one picker over both catalogs, grouped by lane, so a selection sets exactly one arm; through the API, naming both arms is refused (422, naming the exclusive arc), and a target must be a registered property or metric type.

  • The settle window is the driver’s fact about actuation time: how long the device is given to act before a mismatch between what was told and what is observed counts as failure. Within the window, a difference is not yet a verdict. It is a duration, so it has no negative: the field refuses one where you type it, and the API refuses one with a 422.

  • The window belongs to the target, so the console asks for it only where it decides something. A settleable type must state one: the create form starts the field blank, and both the create and a blade’s Save are refused while it is empty beside a target arm. 0 is a legitimate answer there, and the field says what it does before you commit to it (the command is judged at the moment it is issued, settling only if the target already reports what it was told, and failing if it does not); it is an answer you give rather than one the form gives for you (ADR-0108). A fire-and-forget type never reaches settlement at all, so leave the field blank: the type records a window of 0 and nothing ever consults it. That is reboot’s shape.

  • New command type (with command_type:create, granted to operators) opens a create drawer: give it a name (a single lowercase kebab segment, for example set-input or reboot), optionally add a label and description, pick a target (or None), and, if you picked one, state the settle window. An invalid name (an uppercase letter, an underscore, a leading hyphen, a dot) is refused with a message.

  • Pick a row to open its detail blade. The footer Edit pencil (with command_type:update) edits the label, description, target, and settle window; the name is fixed at creation, since it is what every invocation is typed by. Delete (with command_type:delete) removes a custom command type, behind a confirm. A verb you lack greys just that button, its hover reason naming the permission (Requires command_type:update, Requires command_type:delete); the pair never disappears.

  • A command type can carry a params schema (a JSON Schema for the invocation params), set through the API for now; the console does not surface it yet. A schema whose required list names a property its properties block does not declare is refused at write with the name, and the stored schema is enforced at issue: an invocation whose params violate it is refused (422, naming the violated constraint), and absent params validate as the empty object, so a schema with required fields refuses a bare invocation.

  • An official command type is always read-only: the blade keeps the Edit and Delete pair in place, greyed, with the reason on hover: “Official: ships with Omniglass and updates with it.” The shared vocabulary is the same from install to install, the same deliberate exception to the operator-owned rule the Properties catalog makes, and for the same reason: a command type name is the vocabulary a driver maps onto, so a release has to be able to correct it (the seed model).

    The baseline ships this catalog, rendered from the seed itself (make gen) so the list cannot drift from the binary:

    NameDescription
    set-inputTell a display or switcher which video input to select. A settleable command: it opens an intended video-input and settles when the device reports that input within the settle window.
    rebootTell a component to restart. A fire-and-forget command: it records the invocation and a caused event, with no intended value to settle.
  • A duplicate name is refused (409), and an attempt to change an official command type is refused too: the catalog has exactly one entry per name.

Issuing is POST /components/{name}/commands:issue (with command:issue, granted to operators); the component resolves within your read scope, so a component outside it is a non-disclosing 404. One transaction records three things:

  • the command row: the invocation itself, with its params and who issued it;
  • a caused event, typed command-issued, on the component’s event log; and
  • for a settleable command given a value, an intended series row in the target’s lane: the value the device was told to hold, landing beside the observed series so intent and reality can be compared. The row names the command that opened it (its command_id lineage), so every want traces to the invocation that wanted it. A metric target’s intended value must be a JSON number (422 otherwise).

The issue response returns the computed settlement verdict (none for fire-and-forget, else pending, settled, or failed): within the settle window the verdict is pending, and past it the latest observed value either matches the intended one or does not. The command row also records a terminal status, issued until a settle-check stamps settled, failed (the device reported a different value), or timed-out (the window expired with nothing observed), with settled_at as the terminal moment. The settle-check runs wherever settlement is evaluated, at issue and on every settlement read, so a zero-window command returns already terminal, and a fire-and-forget command records settled at issue since it has nothing to wait on. This surface records and reconciles; carrying the invocation to the device is not part of it.

From the CLI, the catalog is omniglass command-type list|get|create|update|delete, and issuing is omniglass component command issue (see the CLI reference).