master
John Lauer 1.3.0: Dock Bar contract (serve --print-url, /api/status LEDs, CORS, say strip), settings modal, taskbar progress, pup vault for logins, adom-bridge + pup_* transport, dashboard overhaul per adom-ui-design, doctor for first run 83b2ae8 1mo ago

Dashboard API contract (server side, implemented in src/serve.rs + src/dock.rs)

Every /api/*, /ui/*, /state, /console, /health response carries Access-Control-Allow-Origin: *; OPTIONS on any path answers 204. All paths are relative to the app root; inside a webview the page MUST use relative URLs (API_BASE + '/api/...', where API_BASE is derived from location.pathname as today).

Existing (unchanged)

  • GET /api/library, GET /api/sources, GET /api/validate, GET /api/projects
  • GET /api/chip/<MPN>, POST /api/reveal, POST /api/open, POST /api/orientation, POST /api/deliver, POST /api/validate/<MPN>, POST /api/thumbnails/<MPN>, POST /api/refetch/<MPN>?format=&source=
  • GET /asset/*, GET /thumb/*, GET /svg/*

Live channel (poll based; 1 s)

  • GET /api/activity -> the heartbeat payload as today PLUS:
    • _toasts: [{t, message, kind}] (kind: ok | err | info), drained on read. The page renders each one as a toast.
    • _ui: [{cmd, ...}] drained on read. Commands the page MUST handle:
      • {cmd:"toast", message, kind} (same as above, alternative path)
      • {cmd:"click", id} -> document.getElementById(id).click()
      • {cmd:"select", mpn} -> select that card (open detail)
      • {cmd:"view", view} -> grid | validation | sources
      • {cmd:"open_settings"} / {cmd:"close_settings"}
      • {cmd:"zoom", mpn} / {cmd:"unzoom"}
      • {cmd:"reload"} -> location.reload()
    • _state_version: <u64> bumps whenever the library changed on disk (use it to refresh the grid instead of refetching /api/library every 4 s).

Observability

  • GET /state -> {ok, app, version, activity, library_count, complete_count, active_project, selected_mpn, view, settings_open, ui_reported_at}. The page reports its client state with POST /state/ui {selected_mpn, view, settings_open, zoom_mpn} whenever it changes (cheap; fire and forget) so the server copy is truth for the AI.
  • GET /console?limit=200 -> {ok, count, items:[{t, level, msg, source}]}.
  • POST /console {level, msg} -> the page overrides console.log/warn/error, window.onerror, unhandledrejection and posts each line here (source = "ui").

Dock contract

  • GET /health -> {ok:true, app:"adom-chip-fetcher", version}.
  • GET /api/status -> {ok, app, version, state: ok|warn|fail, leds:{<key>:{label, state, detail, _hint}}, say:[...], missing_tools:[...]}. Facet keys: dashboard, skill, tools, bridge, library. Cached 10 s; ?force=1 recomputes.
  • GET /api/say -> {ok, phrases:[...]} (from dockbar.json).
  • POST /api/say/try {phrase} -> {staged: bool, where?, reason?}.

Settings (settings-layout skill)

  • GET /api/settings -> {ok, settings:{...}, defaults:{...}}.
  • POST /api/settings {<key>: <value>, ...} -> merge + persist, returns the full settings. Typed by the default's type; enum values validated.
  • POST /api/settings/reset -> restore defaults.

Keys (with defaults and the label the UI shows):

key default label type
taskbar_progress "indeterminate" Taskbar progress during a lookup enum indeterminate / off
auto_zoom false Auto-zoom the active card bool
auto_select_active true Follow the active lookup bool
show_stock_badges true Stock and lifecycle badges on cards bool
activity_stale_seconds 90 Heartbeat considered stale after int

Credentials (pup's vault is the store; chip-fetcher keeps none)

  • GET /api/credentials -> {ok, source:"pup", credentials:[{host, username}], _hint} (passwords never returned). When the desktop is not connected: {ok:false, error, _hint}.
  • POST /api/credentials/import {hostFilter:[...]} -> starts a job (below) running pup's browser-login import (one consent dialog + one UAC prompt on the desktop).
  • POST /api/login {source} -> opens that vendor's sign-in page in the chip-fetcher pup profile and asks pup to autofill from its vault; returns {ok, url, job?}.
  • DELETE /api/credentials/<host> -> removes from pup's vault.

Jobs (for Install / Update rows with live consoles)

  • POST /api/jobs {action} where action is one of install_tools (adom-wiki pkg install adom/adom-chip-fetcher), install_skill (adom-chip-fetcher install), import_logins (pup import, optional hostFilter), refresh_status. Returns {ok, id}.
  • GET /api/jobs/<id> -> {ok, id, action, state: running|done|failed, exit_code, lines:[...], started, ended}; poll every 700 ms and stream lines into the row's console box.

UI driving (the CLI calls these; the page only consumes _ui)

  • POST /ui/toast {message, kind}
  • POST /ui/command {cmd, ...}

CLI verbs that map to the above

adom-chip-fetcher serve [--port 8786] [--print-url]
adom-chip-fetcher health | status | doctor [--fix] | say | try "<phrase>"
adom-chip-fetcher ui toast "<msg>" [--kind ok|err|info]
adom-chip-fetcher ui click <id> | select <MPN> | view <grid|validation|sources>
adom-chip-fetcher ui settings open|close | zoom <MPN> | reload
adom-chip-fetcher settings get | set <key> <value> | reset
adom-chip-fetcher login <source|list|all|import>