Commit Graph

5 Commits

Author SHA1 Message Date
sulthan d72c48295d fix(web): statusline tokens, unreachable dot, reachability test spans (#145)
Second review round (spec + standards):
- Polling-off and unreachable render as statusline tokens; the unreachable
  span drops mark-strong so the patina dot never sits next to red text.
- Reachability tests assert on the rendered span, which 'reachable' and
  'unreachable' substrings never could.
- A pass-log query failure now reads as reachable (no evidence rule) instead
  of condemning the browser, and admin.go loses its dead time import.
- startLatestPoller's doc no longer claims the admin page reads the poller;
  AGENTS.md carries the RefuseBackoff rename.
2026-08-21 20:41:45 +07:00
sulthan cb2b104e63 feat(web): read admin lanes from the durable pass log, not a poller snapshot (#145)
The Lanes page now projects store.LatestLanePasses and the owner-window
outcomes (store.LanePassOutcomes) into per-Site rows instead of reading an
in-memory Poller snapshot, so a deploy answers the instant the store is up.
Browser configuration is a config fact and reachability is derived from
recent browser-Site passes inside latest.RefuseBackoff.

This atomically deletes the in-memory path in the same commit that makes the
page read the DB: latest/status.go (LaneState, Status, LaneStatus,
recordLaneState) and the web.LaneReporter seam plus fakeLanes are gone, and
latest.refuseBackoff is renamed latest.RefuseBackoff at every callsite.
ownerWindow (#142) is referenced, never declared (contract C2)
2026-08-21 20:25:38 +07:00
sulthan 030ffdc26e feat: split admin surface into bookmarkable pages (#138) 2026-08-21 17:01:46 +07:00
sulthan f568fb5e8c fix: an asleep browser Lane is not a stalled one on the admin page (#110)
Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com>
Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
2026-08-16 22:04:18 +07:00
sulthan 1e6f1e985d Owner-only admin page: Reader roster plus Poll Lane status (#102) (#107)
Closes #102.

The only operational surface was /healthz and a fold-out roster inside the owner's own reading page. This adds /admin: an owner-only page carrying the Reader roster and one row per Poll Lane.

- **Poller seam.** `latest.Poller` records each Lane's last pass (`Site`, `Due`, `Checked`, `LastRun`, `Gap`, `Clamped`, `Browser`) and answers `LaneStatus()`; the page reads that snapshot, never a table. A pass that returns before computing its figures (refusal backoff, sidecar down) carries the previous pass's figures forward rather than recording zeroes, and a Lane that has never reached a pace renders no gap at all. Refusal and sidecar reachability are derived at snapshot time.
- **Owner gate at registration.** Every route reaching past the acting Reader lives in `adminRoutes()` and is wrapped in `requireOwner` when it is registered, so a missing gate is visible in the route list rather than hidden in a handler. `web.AdminPatterns()` is what the gate test walks, so a new route cannot be added without being tested. A non-owner gets 404, never 403.
- **Nil poller is a first-class state.** `main.newRouter` takes the reporter as an interface and converts a nil `*Poller` to a nil interface; no poller and no completed pass both render "No data yet" with the reason spelled out, rather than confident zeroes.
- **Roster moved** off the reading page onto /admin, with the Sighting counters and a confirm-gated `Clear marks` control. #103 fills those counters, so on delivery they read zero for everyone - deliberate ordering.
- **One accent, `--patina`** (verdigris, both colour branches): the far side of the wheel from ember's crimson and clear of the archive blue. Ember still means new chapter only; revocation still wears --danger.

Verification: `go vet ./...` and `go test ./...` green (Docker-backed); admin page screenshotted at 1100px and 390px in both colour schemes. Reviewed on both axes (spec, standards); findings on the accent hue, zero-figure honesty and three tests that could not fail are fixed in 58014eb.
Reviewed-on: #107
Co-authored-by: Sulthan Zaki <sultankiki05@gmail.com>
Co-committed-by: Sulthan Zaki <sultankiki05@gmail.com>
2026-08-16 15:02:13 +07:00