Users in HUB_DATA/users.json with scrypt hashes and roles (viewer, operator,
apps-admin, admin), managed by hub/users-cli.ts; HUB_USER/HUB_PASSWORD remain a
bootstrap admin while the file does not exist. Five failed logins in 15 minutes lock
the address or the name for 15 minutes. Logins, logouts and every refused request go
to a JSON Lines audit log that admins read through hub/audit/list. Endpoints are
listed in routes.ts with their kind and capability; writes stay refused for now.
Optional <ID>_ADMIN_TOKEN is read for the coming write stages. The management plan
is in docs/hub-management-plan.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The live UI did not follow the canvas because its base layer differed: dark
palette in hex (now the canvas oklch values), 13 px body text, flat Frame panels.
- Tokens: canvas palette, 14 px body, 1.4 line height; Frame without `dense`
gets the 3 px ring; Panel takes a description line.
- Shell: 56 px brand button with version, 11 px group headings, user card at the
foot, versions moved into the header status popover, Home / group / section
crumbs, amber "Attention" status when blocking is off or paused.
- New KpiStrip and PageTabs; Dashboard KPIs in three frames and a Refresh button.
- Zones: KPI strip, tab with count, views, framed table with the canvas columns.
- Apps: Installed / App Store tabs and a grid instead of cards (store inline).
- Blocking: state banner and tab counts; one "Blocking" title.
- Settings: actions in the header, label-and-help rows with the control on the right.
- DHCP, Administration, DNS Client, Logs, Cache, About: subtitles, framed tables,
KPI strips where the data exists; Login cover with the three-point list.
- docs/compose.shnt.example.yaml: production compose with the console image.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>