docs: record the live UPS command state after real-hardware verification

AGENTS.md gap 1 said the buttons were read-only in practice because no upsd.users account
had `instcmds`. That is no longer true: the login verbs, the command catalog, and the
`[dashboards]` account have each been fixed and verified against both real UPSes.

The rewrite keeps the parts that stay load-bearing: `instcmds = all` means the account may
send every advertised command including the power-cutting ones, and `available_commands()`
filters `LIST CMD` (which upsd serves unfiltered) — NUT has no call for a user's
privileges, so the risk tiers and the typed `DANGER` are the control, not decoration. Also
records what was proven reversibly (`beeper.enable` -> OK, `driver.killpower` refused
without `DANGER`), why a battery test was not run, and the rules for editing upsd.users
without dropping the account `upsmon` authenticates as.

README: `instcmds` is one command per line per `man 5 upsd.users`, the fleet runs
`instcmds = all`, and authentication uses `USERNAME`/`PASSWORD`.

LLM-Generated: true
This commit is contained in:
2026-10-17 12:27:11 -04:00
parent 9041683179
commit 9015931860
2 changed files with 56 additions and 16 deletions
+15 -1
View File
@@ -249,9 +249,23 @@ not `actions = -`:
# /etc/ups/upsd.users
[dashboards]
password = "..."
instcmds = test.battery.start.quick test.battery.start.deep test.battery.stop
instcmds = test.battery.start.quick
instcmds = test.battery.start.deep
instcmds = test.battery.stop
```
One command per `instcmds` line — that is what `man 5 upsd.users` specifies ("to specify
multiple commands, use multiple instances of the instcmds field"), and a comma-separated list
on one line is not that. `instcmds = all` is the alternative, and the fleet runs that: every
command the drivers advertise, including the ones that cut output power. Nothing about the
gates changes — the risk tier, the typed `DANGER`, `NUT_ALLOW_ACTIONS` and the on-battery
refusal are what prevent a click from becoming an outage, because upsd gives the dashboard no
way to ask what an account is allowed to send.
upsd authenticates with `USERNAME` + `PASSWORD` (see `HELP` on your own server for the verbs
it accepts — `USER`/`PASS` are not among them in 2.8.5); a user needs `instcmds`, never
`actions = -`.
`deploy/nut-sudoers` is the ruleset that lets the `ops` account read (and scoped-write) those
files: `sudo install -m 0440 -o root -g root deploy/nut-sudoers /etc/sudoers.d/dashboards-nut`.
Read `upsd.users` before you write it — `upsmon` authenticates from the same file, so