User interface
The UI is a SvelteKit single-page app embedded in the server
(stack.md §3). It is a view over the management
API: it holds no state of its own, and everything it does, a script can do
with stratactl.
1. Principles
- Every view has a URL. Filters, selectors, tabs and the selected revision live in the URL, so a link shows the same view to a colleague (who sees what their own permissions allow).
- Live, not polled. Views subscribe to the SSE topics they display
(
GET /api/v1/events) and re-fetch on change. - Changes go through change sets. Every spec edit opens or extends a draft change set; nothing in the UI writes a revision directly.
- The equivalent command is one click away. Every action and filtered
list offers "Copy as
stratactl". - Permissions decide what is offered. Actions the caller's roles cannot
perform are hidden; a
403that still happens (scope) shows the role and scope that would be needed. Data the caller may not see is absent, never greyed out. An action a tenant limit blocks stays visible but disabled, with the limit and its usage. - Empty is explained. An empty list says whether nothing exists yet or the filters match nothing, and offers the next step: the first object to create, the enrollment command, or clearing the filters.
- Confirmations state consequences. A destructive or disruptive action confirms in a dialog that names what it affects, with counts ("12 agents use this pin; they fall back to the release"). Irreversible deletes of tenant-wide objects (teams, sinks, trust anchors) ask for the object's name to be typed.
- Unsaved input is guarded. Leaving a form with unsaved changes asks first. Saved spec edits need no guard: they live in the draft change set; the editor asks only for text not saved into it yet.
- Secrets are never shown. Secret fields are write-only; rendered
configs show
<secret:name@vN>. - Accessible. Keyboard operable throughout, WCAG 2.2 AA, light and dark themes; charts have a table view.
2. Layout
┌──────────────────────────────────────────────────────────────────────────┐
│ acme ▾ [ search hosts, agents, files, CS-…, RO-… ] ● live user ▾ │
├────────────┬──────────────────────────────────────────────┬──────────────┤
│ Overview │ │ Assistant │
│ Fleet │ page │ (panel, │
│ Spec │ │ opens with │
│ Changes │ │ the page │
│ Rollouts │ │ as context)│
│ Secrets │ │ │
│ Journeys │ │ │
│ Catalog │ │ │
│ Admin │ │ │
└────────────┴──────────────────────────────────────────────┴──────────────┘
The tenant name opens the user menu; with several tenants it offers to switch, which opens the tenant choice (§3.11). The search finds hosts, agents, spec files and objects, change sets and rollouts by name or number, and pages and actions (such as a new enrollment token) by name. The badge next to Changes counts change sets waiting for the caller's review. When the tenant's usage of a limit (architecture.md §12) reaches 90 %, every page shows a banner with the usage; tenant admins get a link to Admin › Tenant, others are asked to contact an admin.
Lists show a fixed set of columns. Hosts and agents sort by any column (clicking its header; the sort lives in the URL), by default hosts by name and agents by instance id. Times show relative ("4 min ago") with the absolute time on hover. Lists with bulk actions have a checkbox per row and a selection bar ("12 selected") with the actions; a bulk action runs per object and reports the result per object, as operation progress (§4).
3. Pages
3.1 Overview
Agents per kind by health and sync, with the reasons behind out_of_sync
and render errors; change sets waiting for the caller's review; active
rollouts with their current stage; failing journeys; agent version
distribution against the catalog. Each number links to the filtered list.
3.2 Fleet
| View | Shows | Actions |
|---|---|---|
| Hosts | Selector bar; host, kind, owner, columns for chosen labels, agents with health dots; clicking a label value adds it to the selector | Bulk: edit manual labels, forget |
| Host | Labels by source with the effective one marked; agents; layers whose selector matches; placements that picked it | Edit manual labels, kind, owner; forget |
| Agents | A health bar per kind (segments link to the filtered list); filters for kind, health, sync, version, desired and applied revision, pending approval; agent, host, kind, health, sync, version, applied revision, last report; with retention.silentAgents set (spec-format.md §3.8), when a not_reporting agent will be forgotten | Bulk: approve, quarantine / release, forget (e.g. all not_reporting) |
| Agent | Status: health, sync and reason, desired / served / applied with revisions and times, flags, identity and assurance, pin or rollout that decides its revision | Approve, quarantine / release, SETTINGS action, revoke credential, forget |
| Agent: Config | The desired, served or applied config; diff between any two | – |
| Agent: Explain | Instance keys; per option the winning value and the overridden ones (spec-format.md §4) | – |
| Agent: Logs, Events | Heartbeat logs (Telegraf, Vector), component and unit state (Elastic Agent), status transitions | – |
| Placements | Per placement and spread value: wanted, picked hosts, candidates, shortfall | – (edited as spec files) |
3.3 Spec
| View | Shows | Actions |
|---|---|---|
| Files | The tree at a revision (default latest), filter by kind, owner, agent kind, plugin, "matches host"; per layer and bundle the instance count per plugin section | Edit (opens a draft), new file (below), import a telegraf.conf or a Vector config as a new layer |
| File | What the object uses (bundles, routes, secrets, placements whose label its selectors select) and what uses it, with a note on a bundle, route, secret or placement nothing uses yet; canonical TOML; for layers and bundles also a structured view: instances with their plugin, options and merge directives; history of the file | Edit, restore an older version, view at any revision |
| History | Revisions with change set, author, message and files changed; diff between any two revisions (tick two, Compare) | Revert a revision (creates a draft) |
Editing. The editor (CodeMirror) works inside the caller's draft change set and offers:
- completion and inline docs from the catalog schema of the target agent versions; TOML syntax errors while typing, L0/L1 diagnostics on every save; a problems panel lists both, each opening its line;
- secret references and
${ENV}references highlighted apart from literals, with completion of secret names, and a reference panel on what each is for (secrets for credentials,${ENV}for values that differ per host and are not secret); - a form view for a plugin instance, generated from its JSON Schema, with the TOML kept in sync;
- for
data_formatoptions, a sample panel that runstelegraf-parsein the browser (agents/telegraf.md §8); - a preview pane: pick an agent (or a host, kind and version) and see the
rendered config, its diff against the base and
explainfor the option under the cursor; - a selector field (§4) wherever a selector is edited.
New file. One dialog, here and in a change set (§3.4): the kinds grouped by what they are for (configure agents; credentials and hosts; synthetic checks; rollout, review and settings), each with a line on what it does, and for the chosen kind how it relates to the others and whether its changes need an admin's approval. Then what the template needs: the agent kind (defaulting to the kind with the most agents), name (for Settings the topic, one file each), owner team, for a layer the precedence with the recommended bands, the selector of a layer, journey, secret grant, placement or approval policy (§4), for a route the teams that may attach it, and the path. A Secret notes that its value and its references come after the merge. The template comments each key it holds; with a draft change set (one of the caller's or a new one), the file opens in the editor.
Import. A telegraf.conf or a Vector config file (uploaded, dropped
or pasted; the agent is picked in the dialog) with an owner team, selector
and precedence becomes a layer in the draft change set, converted as by
stratactl import telegraf or stratactl import vector
(agents/telegraf.md §9,
agents/vector.md §9); the converter's
warnings show before the file is added.
3.4 Changes
| View | Shows | Actions |
|---|---|---|
| Change sets | Tabs: waiting for my review, mine, open, merged, closed | New change set |
| Change set: header | Number, title, state, approved flag, base revision, merged revision and the rollouts delivering it, author (and assistant chat), digest | Edit title and description, validate, submit, rebase, merge (optionally starting rollouts), close |
| Change set: Files | Diff per file against the base, with L0–L2 diagnostics inline | Add or edit a file (a file of the base revision, or a new one as in §3.3), undo a file's change (back to the base revision) |
| Change set: Rendered | Rendered diffs for a sample agent per distinct diff, with the number of agents sharing it | – |
| Change set: Impact | Impact set grouped by owner, kind, version or any label; the agent list. Merged and closed change sets show the summary of their last validation only; before the first validation the tab says it is not computed yet | – |
| Change set: Validation | Diagnostics by level, file and agent version; sandbox results | Re-run validation |
| Change set: Review | Requirements with their reason and who satisfies them; reviews at current and earlier digests | Approve, reject or comment, choosing the teams an approval counts for |
A change set whose base is no longer the latest revision shows a banner with Rebase; one with conflicts lists the files and opens them in the editor with conflict markers. Merge is offered when the change set is approved; the merge dialog shows the rollouts it would start.
3.5 Rollouts
| View | Shows | Actions |
|---|---|---|
| Rollouts | Active and past rollouts per agent kind; kinds without agents or rollouts on one line | Start a rollout (kind, target revision, policy) |
| Rollout | The stages as a pipeline: state, agents applied of total, bake time left, each guardrail's value against its threshold; the change sets delivered; halt reason; agents still applying the revision after their stage passed | Pause, resume, advance, abort, each with a reason |
| Rollout: Agents | Assigned agents per stage with baseline and current health and sync | – |
| Releases and pins | Release pointer per agent kind; pins, active and scheduled, with their agents | Create a pin (selector with kinds, or an agent; revision; window; reason), delete a pin |
3.6 Secrets
| View | Shows | Actions |
|---|---|---|
| Secrets | Name, owner, current version, unset badge, number of agents referencing it | – |
| Secret | Grant and minimum assurance (from the spec, with a link to the file); versions with state; agents referencing it; delivery audit | Write a new value (write-only field), disable a version |
3.7 Journeys
| View | Shows | Actions |
|---|---|---|
| Journeys | Per journey: runners by latest result, stale and unplaced journeys | Import a Chrome recording (into a draft change set); pair this computer as an exploration runner (the command to run, then its state) |
| Journey | Settings and script (read-only; edited as a spec file); per runner the latest result, failing since, run counters; kept runs, filterable by result and by manual or scheduled | Edit (opens a draft); Run now on all runners or one (journeys.md §3.1): the result per runner as it arrives, with links to the runs |
| Run | Step timeline with durations; the failing step's screenshot and accessibility snapshot; the script with the failing line marked; output; for a manual run, who triggered it | Download evidence |
3.8 Catalog
Imported bundles per agent kind and version, with the number of agents on each version; plugins by section with schema, options, sample and docs.
3.9 Admin
Visible to tenant admins.
| View | Shows | Actions |
|---|---|---|
| Users and teams | Members (human and service accounts), teams and their members, source | Add a local member, disable / enable a membership, manage local teams |
| Access | Role bindings by subject, role and scope; for selector scopes the number of matching hosts | Create, delete |
| Service accounts and tokens | Service accounts; tokens with prefix, roles, expiry, last use | Create (expiry presets 7, 30, 90 and 365 days or a date; the token is shown once, with copy), revoke |
| Enrollment | Enrollment tokens with kind, mode, labels, uses; agents pending approval; trust anchors | Create a token (shown once, with install snippets in tabs per agent kind and OS pointing at server.agent_url, class-mode snippet included, noting that the token is not stored in the snippet's history), revoke; add and delete trust anchors |
| Network zones | CIDRs with their labels | Create, delete |
| Audit | Events with filters for object (id, CS-n or RO-n), actor, action and time, each object named and linked while it exists, an assistant's events as the assistant for its user, details folded; sinks with cursor, lag and last error | Create, change and delete sinks |
| Assistant | LLM providers and their models; API key status | Edit the provider list (keys write-only) |
| Tenant | Limits and usage | – |
3.10 Platform pages
In a platform session (service mode) the UI shows only /platform:
tenants (state, limits, usage; update, suspend, resume, delete), catalog
bundles (import) and the platform audit chain. In a self-hosted
installation a platform admin imports bundles on the tenant's Catalog
page.
3.11 Sign-in and tenant choice
/login offers single sign-on and, when enabled, local users. After
signing in it returns to the page that sent the caller there. A failed
single sign-on lands on /login with its reason (oidcCallback in the
API): the sign-in took too long or was started elsewhere,
the identity provider refused or failed, or the account is disabled. A session
bound to no tenant (architecture.md §12)
opens /choose: the caller's tenants (suspended ones shown, not
selectable) and, for platform admins in service mode, the platform. A
caller without a tenant sees that they have no access yet and can sign
out. An OIDC login refused for an unconfirmed email address
(architecture.md §12) lands on
/verify-email: it asks the user to confirm their address with the link
the identity provider sent, links to the account portal to send it again
(service mode), and offers to sign in again.
3.12 Billing (service mode)
The tenant's billing state comes with /api/v1/me
(architecture.md §12). A read-only tenant
shows a banner on every page: agents keep their configuration, nothing new
can be changed or enrolled; tenant admins get Book a plan (the account
UI's plans), others are asked to contact an admin. Tenant admins open the
account UI from the user menu (Billing and plans) through a single-use
link. On Admin › Users, Invite (email, name, role admin or member)
replaces adding local members, and Remove access replaces disabling a
member; both go through the billing service, which pushes the result.
4. Shared components
| Component | Behaviour |
|---|---|
| Selector field | Short form with autocomplete of label keys and values (/api/v1/labels/*), parse errors inline, and a live count of matching hosts with a link to them |
| Diff viewer | Unified or side by side, TOML- and JSON-aware, secrets masked |
| Operation progress | Progress and result of long operations (validation, imports), surviving a reload; for a bulk action, the result per object |
| Problem display | Maps problem codes to messages; lists diagnostics with links to file and line |
| Agent and host chips | Name, kind, health and sync at a glance, linking to the detail |
5. Assistant
The assistant is a panel next to every page (assistant.md). Opening it from a page passes that page as context (a host, agent, file or change set). Answers are Markdown (GitHub flavour, rendered as they stream; raw HTML shows as text). Commands it runs appear as collapsible blocks; a change set it submits appears as a link, and reviewing and merging it happen on the change set page. While the assistant explores a website (journeys.md §8.3), the panel shows the page's latest screenshot, URL and outcome, with a button that stops the session.