Stellar ControlMission control · by Stellar Systems v0.1.0

Tools

Web Console

The web application of Stellar Control: overview, targets, runs, alarms, passes, file transfers, the editor, the topology and the instances, served by the API.

The web console is the browser interface of Stellar Control, for monitoring and commanding. It is a Svelte application (core/frontend) that goes through the API only: whatever it shows or does, a script can do with the same routes. It bundles its fonts and loads nothing from the internet.

Serving it#

Build it once, then point the API at the result:

Shell
cd core/frontend && npm ci && npm run build     # writes core/frontend/dist
YAML
api:
  web_dir: /opt/stellar/frontend                # the content of core/frontend/dist

The API then serves the application at its root (http://localhost:8080/), and its index for any path that is not a file of the build. Every path under /v1 stays the API: an unknown one is 404 api::unknown-route, never the page of the application. Without api.web_dir, the API serves no page. Behind a reverse proxy, the console and its WebSockets are served over HTTPS and WSS like the API.

To work on the console itself, npm run dev serves it on http://localhost:5173 and relays /v1, WebSockets included, to the API at STELLAR_API (http://127.0.0.1:8080 by default).

Layout#

The rail on the left lists the screens in two groups, each with what waits on it:

GroupScreenShown in the rail
OperateOverview—
OperateTargetsThe number of targets
OperateRunsThe runs waiting for a person (2 waiting, amber)
OperateAlarmsThe alarms not NORMAL; red when one is critical and active, or unacknowledged
OperatePassesThe time to the next AOS
OperateFile transfersThe transfers requested or partial
ConfigureEditorThe number of drafts, when an editor is served
ConfigureTopology—
ConfigureInstancesThe number of registered instances

Above the screens, the rail shows the revision of the current configuration (config and the first characters of its hash), or no configuration. Below them, the identity button. Under 1000 px wide, the rail folds to its icons.

The top bar shows the group and the title of the screen, then:

  • API unreachable when the API does not answer, or no configuration when it answers without a published configuration;
  • the number of critical active alarms and of unacknowledged alarms, linking to Alarms;
  • the number of runs waiting for a person, linking to the first of them;
  • the UTC clock, and the next AOS (target, station, time);
  • the switches of the density (compact, the default, or comfortable) and of the theme (light, the default, or dark). Logs and outputs stay on a dark ground in both themes.

Identity#

The identity button at the bottom of the rail opens the identity panel: the declared operator name, the declared roles (operator,supervisor) and an optional OIDC token. It opens by itself while neither a name nor a token is set. They are sent with every request (X-Stellar-User, X-Stellar-Role, Authorization: Bearer) and, for the language server of the editor, in the query of its WebSocket. A declared identity works where the environment accepts it; in orbit, the API requires a token (see Identity and Roles). The API, not the console, decides: an action refused shows the error of the API next to it.

The identity, the theme and the density are kept in the local storage of the browser (stellar-mcs.settings); in a private window, they last for the session.

Addresses#

Every screen has its own URL: links can be shared, and the back button works.

URLScreen
#/overview (or none)Overview
#/target/<target>Targets; #/target opens the first target
#/runs, #/runs/<run>Runs: the launch form, or a run
#/alarmsAlarms
#/passes, #/passes/<target>Passes
#/files, #/files/<target>File transfers
#/editor, #/editor/<draft>, #/editor/<draft>/<path>Editor
#/topologyTopology
#/instances, #/instances/<kind>, #/instances/<kind>/<instance>Instances
#/driver/<instance>, #/gateway/<instance>The detail of a driver or a gateway

Live data#

What every screen starts from is polled once for all of them; a screen that needs more (a detail, a stream of values) asks for it itself.

DataSourceRefreshed
Topology, instances, alarms, the 100 most recent runsGET /v1/topology, /v1/instances, /v1/alarms, /v1/runs?limit=100Every 3 s, the pace of the heartbeats
Alarms/v1/alarms/watch (WebSocket)At once, on each transition
Output connectors, drafts of the editorGET /v1/connectors, /v1/editor/draftsEvery 10 s
Passes, schedules, transfers/v1/passes/watch, /v1/schedules/watch, /v1/transfers/watch (WebSockets)The whole bucket first, then each entry that changes

Ages, countdowns and durations follow the clock of the browser, every second. A WebSocket closed by the network reconnects by itself, waiting from 0.5 s to 10 s between attempts. See WebSocket Streams.

Overview#

#/overview, the home screen. The state of the system at a glance:

  • Readout: targets ready (and the first not ready), links bound and available, runs active (waiting for a person, launched in the last 24 h), alarms (critical, unacknowledged, shelved), and the pass in progress (time to LOS) or the next pass (time to AOS, marked no gateway when the check before AOS found none).
  • Targets: each target with its platform, environments, readiness, the chain of its default link (driver → transport → gateway, each with the health of its instance, the first reason of a target not ready), and the runs holding its lease. An Environment ladder filters them.
  • Pass plan: the passes from 2 h ago to 10 h ahead, a lane per ground station, with the runs scheduled on them (as in Passes).
  • Questions and decisions of the runs waiting for a person, answered from here (Yes, No; Replay, Skip, Abort), as in Runs.
  • Runs in progress: procedure, state, targets, environment, operator, step and elapsed time.
  • Active alarms: the first eight, with their severity, value, state and age.
  • Output connectors, when there are some: the lag of each consumer (unread messages, how far behind), and healthy, at risk (of losing data to the retention), gone or not registered. See Output Connectors.

Targets#

#/target/<target>. One target, chosen in the list at the top, with its platform, readiness, environments and the runs holding its lease. live or reconnecting tells the state of the stream of its values. The reasons of a target not ready are shown in full. The left column has two tabs: Values (the curve and the current values) and Parameters (its mode and the parameters of its components).

  • Readout: its default link (chain of instances, availability, the other links bound or not), the COP-1 state of the link (FOP state, V(S), N(R), lockout, retransmissions), and the last telemetry received (age, on-board time, delivery, link).

  • Curve of one measure against its soft and hard limits, over 10 min, 1 h, 6 h or 24 h: read from the history of the values, then extended by the values received. By default the first numeric measure with values; click a row of a table to choose another. thinned to fit when the API thinned the history.

  • Current values, streamed from the value table: one table per component, a column per instance, with the unit, derived for a derived measure, a trend of the values received since the page opened (ten minutes at most), and the limits. A value out of its limits is marked ▲ or ▼; a value older than 30 s is shown stale. Hover a value for its on-board time, its age, its delivery and its link; hover a measure for its description.

  • Parameters tab (see Modes and Parameters):

    • Mode: the current mode of the target, default when it is the default mode, and since when and by whom (an operator, or the run whose configure set it; the default mode never set otherwise). Set mode declares another mode of the topology under the identity of the operator: it sends nothing, and is refused while a run holds the target (mode::target-held).
    • Parameters: one row per parameter and instance, with its value in the current mode, its value in each mode, the telecommand setting it, and its readback: the last sample of the measure reading it back, ✓ when it has the value of the mode within the tolerance of the parameter, ✗ when not (hover it for the measure and the age of the sample). With several environments, a list chooses the one whose overrides apply (base values without). Read again every 5 s.
  • Telecommand: a form built from the catalogue of the target (see Direct Telecommands and Values):

    FieldMeaning
    Component, instanceThe instances as buttons, or a list beyond four; the file id for the files component
    TelecommandHazardous ones marked ⚠, with their description and whether they change the on-board state
    ArgumentsOne field per argument, with its unit and range: a list for an enum or a boolean, the unit added to a plain number
    EnvironmentWhen the target has several: selects the parameters of the link; last of the link keeps the environment of its last telecommand

    A hazardous telecommand needs its box ticked (I confirm sending it to …) before Send. The last twelve telecommands sent are listed with their chain of acknowledgements as it progresses (a non-conforming echo marked ✗), their final state and the time it took; without a final state after 30 s, no final state. See Telecommand Lifecycle.

  • On-board files, for a target with a files component: the directory from the last listing (identifier, type, size, generation, transfer). List sends the listing telecommand, Download starts the transfer of a file, and a transfer in progress shows its percentage, linking to File transfers. See File Transfers.

API: GET /v1/targets/{target}/catalogue, /v1/targets/{target}/values/watch (WebSocket), GET /v1/targets/{target}/values/history, GET and PUT /v1/targets/{target}/mode, GET /v1/targets/{target}/parameters, POST /v1/tc then /v1/tc/{target}/{id}/events (WebSocket), GET /v1/targets/{target}/files, POST /v1/targets/{target}/files/refresh, POST /v1/transfers.

Runs#

#/runs. The recent runs on the left, and on the right the launch form, or the run chosen.

The list shows the runs active, of the last 24 h, or all (the 100 most recent); by default the active ones, or those of the last 24 h when none is active. An Environment ladder and a search on the procedure, the targets and the operator filter it. Runs are grouped Now and Earlier, each with its state (running, waiting, suspended, passed, failed), targets, environment, operator, the reason of a failure, and its elapsed time or start.

Launching a procedure#

The form lists the procedures of the libraries of the configuration (⚠ for those that send hazardous telecommands), with their description, their longest duration and the environments they are allowed in. Then:

FieldChoices
EnvironmentThe environments of the topology the procedure is allowed in
RoleA target per role, among those of the platform of the role in that environment (not ready marked)
InputA list for an enum, a field for the others (with its unit), a file chooser for a file input

A file input is uploaded first (POST /v1/uploads), and the run receives the hash of its content. Launch sends the run request (POST /v1/runs) and opens the run. See Running Procedures.

A run#

#/runs/<run>. The run, from its log replayed then followed over its WebSocket (/v1/runs/{id}/events):

  • its procedure and library, state, environment, targets by role, inputs, who launched it and when, the hash of its procedure IR, and its duration against its longest duration (a bar while it runs);
  • the question or decision it waits for: Yes or No, with an optional typed answer kept in the log, and the role whose confirmation is awaited; or, after a failed step, Replay, Skip or Abort;
  • its steps, each attempt with its state, its reason of failure and its duration;
  • its log: every event, one line each;
  • its evidence: telecommands sent, checks (and those failed), answers, start and end.

While it runs: Suspend, then Resume · replay or Resume · skip; Abort. Finished: its outcome, the reason of a failure, and Report, the test report rendered by the API (GET /v1/runs/{id}/report, in a new tab). See Questions, Decisions and Control and Evidence and Reports.

API: GET /v1/procedures, GET /v1/topology, POST /v1/uploads, POST /v1/runs, /v1/runs/{id}/events (WebSocket), POST /v1/runs/{id}/answers, POST /v1/runs/{id}/suspend, /resume and /abort.

Alarms#

#/alarms. The readout counts the critical and warning alarms active, the unacknowledged ones (and those returned to normal), the shelved ones, and tells whether the alarm stream is live.

The list shows the alarms active (not shelved), unack, shelved, or all (NORMAL included, read with ?all=true), by severity then by age: alarm and instance, target, severity and state, value, age and who or what changed it last. Per alarm:

ActionWhenEffect
AckUnacknowledgedAcknowledges it
ShelveNot NORMAL, not shelvedShelves it for the duration of the Shelve for field (30 min by default)
UnshelveShelvedEnds the shelving

Tick several alarms (or all of them) and Acknowledge selected acknowledges the unacknowledged ones among them. Clicking an alarm shows its detail on the side: state and previous state, severity, value, active since, last change and its cause, shelved until. Below it, the transitions received since the page opened (the fifty last): the stream carries new transitions only, without history. See Alarm Handling.

API: GET /v1/alarms, /v1/alarms/watch (WebSocket), POST /v1/alarms/{target}/{alarm}/acknowledge, /shelve and /unshelve.

Passes#

#/passes/<target>. The passes of one target over its ground stations, chosen in the list at the top (targets with passes first); the feeders of its passes and when they last wrote. Without a pass, the screen says where passes come from. See Passes.

  • Readout of the pass in progress or the next one: time to LOS or AOS, AOS, LOS and length, maximum elevation, uplink or receive only, transceiver and protocol, expected rates, status and sources, and the gateway checked before the AOS (or why none).
  • Timeline over 12 h, 24 h or 72 h, a lane per station: booked passes filled, predicted ones dashed, cancelled ones faded, a pass without gateway in red; the runs scheduled on the passes in a lane of their own, a schedule at risk in red.
  • Passes from 6 h ago to the end of the window: AOS, LOS, length, station, maximum elevation, link (↑↓ or ↓ only), status (over once past), sources, gateway. A pass without uplink refuses every telecommand.
  • Schedules of the target (cancelled ones left out, and those fired or missed more than a day ago): the run, its state (scheduled, at risk, fired, missed), its pass, start and fire time, longest duration, targets, the reasons of a schedule at risk, and whether it still fits in its pass. A fired schedule links to its run.

A schedule scheduled or at risk can be cancelled (Cancel). One that needs the validation of a supervisor shows Validate, enabled when the declared roles include supervisor. See Scheduling.

API: /v1/passes/watch and /v1/schedules/watch (WebSockets), POST /v1/schedules/{id}/cancel and /validate.

File transfers#

#/files, or #/files/<target> for one target. Downloads and uploads of on-board files, resumable over several passes. The readout counts the transfers in progress (partial), requested (waiting for a link or a pass), done and corrupted in the last 24 h, and the volume received and sent in 24 h.

The list, filtered by target and by direction (All, Downloads, Uploads), shows the transfers moving first: target, file id and generation, direction, type, size, progress (or the reason of a failure), state, who started it (a run links to it) and the age of its last update. Clicking one shows its detail: its place in the chain REQUESTED → PARTIAL → COMPLETE → VERIFIED → PROCESSED (or CORRUPTED, SUPERSEDED), a map of the file in 80 cells (received, in part, missing), and its generation, ranges received, checksum, priority, author, creation, last update and, for an upload, the hash of its content.

The screen starts nothing: downloads start from the on-board files of a target, uploads from a procedure with a file input. See File Transfers.

API: /v1/transfers/watch (WebSocket).

Editor#

#/editor. The web editor of the configuration repository, when the API relays an editor service (api.editor_url); otherwise the screen shows the error of the API. It loads only when opened. The top of the screen says where the reviews go (forge, project and target branch), or that the drafts are published at once (direct forge, a trial cell). See Web Editor.

  • Drafts: every draft with its title, owner (you for yours), branch, review (its number, linking to the forge; published; pushed; or editing) and age. Click one to open it.
  • New draft: a title (What it changes), then Start a draft. An identity is needed: the draft is yours, and so are its commits.

#/editor/<draft>/<path>. A draft open:

  • Files, filtered by name, the changed ones marked with their status;
  • the file in CodeMirror, with the language server of the draft when it is yours: errors, completion (Ctrl-Space), hover, and F12 to go to a definition, in this file or another one. Save · Ctrl-S writes it; opening another file, the diff, a proposal or a dry run saves it first. The draft of someone else is read-only, without language server;
  • Dry run… on a .proc file: the procedure under the cursor (or the only one of the file), its inputs asked, then Run on simulated targets, in the environment SIM with a simulated target dry-<role> per role; the output is streamed as it comes;
  • the draft: branch, the commit it started from, age, review and state of the language server;
  • Propose, on your draft: a commit message (the title by default), the files changed, then Propose for review (or Update the review); the link to the review, or the branch pushed without forge. With the direct forge, Publish: the draft merged into the target branch, and the commit and snapshot that became the current configuration. Diff shows the changes against the target branch. Abandon… asks Abandon for good or Keep.

API: GET /v1/editor, /v1/editor/drafts and /v1/editor/drafts/{id}, POST /v1/editor/drafts, GET and PUT /v1/editor/drafts/{id}/files/{path}, GET …/diff, POST …/review, POST …/dry-run, DELETE /v1/editor/drafts/{id}, /v1/editor/drafts/{id}/lsp (WebSocket).

Topology#

#/topology. The configuration as the reconciler applies it:

  • Environments: a card per environment with its targets (ready, not ready) and its policy: drafts accepted or refused, the identity required (declared or OIDC token), the roles that confirm a hazardous telecommand, and whether hazardous runs must be planned on a pass. Click a card, or use the Environment ladder, to show its targets only. See Environments.
  • Bindings: a graph of every link of every target, targets → drivers → transports → gateways: bound on the default link, bound on another link, degraded or unavailable, not bound (drawn to what the link declares). Click a node (or Enter on it) for its target or its instance.
  • Not ready: each target not ready and why, as the reconciler says it.
  • Reconciler: its journal, newest first — bound, unbound, rebound, ready, not ready, revision — with the chain of instances and the reasons.
  • Leases: the targets held by runs, shared or exclusive.
  • Configuration: the active revision, the targets still on a previous one, and a link to change it in a draft of the editor.

API: GET /v1/reconciler/events?limit=100, then /v1/reconciler/events/watch (WebSocket).

Instances#

#/instances, or #/instances/<kind> for one kind. The drivers, transports, gateways, connectors and services registered with the reconciler, grouped by kind, filtered by kind and by a search on the name, the software and the links: software and version, state (healthy, degraded, gone; link down; the reason given), the age of its last heartbeat, what it declares (catalogue, frames, uplink and downlink with their rates, tags) and the links bound to it. The top counts the instances gone and degraded, or says all healthy.

An instance#

Click a driver, a transport or a gateway to detail it on the side (#/instances/<kind>/<instance>; #/driver/<instance> and #/gateway/<instance> open it too), refreshed every 3 s:

  • its identity and state: software, start and uptime, registration, heartbeat period and last heartbeat, its credentials (a JWT issued by the reconciler, or bootstrap credentials), its public key; for a gateway, its uplink and downlink (type and rate) and its tags;
  • for a driver, the catalogue it implements against the current configuration: whether a version of the configuration fits, its codec, the telecommands and measures covered, and those missing;
  • for a gateway, its throughput per target as it reports it (every 5 s by default, the last five minutes), and, for a simulated gateway, its faults, each switched on and off with a button (see Simulated Targets);
  • the links bound to it, with the durable consumer of their telecommands: delivered, waiting, unacknowledged, redelivered; previous configuration for a binding not yet on the current one.

API: GET /v1/instances/{kind}/{instance}, /v1/instances/gateway/{instance}/throughput (WebSocket), GET /v1/sim/{gateway}/faults, PUT /v1/sim/{gateway}/faults/{fault}.

Stellar Control · v0.1.0

↑↓ to moveEnter to open