diff --git a/PLAN.md b/PLAN.md index f2004fc..848fd79 100644 --- a/PLAN.md +++ b/PLAN.md @@ -587,6 +587,41 @@ something long in one, switch away and back, refresh — it's all still there. `POST /api/password`, current password required), Access tokens (list/revoke the tokens hubs hold), About (version, host, arch, uptime, certificate). +## Network tab (2026-09-27) + +A **Network** tab, per machine like every other: the interfaces as the kernel has them +(addresses, MAC, MTU, negotiated link speed, carrier, byte totals, live rates from the +sampler's own sensors), the default route and resolvers, what the internet sees of this +connection, and an **internet speed test**. + +Decisions worth keeping: + +- **Measured by the daemon, not the browser.** The test runs on the machine in the switcher, + so the figure is that machine's line — the router's, if you switch to `gate` — and it + carries on if the phone locks or the tab closes. The page polls a run it is not driving. +- **No tool to install.** It measures against Cloudflare's public speed endpoints + (`__down`, `__up`, `cdn-cgi/trace`), which is what makes it work identically on Debian and + on OpenWrt, where `opkg install` costs flash. That is the feature's one external + dependency, and it is named in `internal/network/speedtest.go`. +- **Several streams, HTTP/2 off, and the ramp thrown away.** One stream over one connection + measures a congestion window; HTTP/2 would put every stream back on one connection and do + the same. The first second of each phase is measured and discarded. +- **Latency is the round trip less the far end's own Server-Timing.** A zero-byte response + is mostly Cloudflare's worker running — 20 to 45 ms of it against a few ms of wire. Left + in, it reported 31 ms for a 7 ms line. Jitter is the mean change between consecutive + probes, not a standard deviation, so one slow probe doesn't run away with it. +- **A refused phase is not a number.** The far end rate-limits by volume, and a test moves a + few hundred megabytes; several in a row earn 429s. So: a 20-second cooldown between tests, + a stream that retries twice before giving up, the rate computed over the window in which + bytes were actually still arriving, and a plain sentence when it was cut short. Coasting to + the end of the clock with nothing arriving reported a third of the truth. +- **The last result is published as sensors** (`net.internet.*`), so the line is a widget, a + graph, an alert or a Prometheus series like anything else. Each carries the time the test + ran, not the time it was asked for. +- **Not scheduled.** Nothing takes a speed test on its own. A nightly one recorded to the + history is the obvious next step and deliberately not built yet — the cron shape for it + already exists twice over (ZFS snapshots, Docker image updates). + ## To do - **Grow the Files tab until copyparty can go** — asked for 2026-09-23 as two items (Files diff --git a/README.md b/README.md index 7642367..a075d1f 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,7 @@ What adapts to the host, rather than assuming Debian: | Updates tab | apt, dnf, zypper, pacman, apk: list, refresh, upgrade, install (pacman: all or nothing) | | Services / timers | systemd of any age (JSON output where it exists, the plain table before v246); a clear message on hosts without systemd | | Disks | `lsblk`, or `/sys/block` when it's missing (busybox) or too old; SMART and ZFS only when their tools are there | +| Network | `/proc` and `/sys` for the interfaces, addresses, link speed and default route. The speed test needs no tool installed: it measures against Cloudflare's public speed endpoints, so it works the same on Debian and on the OpenWrt router | | Dashboard | `/proc` and `/sys` only: hwmon or thermal-zone temps, fans, NICs, disks, mounts; empty sections where the hardware has nothing to report. UPS from whichever of `pwrstat`, NUT (`upsc`) or `apcupsd` is installed | | Listen address | bound with `IP_FREEBIND`, so a LAN address that isn't up yet at boot doesn't fail the start | | Self-update | the new build must run and load this host's config before it replaces the old one; atomic rename; the daemon then re-execs itself, so it restarts the same way under systemd, OpenRC or nothing; `hamlab.prev` kept | diff --git a/SENSORS.md b/SENSORS.md index b3812c3..600dea9 100644 --- a/SENSORS.md +++ b/SENSORS.md @@ -16,6 +16,7 @@ cpu.usage cpu.core..usage cpu.temp load.1|5|15 uptime mem.total|used|avail|free|cached|buffers|used_pct swap.total|used|avail|used_pct temp..