Files
enricobuehler 47dbd7b514 The host learns to end its own day: sleep, restart and shutdown as gated actions
design/host-actions.md P0 (host core) + P1 (web console). A reusable action
registry — GET /api/v1/actions (per-caller permission + honest availability) and
an id-only POST /api/v1/actions/{id} on the mgmt cert lane — with three power
built-ins, so the Wake-on-LAN round trip finally closes from the couch.

Core: GRANT_POWER (1<<6) joins the mask; GRANT_ALL 0x3F -> 0x7F; the legacy-full
read rule (an explicitly stored pre-power 0x3F reads as the current GRANT_ALL,
so old Full records neither render Custom nor silently lack Power); typed close
RejectReason::HostPower (0x6B) so ended sessions say why.

Host: power executors (logind via zbus behind the already-shipped polkit rule,
deliberately without -ignore-inhibit; Windows SeShutdownPrivilege +
InitiateSystemShutdownExW / SetSuspendState; macOS answers 501); ordering
reply-202 -> typed close -> 1 s grace -> act; single-flight; another device's
live session blocks a cert-lane invoke (409); action.invoked on the event bus;
denials logged once per (fingerprint, action) per boot. The plugin token gets
neither route.

Console: Host-power card (password-confirmed, the update-apply recipe) + a BFF
route that keeps the invoke off the ungated catch-all; Host power toggle in the
Access sheet. Mirrors: web/Kotlin/Swift consts + legacy rule, pf-client-core
preset_label now masks (an old client no longer renders a new host's Full as
Custom). Tray's service-restart row renamed Restart Punktfunk before the
clients ship a machine-level Restart host. Docs: host-power page, access-levels
row, WoL cross-link. openapi/header/SDK regenerated.
2026-08-28 21:54:15 +02:00
..