PLAN.md: CPU power on the Processes tab, shipped as v0.1.0-194

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Mitchell-Johnson
2026-10-11 00:00:05 -07:00
co-authored by Claude Opus 5.5
parent bfedf622be
commit a9b4d7969e
2 changed files with 9 additions and 1 deletions
+8
View File
@@ -327,6 +327,14 @@ something long in one, switch away and back, refresh — it's all still there.
`grid` the sampler hung for 42 minutes in Go's poller on the Arc's `fan1_input` —
`readStr` now uses plain blocking syscalls and each GPU's sysfs reads run under a
3-second deadline (v0.1.0-168; `hamlet/docs/gotchas.md` has the mechanism).
- **CPU power on the Processes tab** — **shipped 2026-10-10** (v0.1.0-194,
`internal/metrics/cpupower.go`, the `cpu.power` sensor). Asked for beside the clock speed,
and that is where it sits: "3600 MHz · 89 W" in the cpu box's header. Watts are the RAPL
package energy counters' delta between samples, summed over packages; `psys`, a package's
parts and the MMIO duplicate are left out. The counters are root-only, so a daemon running
as `core` keeps a second root child, `hamlab cpu-energy`, beside `drm-clients`. Read on all
four Intel machines; the Mac mini has no CPU-only counter (its SMC reports the whole
machine's draw instead) and shows nothing.
- **The ARC on the ZFS tab** — **shipped 2026-10-02** (`internal/metrics/arc.go`,
`internal/storage/arc.go`, `GET /api/zfs/arc`, the Cache section in `ZFS.tsx`, `zfs.arc.*`
sensors). Asked for as "current ARC usage, including any types of caching services in the
+1 -1
View File
@@ -106,7 +106,7 @@ The installer supports systemd, procd and OpenRC (`internal/setup/setup.go:217-2
| # | Sev | Where | Assumes | General form |
|---|---|---|---|---|
| 7.1 | **A** | `internal/priv/priv.go`; every tab that calls `priv.Available()`; `web/src/Updates.tsx:2144` "give its user passwordless sudo or doas"; `web/src/Jobs.tsx:1883` | Full function needs the service user to have **unrestricted passwordless sudo**, which `hamlet/CLAUDE.md` grants on every host here. The installer neither creates nor offers a sudoers rule, so on a fresh box most tabs are read-only and the UI tells the user to go fix sudoers by hand. | `hamlab install --sudo` writes a **scoped** `/etc/sudoers.d/hamlab` naming the commands Ham Lab runs (smartctl, zpool, zfs, systemctl, docker, journalctl, tee for its cron files, `hamlab fs|space-walk|drm-clients|replace`), or installs as root. Either way the console works out of the box. |
| 7.1 | **A** | `internal/priv/priv.go`; every tab that calls `priv.Available()`; `web/src/Updates.tsx:2144` "give its user passwordless sudo or doas"; `web/src/Jobs.tsx:1883` | Full function needs the service user to have **unrestricted passwordless sudo**, which `hamlet/CLAUDE.md` grants on every host here. The installer neither creates nor offers a sudoers rule, so on a fresh box most tabs are read-only and the UI tells the user to go fix sudoers by hand. | `hamlab install --sudo` writes a **scoped** `/etc/sudoers.d/hamlab` naming the commands Ham Lab runs (smartctl, zpool, zfs, systemctl, docker, journalctl, tee for its cron files, `hamlab fs|space-walk|drm-clients|cpu-energy|replace`), or installs as root. Either way the console works out of the box. |
| 7.2 | **A** | `internal/api/server.go:1069-1080` `clientKey()`, `:1083-1092`, `:431-433` `secure()` | The **first `X-Forwarded-For` hop is trusted unconditionally**, because here Ham Lab always sits behind Nginx Proxy Manager. On a host exposed directly, a client sets the header and defeats the per-client login rate limiter and the session IP check. | Trust `X-Forwarded-*` only from configured proxy addresses (`trusted_proxies` in config), else use the socket peer. |
| 7.3 | **B** | `internal/api/server.go:1324` `X-Accel-Buffering: no` "nginx (NPM)" | Harmless header; comment names the lab's proxy. | Keep header; generalise comment. |
| 7.4 | **B** | `internal/api/guests.go:1-9`, `PLAN.md:21` | Guest logins are full-power ("he gives these to people he trusts"). A product default. | Keep, but it is a posture decision taken for this household; a read-only guest is the generic expectation and was cut. Document as a deliberate choice in README. |