Skip to content

Console redesign: an Inbox of what needs you, actions on every row, built on Base UI #756

Closed
7 of 7 issues completed

Description

@V3RON

Request: none

Problem

The console only shows things. An operator who sees a stuck request, a drained worker or a lost worker has to leave it for the CLI or the HTTP API, even though the HTTP API already offers release, cancel, drain, undrain and remove. Each page is laid out a little differently. Nothing lists in one place what needs a person now, and the layout has no room for the features coming next.

Who it is for

The operator of a Simlock gateway or single host. They watch many agents lease devices across several workers, and need to see in a few seconds whether anything is wrong, then fix it from the same page.

Outcome

After this lands, an operator can:

  • open the console and see the whole system at a glance on Overview: five numbers, what needs them (or one line saying nothing does), capacity per platform, the last hour of leases held and requests waiting, and every worker;
  • open Inbox for the full list of what needs a person, and undrain a drained worker from its row in one click;
  • release a lease, cancel a waiting request, and drain, undrain or remove a worker, from the row's ⋯ menu, a right-click on the row, the item's drawer or the Inbox;
  • see each item's details in a drawer over the page, with an address that can be shared;
  • find any page, worker, device, lease or request, and run any of those actions, from ⌘K;
  • scroll Activity back through the daemon's event history, as far as it is kept, up to 10,000 events in the list;
  • read on every page the same parts in the same places: page header, toolbar, table with a pager, drawer, toasts.

How it works for the user

flowchart TD
  A[Sign in] --> B[Overview]
  B -->|nothing needs you| B1[One line: Nothing needs you]
  B -->|something does| C[Needs you: top 4, each opening its drawer]
  C --> D[Inbox: every item]
  D --> E{Fix button or row ⋯}
  E -->|undoable: drain| F[Toast with Undo]
  E -->|final: release, cancel| G[Confirm naming the thing] --> H[Toast]
  E -->|remove worker| I[Type the worker's name] --> H
  H -->|daemon refuses| J[Error toast stays: the daemon's message, Retry]
  B --> K[Fleet, Leases, Queue, Activity, Usage]
  K --> L[Row opens the drawer: details, Screen, Events]
  B -.⌘K.-> M[Search or jump to: pages, items, actions]
Loading

The sidebar, top to bottom: Overview, Inbox (with its count), then Operate: Fleet, Leases, Queue, then Observe: Activity, Usage.

On a single host, Drain, Undrain and Remove never appear: a single host has no fleet to take a worker out of.

Examples

What goes in the Inbox:

Situation In the Inbox Group
a worker is disconnected or incompatible yes Broken
a device is quarantined yes Broken
a worker is drained, over its RAM budget, or a device stalled yes Needs a look
an enrolled phone is absent (locked, untrusted, unplugged) yes (new) Needs a look
a request has waited 61 s yes (new) Needs a look
a request has waited 59 s no —
a lease ends in 4 min yes (new) Heads-up
a lease ends in 6 min (a default lease is 15 min) no —
a worker's disk is at 91% no (shows on its row and page) —

Which actions an item offers:

Item Gateway Single host
held lease Release lease Release lease
waiting request Cancel request Cancel request
connected worker, not drained Drain none
drained worker Undrain none
disconnected worker Drain or Undrain, Remove worker (cannot happen)

What could go wrong

  • An operator releases the wrong lease and an agent's run fails. Likely enough that release always asks first and names the holder, device and worker.
  • An action fails without the operator noticing. Unlikely: an error toast stays until closed and says the daemon's reason.
  • A table or drawer is harder to use with a keyboard or screen reader than today's lists. Checked by the accessibility checks in every browser.
  • Signed in through a sign-in proxy over plain http:// on a network name, every action is refused. Rare; the error toast says so.

Words used

  • Inbox: the page listing what needs a person, e.g. "linux-ci-2 is disconnected".
  • Needs you: the Overview panel showing the first four Inbox items with problems.
  • Heads-up: an Inbox item that is not a problem yet: a lease with under 5 minutes left.
  • Drawer: the panel that slides over the page from the right to show one item, e.g. a lease's details and live screen.
  • Toast: a short message in the bottom-right corner after an action, e.g. "mac-studio-2 drained · Undo".
  • Single host: a daemon running on its own, not a gateway; it has one worker, itself.

Non-goals

  • New HTTP routes or actions: retry a wipe, delete a device, extend a lease, run cleanup, snooze an item, create or revoke tokens, edit alert destinations.
  • The Manage pages (Components, Physical devices, Alerts, Access, Audit, Settings, Baselines). Each comes with its own feature.
  • A record of who did an action (Every action leaves a trace of who did it #703).
  • Redirects from the old addresses /workers, /waiting, /events, /attention.

Completion conditions

  • A person signed in with an operator token on a gateway sees Overview at /: five numbers, "Nothing needs you" when the Inbox is empty, capacity per platform, two charts, all workers.
  • Every Inbox rule in Examples holds, in the browser.
  • From the console alone, a person can release a lease, cancel a waiting request, drain then undo, undrain, and remove a disconnected worker; each ends in a toast, and the page shows the daemon's new state.
  • A refused action shows the daemon's message in a toast that stays until closed.
  • On a single host, no Drain, Undrain or Remove appears anywhere.
  • Every page has the shared header; every page with a list of items shows it in the one table component, with the shared toolbar (chips left, search right), a pager once the rows exceed a page, and details in the drawer. Overview and Usage use the shared header and toolbar. Every page passes the accessibility checks in light and dark.
  • No page, drawer, menu, dialog, toast or ⌘K search creates a <style> element or a CSP violation.
  • ⌘K finds a page, a worker, a device, a lease and a request by name, and runs an action.
  • Activity scrolls back past the last hour, to the oldest event the daemon keeps or until the list holds 10,000 events.

Open questions

Decisions

Shared values

Value or state Rule Written by Read by Source
Pages and addresses / Overview, /inbox[/<key>] Inbox, /fleet Fleet, /fleet/<workerId>[?tab=devices|warm-pool|host|events] worker page, /fleet/<workerId>/<deviceId> device drawer, /leases[/<leaseId>], /queue[/<requestId>], /activity[/<eventId>], /usage. An address whose last segment holds a . ends in /. Search text is ?q=. No redirects from old addresses; an unknown address shows Not found. #765 (renames, /leases), #766 (/fleet/<workerId>…), #768 (/, /inbox) every task, the browser lane ADR 0037 §2; ui/src/app/routes.ts:19-27; src/http/server.ts:108-111
Sidebar No group: Overview, Inbox (count = Inbox items with a problem, not heads-ups). Operate: Fleet, Leases, Queue. Observe: Activity, Usage. #765 (groups, renames), #768 (Overview, Inbox) #770 this spec
Drawer Modal over the whole console, sidebar included; opens at /<page>/<id> (or /fleet/<workerId>/<deviceId>), closes to the address it opened from, keeping the query; Escape, ✕ or the dim layer closes; animates on open only. #765 #766, #767, #768 ADR 0037 §2
Inbox items Today's six attention kinds, plus an absent enrolled phone (<workerId>/<deviceId>/absent, needs a look), a request waiting over WAITING_TOO_LONG_MS = 60 000 ms (request/<requestId>/waiting, needs a look), a lease whose deadline is under EXPIRING_UNDER_MS = 5 min away by the daemon's clock (lease/<leaseId>/ending, heads-up). Groups in this order: Broken, Needs a look, Heads-up; inside a group, worker order, then longest wait, then least time left. #768 #769, #770 ui/src/model/attention.ts:35-77, ui/src/model/leases.ts:130-135, src/core/config.ts:52
Inbox fix button Only a drained worker's item has one: Undrain. Every other item has none; its actions are under ⋯ and in its drawer. #769 #768 this spec
Ending soon EXPIRING_UNDER_MS = 5 min, one home in model/leases.ts, read by the Leases filter, Overview and the Inbox #768 #765 ui/src/model/leases.ts:130-135
Action list Per kind (lease, request, worker, Inbox item): label, when offered, confirm kind, danger. As in ADR 0037 §3. #769 #770 ADR 0037 §3
Daemon mode daemon.mode from GET /v1/status after sign-in and after each reconnect; gateway offers worker actions; anything else, or a failed read, offers none. #766 #766 (worker Events tab), #769, #770 ADR 0037 §4; src/contract/operations.ts:117
Toast and confirm wording, the action runner Written out in #769's In short; useActions().run owns the confirm, the write and the toast #769 #770 this spec

Tasks

flowchart LR
  A["#765 shell, Base UI, drawer, Leases"] --> B["#766 Fleet and worker page"]
  B --> C["#767 Queue and Activity"]
  G["#764 events history paging"] --> C
  C --> D["#768 Overview, Inbox, Usage"]
  D --> E["#769 actions"]
  E --> F["#770 ⌘K"]
Loading

The console tasks run one after another: each edits the route table, the page list in views.spec.ts and the manual's Pages table that the next one edits.

Completion conditions → tasks:

Open work in the same area:

Written by an agent.

Activity

  1. added
    feature:specSpec in progress, business and technical together.
    on Oct 20, 2026
  2. added a commit that references this issue on Oct 20, 2026
  3. V3RON commented on Oct 20, 2026

    @V3RON
    ContributorAuthor

    Spec updated: all business sections, Decisions (ADR 0037, PR #762), Shared values and Tasks (#764–#770) written from the 2026-10-20 session.

    Written by an agent.

  4. added a commit that references this issue on Oct 20, 2026
  5. added
    feature:plannedSplit into tasks. Never picked up itself.
    and removed
    feature:specSpec in progress, business and technical together.
    on Oct 20, 2026
  6. V3RON commented on Oct 20, 2026

    @V3RON
    ContributorAuthor

    Spec updated: tasks #764–#770 checked and set ready; ADR 0037 accepted (PR #762); decisions this session: Activity infinite scroll back through history, ending soon under 5 min, Undrain is the only Inbox fix button, the mode read moves to #766.

    Written by an agent.

  7. V3RON commented on Oct 20, 2026

    @V3RON
    ContributorAuthor

    Delivery run

    Merged: none (the feature merges as one stack at the end)
    In the stack, review passed: #773 (#764), #780 (#765), #787 (#766), #789 (#767), over ADR PR #762 (stack #781)
    Waiting: #768 (PR #793 part built; handoff on #768), #769 on #768, #770 on #769
    Decided: none
    Asleep: 144 min

    The run stopped at the session's 10-hour budget. Run deliver 756 in a new session to go on from #768.

    Written by an agent.

  8. github-actions commented on Oct 21, 2026

    @github-actions

    All 7 sub-issues are closed. If the completion conditions hold on main, close this feature and flip its ADRs to Accepted.

  9. github-actions commented on Oct 21, 2026

    @github-actions

    All 7 sub-issues are closed. If the completion conditions hold on main, close this feature and flip its ADRs to Accepted.

  10. github-actions commented on Oct 21, 2026

    @github-actions

    All 7 sub-issues are closed. If the completion conditions hold on main, close this feature and flip its ADRs to Accepted.

  11. github-actions commented on Oct 21, 2026

    @github-actions

    All 7 sub-issues are closed. If the completion conditions hold on main, close this feature and flip its ADRs to Accepted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature:plannedSplit into tasks. Never picked up itself.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions