From a9b4d7969ee425b4d113b6cd97e0ec9d9efd561f Mon Sep 17 00:00:00 2001 From: Mitchell-Johnson Date: Sun, 11 Oct 2026 00:00:05 -0700 Subject: [PATCH] PLAN.md: CPU power on the Processes tab, shipped as v0.1.0-194 Co-Authored-By: Claude Opus 5.5 --- PLAN.md | 8 ++++++++ PORTABILITY.md | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/PLAN.md b/PLAN.md index 94ce87b..f816813 100644 --- a/PLAN.md +++ b/PLAN.md @@ -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 diff --git a/PORTABILITY.md b/PORTABILITY.md index d64bf66..21ef249 100644 --- a/PORTABILITY.md +++ b/PORTABILITY.md @@ -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. |