hub v0.159.0: a refused whole-guest backup has its own alarm (R-1150); a reinstall re-issues the claim code and the off-site login when the old host is stale or off (R-1154)
R-1150: the agent's localapi:backup-cadence-cap is a separate per-host state in HostCapabilityChecker: alone it raises whole_guest_backup_refused (warning, plain text, agent reason in details) and whole_guest_backup_refusal_cleared (info); other critical caps keep agent_capability_degraded/_recovered unchanged. New types operator-only and hub-origin only (not in allowedEventTypes: the suspected controller must not post them). agent_capability_degraded/_recovered join operatorOnlyEvents (the checker's "never the customer" claim was configuration only). R-1154: handleHostEnroll's reuse path re-issues (claim code + off-site login) when no controller wait is open and either deliberate_off_at is held or both the host report and the controller report are older than alerting.stale_threshold (wired from main); once per silence (host_reenroll_reissued record, also written at mint); a live box gets nothing re-issued and the skip is recorded (host_reenroll_not_reissued). 05 section 8 [DESIGN]. Tests red-proved; go build/vet/test green.
This commit is contained in:
1 parent
e4f022a0d9
commit
5121536f10
14 files changed
+995
-33
No files matched your search
@@ -337,6 +337,9 @@ func main() {
|
||||
}
|
||||
apiHandler := api.New(dataStore, cfg.API.ReportAPIKey, cfg.Notifications.ResendAPIKey, cfg.Notifications.FromEmail, templateProvider, logger)
|
||||
apiHandler.SetAssetManager(assetsMgr)
|
||||
// R-1154: the host-enroll reuse path judges "the old box is gone" by the same threshold as hostStatus and the
|
||||
// staleness checkers (unwired = it never re-issues). Pinned by r1154_wiring_test.go.
|
||||
apiHandler.SetStaleThreshold(staleThreshold)
|
||||
|
||||
// Initialize notification dispatcher
|
||||
dispatcher := notify.NewDispatcher(
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// R-1154 seam wiring: main() must hand the api handler the SAME stale threshold the staleness checkers get
|
||||
// (apiHandler.SetStaleThreshold(staleThreshold)). Unwired, the host-enroll reuse path never re-issues the claim
|
||||
// code and the off-site login on a reinstall — the R-1154 defect, back in silence.
|
||||
//
|
||||
// COMPANION RED-PROOF (observed 2026-10-19): with the call deleted from main.go this fails with
|
||||
// "cmd/hub/main.go never calls apiHandler.SetStaleThreshold(staleThreshold)". Restored.
|
||||
func TestR1154_MainWiresTheStaleThresholdIntoTheAPI(t *testing.T) {
|
||||
f, err := parser.ParseFile(token.NewFileSet(), "main.go", nil, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
wired := false
|
||||
ast.Inspect(f, func(n ast.Node) bool {
|
||||
c, ok := n.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
sel, ok := c.Fun.(*ast.SelectorExpr)
|
||||
if !ok || sel.Sel.Name != "SetStaleThreshold" || len(c.Args) != 1 {
|
||||
return true
|
||||
}
|
||||
recv, _ := sel.X.(*ast.Ident)
|
||||
arg, _ := c.Args[0].(*ast.Ident)
|
||||
if recv != nil && recv.Name == "apiHandler" && arg != nil && arg.Name == "staleThreshold" {
|
||||
wired = true
|
||||
}
|
||||
return true
|
||||
})
|
||||
if !wired {
|
||||
t.Error("cmd/hub/main.go never calls apiHandler.SetStaleThreshold(staleThreshold)")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user