Two owner-gated POST routes write the durable poll_lanes pause stamp the
poller's top-of-pass gate already reads: /admin/lanes/{site}/pause validates
the duration against the fixed 1h/6h/24h allow-list and the Site against the
registry, and /admin/lanes/{site}/resume zeroes the stamp. Both cap the form
body like the API path, answer with the freshly rendered Lanes block, and
never command the poller — the pause is a fact about the Site, so it
survives a restart. The Lanes page's c-ctrl slot now carries the pausebar:
Resume while paused, the duration select plus Pause while running, with the
paused phrase read from the live poll_lanes stamp so a press renders as
paused with no pass having run. Tests cover the round trips, rejections,
body caps, the pause-before-refusal ordering, fresh-poller survival, resume
restoring the full queue, and acquisition being unaffected.
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.
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)
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>