# REPORT — the hub's System page, made readable (2026-10-10) **Before:** 3 cards plus one box table with 30 columns that scrolled sideways. Release ids, cancelled TEST approvals and package counts came first. The red „Approve now (guest + host)" sat in the middle of the page. **After:** 4 parts, in this order: 1. Needs attention. 2. Waiting for you. 3. Boxes: one 7-column table. Each row opens in place. 4. Details: closed by default. No sideways scroll at 1280 px or at 390 px (measured: `scrollWidth == clientWidth` at both widths). Built and tested only. **No deploy, no release, no box touched.** It ships with the next hub release. ## Baseline - `felhom.eu` `main` @ `ec5605d4` after `git pull --rebase`. The last hub release in `hub/CHANGELOG.md` is v0.145.0. - Architecture read: `05-hub-architecture.md` §5 (floors, vouched agent), `11-os-updates.md` §5.7, §5.8 and §5.11 (System page, lanes, kernel approval), `08-alarm-ladder.md` §6.3 (the colours). ## What changed - `hub/internal/web/system_view.go` (new) is the view model: - `buildSystemPage` takes all the inputs and is pure, so the fixture can feed it. - `summariseRow` makes the box mark and the plain-words reasons, from the same cell colours as before. - `buildWaiting` makes the cards, with the same gate the buttons always had: a set exists, it is not approved, and nothing is waiting. - `hub/internal/web/system.go`: the handler fills `systemInput`. It now also reads the controller version per box (`GetCustomers`). It reads the candidate package list and the healthy-night count, both only to describe a card. - `hub/internal/web/templates/system.html`: the new layout and its page CSS. It uses the hub's colour tokens. The nav wraps on a phone (this page's CSS only). - Docs: `05` (a short paragraph) and `11` §5.7 (the new layout). `hub/CHANGELOG.md`: an „Unreleased" entry. ## Where each old item went (the Baselines contract) | Old item | Now | |---|---| | Flash / error line | unchanged, at the top | | Per box: the 30 columns, the ring button, the updates switch | Boxes: the row opens to all of them. Ring, health, controller + agent, OS updates, kernel and last night are also in the row | | Approved releases (ids, packages, by, TEST) | **Details** | | „Approve now (guest + host)" | **Details**, beside the releases. It now asks: „Approve the guest and host sets now, without the usual 24 h and one night?" | | Cancelled approvals (last 7 days) | **Details** | | What ring 0 runs now (counts, first seen, the wait reason) | **Details**. A set still being tested is also listed under Waiting for you, with the hub's reason | | Approve Docker / Proxmox / kernel set | Waiting for you: one card each, when the button is allowed | | Version floors, global floor, vouched agent | **Details** (the `#version-floors` link opens it) | | kernel.panic, oops, crash restarts, crash guard, root files | in each box's row, and also as a table in **Details** | | Legend („unknown" = could not read, never a guess) | under the Boxes title | Same routes and the same `_csrf` field on every form. Clicking to open works without JavaScript (`
`). ## Tests - `go build ./... && go vet ./... && go test ./...` in `hub/`: rc 0. `python3 scripts/repo_gates.py --fast`: rc 0. - Pushed as `cf6fec8d`. CI job **1643** (matched on `head_sha`): `completed`, conclusion **success**. - New file `system_layout_test.go`. Each test below was **red-proofed: I broke the code on purpose and saw the test fail**. - Every old item is still on the page. Red: I dropped the containerd line → `Boxes lacks ">containerd"`. - Every form carries `_csrf` and posts only to the old routes. Red: I removed `_csrf` from a card → `form /os/approve-pve lacks the CSRF or return field`. - Needs attention: a green box is not listed; amber and red boxes are, with reasons; all green gives one line. Red: I skipped the cells → `the amber box (agent behind) is missing`. - Waiting for you: a card per lane, the not-ready line, nothing once approved, guest/host never a card, and the empty line. Red: I dropped the wait gate → `kernel not ready: cards [...]`. - Approve now is inside Details and asks first. - Changed old assertion: `system_trim_test.go` now looks for `>Last disk trim` (it was ``). The label moved from a table header into the box panel. ## Screenshots (made-up fixture shaped like today: 4 boxes, kernel approved, Docker still testing, Tester 2 „unknown") All are in `documentation/audits/hub-system-page-2026-10-10/`. They were taken with a headless Chromium in the scratchpad, from `system-fixture*.html`. Those pages are written by `SYSTEM_PAGE_FIXTURE_OUT= go test ./internal/web/ -run TestSystemPage_WriteFixture`. - `01-1280.png` — the page at 1280 px. - `02-390.png` — the page at 390 px (phone). - `03-1280-details-open.png` — Details open. - `04-1280-box-open.png` — one box (Tester 1) open. - `05-1280-waiting-card.png` — a Proxmox set ready, as a card with its button. ## Not done / notes - Guest and host sets get no card: they approve themselves. Their urgent override („Approve now") is in Details. - The flash after an approval still says `approved `. That text comes from the `/os/` route, not from this page, so I left it. - Teardown: provisioned nothing. No machine, no host, no hub change. ## Questions for the operator 1. Look at the five screenshots. Is the order right (problems first, then approvals, then boxes)? OK, or what to change? 2. Tester 2 („agent older than v0.142.0") shows red for „agent behind" plus three amber reasons. Do you want an old agent as one line only, or is the full list useful?