phase: 20_masthead_nav_polish
**Phase 20 final verification pass — all four tasks already complete; verified in full.** - Verified: three-row masthead CSS (`.masthead` flex-wrap + two `flex-basis: 100%`, `min-height`, no `margin-inline-start`), un-sticky `position: relative` + `z-index: 40`, 180 ms `visibility/opacity/transform` slide (closed `nav.tabs` / open `.is-open`, both states in the file's single reduced-motion block), both admin links on all 8 signed-in pages, `/login` neither. - `uv run pytest` → **1464 passed, 15 skipped** · `uv run pytest --cov --cov-fail-under=94` → **98.94%** (floor 94, unchanged) · `ruff check src tests agent` clean · `pyright` 0 errors · **`bash .agents/validate.sh` EXIT=0** (incl. `node --check` + repo hygiene) · `uv run pytest -m live --live` → **11 passed**. - Browser (live dev server, invariant 10): `20-task01-rows.cjs` 121 PASS/0 FAIL · `20-task02-unsticky.cjs` 81/0 · `20-task03-slide.cjs` 32/0 · `20-task04-admin-links.cjs` 87/0 · phase-18 `nav-final-pass.cjs` 45/45, `nav-task03-verify` 77, `nav-task04-verify` 24/24 · phase-19 scripts 11/22/24/29 all pass. Screenshots refreshed in `data/logs/` (`masthead-rows*`, `masthead-unsticky*`, `slide-*`, `admin-links-*`). Dev server restarted; `/api/health` all nine sources `ok`. - Completion criteria: 3-row bar @1280/360 ✓ · scroll leaves bar behind + dropdown under whole bar ✓ · slide out/in 180 ms, reduced-motion snap ✓ · `/certs`→`⚷ Certs`, `/settings`→`⚙ Account` before theme toggle, outside `.tabs` ✓ · pytest/coverage/ruff/pyright ✓ · validate ✓ · no regression in tab structure, token reveal, safe-area padding, four close paths, status dots, theme toggle ✓. - Docs: **AGENTS.md** gap 12 still said phase 20 was "in `todo/`… admin-link half has landed" and attributed the wrap to the old fixed 58 px row — rewritten to the completed state (three rows/un-sticky/slide/both links; 24 still todo; 21's `/certs` `.scroll` noted as not reaching `/`'s table). **README.md** `web/` bullet enumerated the controls row without `⏸ Pause` and omitted `/login` from the two-row list — both fixed. Everything else (setup, commands, env table vs `config.py`, routes vs `api.py`, agent/installer flags, testing policy) verified consistent. - Deviations: no dependency bump — `uv pip list --outdated` still reports the pre-existing advisory `fastapi 0.153.0 → 0.156.4` (deps untouched this phase, validate treats it as advisory); `NOTES.md` is empty in the working tree from an operator edit outside these tasks (both items live in phases 20/24) — left as-is; no live-infra changes made or needed. - Next pending phase: `21_page_cleanups` (pause button removal, `/system` GPU values, `/certs` table scroll).
This commit is contained in:
@@ -14,7 +14,7 @@ No Prometheus, no Grafana, no CDN, no build step. Nothing is fetched from the in
|
||||
runtime; every asset is served by this app.
|
||||
|
||||
Three more pages are not dashboards: `/login` (the one thing an anonymous visitor sees),
|
||||
`/settings` — `⚙ Account` in the masthead of every dashboard — which shows this browser's
|
||||
`/settings` — `⚙ Account`, in the masthead of every signed-in page — which shows this browser's
|
||||
session, signs it out, and changes the admin password, and `/certs` — `⚷ Certs`, beside it —
|
||||
which is the certificate authority the agents are dialled with: the root CA, this dashboard's
|
||||
own client certificate, and one row per host with its rotate, revoke and bundle download.
|
||||
@@ -356,8 +356,8 @@ in-app path (`/ups`, not `//evil.example`), judged on the server and again in th
|
||||
|
||||
### The account page
|
||||
|
||||
`/settings` — reached by `⚙ Account` in the masthead of every dashboard — is the session facts and
|
||||
the one form that changes the password.
|
||||
`/settings` — reached by `⚙ Account`, which sits in the masthead of every signed-in page including
|
||||
this one — is the session facts and the one form that changes the password.
|
||||
|
||||
| Panel | What it says, and what the button does |
|
||||
| ----- | ------------------------------------------------------------------------ |
|
||||
@@ -642,10 +642,21 @@ certs.py ─ root CA + client cert, minted once at startup (unreadable row → n
|
||||
* `web/` — five static dashboard pages (`/`, `/system`, `/disks`, `/llm`, `/ups`) plus the three
|
||||
admin pages (`/login`, `/settings`, `/certs`), one stylesheet, hand-rolled
|
||||
SVG charts (`charts.js`), and a masthead status dot per dashboard job (`disks` has its own:
|
||||
the same agent can answer the 10-second utilisation poll and have a wedged SMART pass). At
|
||||
≤640px the five tab links leave the bar and come back as a dropdown under it, opened by the `☰`
|
||||
button (`/login` renders no tabs, so it has no button either), and above it the masthead stays
|
||||
the one row it has always been. No framework, no CDN, no bundler, and no narration: a page never
|
||||
the same agent can answer the 10-second utilisation poll and have a wedged SMART pass).
|
||||
The masthead is **three left-justified rows at every width**: the brand and the five dashboard
|
||||
tabs, then the per-source indicators on their own row, then the clock / `⏸ Pause` (on the four
|
||||
pages that poll) / `⚷ Certs` / `⚙ Account` / `☾ Dark` controls on a row under those (a page with no
|
||||
indicators — `/login`, `/settings`, `/certs` — renders two, and a control is never hidden to make a
|
||||
narrower width work). Both admin links are on all eight
|
||||
signed-in pages, the two pages they name included: the cluster is the same wherever you are, and a
|
||||
link to the page you are already on is a harmless no-op rather than chrome that vanishes. The bar is **not sticky**: it scrolls away
|
||||
with the page, so every pixel of height goes to the data (it stays a positioned element, which is
|
||||
what keeps the mobile dropdown anchored under it). At ≤640px the five tab links leave the bar
|
||||
and come back as a dropdown under the whole of it, opened by the `☰` button (`/login` renders no
|
||||
tabs, so it has no button either), and that menu **slides**: 180 ms of fade plus an 8 px rise on
|
||||
the way out and the same on the way back in, with nothing hidden from a keyboard or a screen
|
||||
reader while it is shut, and no motion at all when the system asks for none
|
||||
(`prefers-reduced-motion`). No framework, no CDN, no bundler, and no narration: a page never
|
||||
explains its own pipeline, so the words on screen are the ones you act on — a unit, a `Δ10.0s` provenance tag, a
|
||||
`SIMULATED` badge, or the sentence beside an empty panel. The overview (`/`) is exactly two panels — a
|
||||
**Warnings & errors** list built from `/api/summary`'s `alerts` (each row links to the
|
||||
|
||||
Reference in New Issue
Block a user