hub 0.167.0 source: R-1230 — a box that holds for the household's recovery code is not reported stuck and gets no off-site re-issue (measured on the test night); red-proved
This commit is contained in:
@@ -12,6 +12,12 @@
|
||||
`TestD30_TheAlarmClearsWhenTheNewKeyShakesHands` (red-proved). The stale text says an agent with D30 re-keys by itself
|
||||
15 minutes after it sees the sign, plus its next desired-state fetch; the `wg_tunnel_ok` log line is INFO; the source comment no longer says the ok event is
|
||||
mailed (it is stored, not mailed — review 2026-10-22 night).
|
||||
- **R-1230 — a held box is not „stuck".** Measured on the test night (Tester4, reinstalled): a box that consumed its
|
||||
one-time off-site password and now waits for the household's recovery code reports `offsite.state=
|
||||
awaiting_recovery_key` and no offbox target; after one hour the delivery checker read it as „burned" — a false
|
||||
`offsite_delivery_stuck` mail to the operator and a re-issue of the off-site login (a config bump that restarts the
|
||||
box's controller). The checker now stands down for that declared state (the wait is the household's, it can take
|
||||
days); an undeclared consumed shape alarms as before. `TestR1230_AHeldBoxIsNotStuck`, red-proved.
|
||||
- `scripts/wire_contract_gate.py`: `wireguard.last_handshake_age_s` left the unread list (the hub reads it since 0.166.0).
|
||||
|
||||
## v0.166.0 (unreleased — built 2026-10-22 night, NOT deployed; the deploy is the operator's yes) — the clock-ahead tunnel alarm (R-1204)
|
||||
|
||||
@@ -102,6 +102,12 @@ func (c *OffsiteDeliveryChecker) Check() {
|
||||
declared := false
|
||||
if _, _, state, derr := c.store.LatestReportOffsiteDeclaration(cfg.CustomerID); derr != nil {
|
||||
c.logger.Printf("[WARN] offsite-delivery: %s: read declaration: %v (treating as undeclared)", cfg.CustomerID, derr)
|
||||
} else if state == declaredAwaitingRecoveryKey {
|
||||
// R-1230 (test night 2026-10-23, measured): a reinstalled box that HOLDS — its credential consumed, the
|
||||
// household's recovery code not entered yet — reports no offbox target, so it read as „burned": a false
|
||||
// operator mail and a needless re-issue of the off-site login (which restarts the box's controller). The
|
||||
// box says what it waits for; that wait is the household's, and can take days. No event, no heal.
|
||||
continue
|
||||
} else {
|
||||
declared = state == declaredNeedsCredential
|
||||
}
|
||||
@@ -137,6 +143,11 @@ const (
|
||||
// are pinned together by TestDeclaredStateStringMatchesTheReconciler.
|
||||
const declaredNeedsCredential = "needs_credential"
|
||||
|
||||
// declaredAwaitingRecoveryKey mirrors the controller's backup.OffsiteStateAwaitingRecoveryKey (the box holds: the hub
|
||||
// keeps a sealed package and only the household's recovery code opens it). Pinned by
|
||||
// TestR1230_AHeldBoxIsNotStuck.
|
||||
const declaredAwaitingRecoveryKey = "awaiting_recovery_key"
|
||||
|
||||
func shapeOf(status offsite.DeliveryStatus, declared bool) deliveryShape {
|
||||
if declared {
|
||||
return shapeDeclared
|
||||
|
||||
@@ -300,3 +300,30 @@ func TestDeliveryChecker_QuietShapes(t *testing.T) {
|
||||
t.Fatalf("disabled offsite must be skipped, got events=%v calls=%d", *h.events, h.reissuer.count())
|
||||
}
|
||||
}
|
||||
|
||||
// R-1230 (test night 2026-10-23, measured live on Tester4): a reinstalled box that waits for the household's recovery
|
||||
// code reports `offsite.state=awaiting_recovery_key` and no offbox target. It must raise no „stuck" event and no
|
||||
// re-issue — the wait is the household's. The control: the same consumed shape WITHOUT that declaration still alarms.
|
||||
// RED-PROOF: with the awaiting_recovery_key skip removed, this fails (a stuck event and a re-issue) — seen failing
|
||||
// 2026-10-23 night.
|
||||
func TestR1230_AHeldBoxIsNotStuck(t *testing.T) {
|
||||
h := newDTHarness(t, true)
|
||||
h.burnedFixture(t, 5)
|
||||
if err := h.st.SaveReport("c1", []byte(`{"health":{"status":"ok"},"offsite":{"enabled":false,"state":"awaiting_recovery_key","escrow_state":"pending"}}`)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h.checker.Check()
|
||||
if n := len(h.savedEvents(t, "offsite_delivery_stuck")); n != 0 {
|
||||
t.Fatalf("a box waiting for the household's recovery code is not stuck: %d stuck event(s)", n)
|
||||
}
|
||||
if h.reissuer.count() != 0 {
|
||||
t.Fatalf("no re-issue for a held box, got %d", h.reissuer.count())
|
||||
}
|
||||
if err := h.st.SaveReport("c1", []byte(dtReportNoOffsite)); err != nil { // control: no declaration → the old verdict
|
||||
t.Fatal(err)
|
||||
}
|
||||
h.checker.Check()
|
||||
if n := len(h.savedEvents(t, "offsite_delivery_stuck")); n != 1 {
|
||||
t.Fatalf("control: an undeclared consumed shape must still alarm, got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user