Skip to main content

SPEC-0015: Operator Board v2 (Charm-Web)

SPEC · SPEC-0015 · Status · draft · Date · 2026-07-18 · Implements · ADR-0018 · Requires · SPEC-0003, SPEC-0007, SPEC-0012

Overview

The redesigned human surface: the charm-web design language (ADR-0018) applied across a six-view information architecture — board · todos · endpoints · personas · friends · providers — with a three-lane live patch-panel board, full-page wizards, a global keyboard map, and day/night themes. Supersedes SPEC-0013 (Operator Board). The durable architecture of SPEC-0012 (embedded templates, HTMX + SSE, CSRF, error standards, no-JS fallbacks) is inherited, not restated. The Providers view's backend contract is SPEC-0017; this spec owns its placement in the IA and shared chrome.

Requirements

Requirement: Design Token System

The UI SHALL be styled exclusively through a charm-web token layer replacing the Operator/brass tokens: a day theme (lavender-paper, deepened accents) and a night theme (blue-black, neon), both complete, selected via prefers-color-scheme with an <html data-theme> override. Trust-mode and todo-state colors SHALL exist as named tokens in both themes, and token text/background pairs SHALL pass WCAG AA, enforced by porting the existing contrast test to the new palette.

Scenario: Contrast gate

  • WHEN the token stylesheet changes
  • THEN the automated contrast test fails the build if any declared token pair drops below AA in either theme

Requirement: Typography And Vendored Fonts

The UI SHALL use JetBrains Mono (body/UI/code) and Space Mono (display), vendored as woff2 under static/fonts/ and embedded — no font CDN. The Zilla Slab and IBM Plex families SHALL be removed. The font-coverage test SHALL retarget to the new files.

Scenario: Offline serve

  • WHEN the binary runs with no outbound network
  • THEN all UI text renders in the vendored faces with zero external requests

Requirement: Application Shell And Navigation

The shell SHALL present the top bar (wordmark, ~/operator breadcrumb, MCP-connected indicator, "+ new" wizard launcher, theme control) and a six-view navigation: board, todos, endpoints, personas, friends, providers. Every view SHALL end in a key-hint footer rendering the active keymap. The login page SHALL be restyled in the same language.

Scenario: Providers joins the IA

  • WHEN an operator opens any view
  • THEN navigation offers all six views, with the active view indicated

Requirement: Theme Toggle

The shell SHALL provide a visible theme control (and the t key) cycling day/night, persisted in localStorage, applied before first paint without flashing the wrong theme, and without violating the same-origin CSP (no inline scripts; a tiny external boot script or CSP hash).

Scenario: Returning operator

  • WHEN an operator who chose night reloads on a day-preferring OS
  • THEN the page paints night from the first frame

Requirement: Patch Panel Board

The board SHALL render three lanes — received, verified, patched through — as the live view of every inbound line. Lane semantics: received holds ephemeral in-flight cards (an event arriving/being verified, SSE-only, never persisted as a distinct state — rejected events leave the lane with a rejection surface, accepted ones advance); verified holds durable todos not yet claimed (trust check passed, normalized, deduped); patched through holds todos claimed by or completed under an agent. Cards SHALL carry provider glyph, title, trust chip, state chip, and age; lane headers SHALL carry live counts. Cards SHALL move between lanes over SSE without reload.

Scenario: A signed webhook crosses the board

  • WHEN a signed GitHub webhook is received, verified, stored as a todo, and later claimed
  • THEN its card appears in received, advances to verified on todo creation, and moves to patched through on claim — each transition pushed live

Scenario: Rejected caller

  • WHEN a webhook fails signature verification
  • THEN the payload is not persisted (SPEC-0001 unchanged) and the received lane surfaces the redacted rejection transiently

Requirement: Todos View And Drawer

The todos view SHALL present the durable queue as a filterable table (line, provider, trust, state, age) with the detail drawer (lifecycle timeline, idempotency key, lease, claimed-by, payload, requeue/cancel actions) restyled in the new language, preserving all current actions and SSE row updates.

Scenario: Live claim

  • WHEN an agent claims a todo while the view is open
  • THEN the row's state chip updates in place without reload

Requirement: Endpoints View And Vend Wizard

The endpoints view SHALL render vended endpoints as cards (principal, persona, queues, verbs, MCP URL, credential tail with hashed/last-used, expiry countdown, rotate/revoke). Vending SHALL become a full-page wizard: persona → queues → verbs → credential lifetime → vend, ending in the one-time credential reveal with copyable .mcp.json. For OAuth-capable clients the reveal SHALL offer the URL-only variant (SPEC-0016). Scope stays immutable; the wizard SHALL make re-vend the path for scope changes (SPEC-0007 doctrine).

Scenario: Lifetime chosen at vend

  • WHEN the operator selects a 7-day lifetime and completes the wizard
  • THEN the endpoint records its expiry, the card shows the countdown, and the reaper enforces it (SPEC-0016 REQ "Credential Lifetime")

Requirement: Personas View And Wizard

The personas view SHALL render persona cards (initials block, name, human-authored prompt, verb subset, derived skills, vended-as usage). Creating/editing SHALL be a wizard whose final step shows a live preview of the A2A Agent Card rendered from unsaved form state, so the operator sees exactly what peers will discover before saving.

Scenario: Preview before publish

  • WHEN the operator edits the verb subset in the wizard
  • THEN the previewed card's advertised skills update to the derived set before anything is persisted

Requirement: Friends View And Approval Flow

The friends view SHALL separate pending · in your queue from established edges (direction, peer, queues, last-seen, revoke). The approval flow SHALL present "approving is the vend" — showing the scoped endpoint that approval mints — and on approval SHALL surface the vended result explicitly rather than only a toast. Per-direction, revocable, non-transitive semantics (SPEC-0010) are unchanged.

Scenario: Approve mints and shows the grant

  • WHEN the operator approves a pending friend request
  • THEN the flow completes with the vended endpoint's identity and scope visible, and the edge moves to established

Requirement: Global Keyboard Map

The UI SHALL implement a global keymap — g then a view key (go to view), / (focus filter), enter (open selection), t (theme) — declared in one registry that both drives behavior and renders the key-hint footer, so hints never drift from bindings. Bindings SHALL never shadow text inputs.

Scenario: Hints match behavior

  • WHEN a key binding changes in the registry
  • THEN the footer hint changes with it, with no second source of truth

Requirement: Wizard Interaction Pattern

Create/vend/connect flows SHALL be full pages (not overlay modals) with server-side step state, back navigation that preserves entered values, and a no-JS fallback that completes the same flow. Destructive and irreversible steps (vend, revoke) SHALL confirm before executing.

Scenario: JavaScript disabled

  • WHEN an operator completes the vend wizard with JS disabled
  • THEN every step renders server-side and the flow completes identically

Requirement: Live Fragment Architecture

SSE live updates SHALL continue through the existing hub with per-view fragment template files (splitting the shared fragments file), and lane movement SHALL be expressed as typed events with out-of-band removal + insertion. The SSE hub and auth (SPEC-0012) are unchanged.

Scenario: Fragment isolation

  • WHEN a todos fragment changes
  • THEN no board or friends template file is touched