Hub v0.149.0: a box the household switched off is not an outage for 14 days (R-998)
gates / gates (push) Successful in 6m40s

hosts.deliberate_off_at follows the agent's deliberate_off field (set, then cleared by the first
report of a new boot; one info event each way). While held, every silence alarm is held: host and
node staleness, the 05:00 backup deadlines, off-site and restore-test freshness, the OS alarms and
the kernel notice. After 14 days the usual alarms fire once, naming the power-off. Pages show
KIKAPCSOLVA and the time. Consequence tests with controls; each guard red-proofed.
This commit is contained in:
2026-10-13 19:47:02 +02:00
parent ed59bf3cbd
commit 50e47e29af
24 changed files with 638 additions and 17 deletions
+6
View File
@@ -744,6 +744,11 @@ type hostReportPayload struct {
CollectedAt time.Time `json:"collected_at"`
Lines []string `json:"lines"`
} `json:"log_tail"`
// DeliberateOff (R-998, agent >= 0.155.0): the household asked this box to power off, in its current boot.
// Absent = not (or an older agent). deliberate_off.go turns it into the host row's hold.
DeliberateOff *struct {
RequestedAt string `json:"requested_at"`
} `json:"deliberate_off"`
}
// hostForeignKeyArchives mirrors the agent's hub.ForeignKeyArchives (R-366 slice 2).
@@ -921,6 +926,7 @@ func (h *Handler) handleHostReport(w http.ResponseWriter, r *http.Request) {
h.checkTunnel(hostID, custID, rep.Cloudflared.Status, rep.Cloudflared.Detail)
h.checkCrash(hostID, custID, body)
h.checkDeliberateOff(hostID, custID, &rep)
for _, g := range rep.Guests {
status := g.Status