R-204 item 4 (hub half): the hub answers a rebuilt box's request (hub v0.96.0)

New internal/offsiteheal, the sibling of pbsdrheal: it acts ONLY on the state the
box declares, sustained across two distinct reports, re-staging the stored
credential before ever minting a new one. A healthy box is a pure no-op; it never
blind-timer-reissues and never re-runs a provisioning step.

RESTAGE IS POSSIBLE because the stored value survives a consume — established from
the schema and ConsumeOneTimeSecret (which stamps consumed_at and nothing else),
not inherited from the PBS analogy, and pinned by a test that asserts the SAME
value comes back.

reportHasOffsite is TIGHTENED to require enabled:true. Its comment asserted that
presence == applied-on-the-box, and the declaration deliberately breaks that
premise; left alone it would have read a request for help as proof the tier was
applied. Provably a no-op for every report shape that existed before, because an
attached object has always carried enabled:true.

R-192's guard half is CLOSED BY REPLACEMENT: the delivery checker's counting
inference read the OLDEST 500 reports after a consume — all predating a rebuild,
which is why demo-hp sat stranded for 108 reports under a confident regressed-shape
verdict. A declaration outranks both inferred shapes, and the checker stands down
with a record so the two mechanisms cannot double-issue.

No escrow ceremony is ever run or requested: credential automatic, key
customer-present.
This commit is contained in:
2026-08-05 10:48:18 +02:00
parent c917251eeb
commit f62a115891
8 changed files with 1026 additions and 16 deletions
+82 -5
View File
@@ -978,11 +978,27 @@ func (s *Store) SaveReport(customerID string, reportJSON []byte) error {
return err
}
// reportOffsitePresence is the minimal parse for "does this controller report carry an offsite
// status object" — the R-70 delivery-state signal. The report builder attaches `offsite` only when
// the box actually has an offbox target configured, so presence == applied-on-the-box.
// reportOffsitePresence is the minimal parse for "does this controller report show an offsite tier
// that is actually CONFIGURED on the box" — the R-70 delivery-state signal, i.e. applied-on-the-box.
//
// ⚠ TIGHTENED 2026-08-05 (hub v0.96.0, R-204 item 4), and the reason is exactly the trap this
// project keeps recording. The predicate used to be bare PRESENCE, under a comment asserting *"the
// report builder attaches `offsite` only when the box actually has an offbox target configured, so
// presence == applied-on-the-box"*. Controller v0.199.0 breaks that premise deliberately: a REBUILT
// box now attaches an offsite object carrying `enabled:false` and a declared `state` in order to ASK
// for a credential. Left as presence-only, this function would have read that request for help as
// proof the tier was applied — turning `DeliveryStateFor` into DeliveryApplied for the exact boxes
// that are stranded, and suppressing the stuck event for them.
//
// The tightening is `enabled == true`, and it is PROVABLY A NO-OP for every report shape that exists
// today: `backup.OffboxReportStatus` returned nil unless `t != nil && t.Enabled`, so an attached
// object has ALWAYS carried `enabled:true`. Pinned by
// TestReportHasOffsite_EnabledOnly — including a case asserting the pre-v0.199.0 shape still reads
// true, so the equivalence is measured rather than argued.
type reportOffsitePresence struct {
Offsite json.RawMessage `json:"offsite"`
Offsite *struct {
Enabled bool `json:"enabled"`
} `json:"offsite"`
}
func reportHasOffsite(reportJSON string) bool {
@@ -990,7 +1006,7 @@ func reportHasOffsite(reportJSON string) bool {
if err := json.Unmarshal([]byte(reportJSON), &p); err != nil {
return false // unparseable report → no offsite evidence
}
return len(p.Offsite) > 0 && string(p.Offsite) != "null"
return p.Offsite != nil && p.Offsite.Enabled
}
// LatestReportOffsitePresence reports whether the customer's most recent controller report exists
@@ -1415,6 +1431,67 @@ func (s *Store) ConsumeOneTimeSecret(customerID string) (string, error) {
return value, nil
}
// RestageOneTimeSecret re-arms an ALREADY-STORED one-time offsite secret for re-consumption by
// clearing its consumed flag — WITHOUT changing the secret value, WITHOUT inserting a row, and
// WITHOUT any storage-provider call. It is the off-site sibling of RestageHostPBSSecret (pbsdr.go),
// and it exists because a REBUILT box has no credential of its own: its predecessor spent the
// one-time password (R-193 / R-204 item 4).
//
// IT IS POSSIBLE AT ALL ONLY BECAUSE THE VALUE SURVIVES A CONSUME, and that was established from
// this file rather than assumed from the PBS analogy (the two secrets are different objects with
// different lifecycles, and assuming a shared shape is how two sessions confused the credentials):
// ConsumeOneTimeSecret sets `consumed_at` and NOTHING ELSE — the `value` column is never cleared or
// overwritten, and the schema declares it `TEXT NOT NULL`. So the row still holds a serviceable
// password after consumption, and re-arming it costs no external call and converges in one report
// tick. Pinned by TestRestageOneTimeSecret_ReArmsTheSameValue.
//
// Returns restaged=true when a row existed (its consumed flag is now cleared, so
// ConsumeOneTimeSecret will serve it once more); restaged=false when NO secret is stored for the
// customer — the caller must then escalate to a fresh mint (ReissueCredentials). The value is never
// read or logged here.
func (s *Store) RestageOneTimeSecret(customerID string) (bool, error) {
res, err := s.db.Exec(`UPDATE one_time_secrets SET consumed_at = NULL WHERE customer_id = ?`, customerID)
if err != nil {
return false, err
}
n, err := res.RowsAffected()
if err != nil {
return false, err
}
return n > 0, nil
}
// LatestReportOffsiteDeclaration returns the id of the customer's newest controller report and the
// state DECLARED on its `offsite` object (controller >= v0.199.0; "" on anything older, on a report
// with no offsite object, and on an unparseable one).
//
// The report id is the debounce currency: the reconciler counts DISTINCT reports, not its own ticks,
// so a stuck box is confirmed by fresh evidence rather than by the passage of time.
//
// found=false when the customer has no reports at all — distinguished from "a report that declares
// nothing" so the caller never treats an absent report as a healthy one.
func (s *Store) LatestReportOffsiteDeclaration(customerID string) (found bool, reportID int64, state string, err error) {
var id int64
var reportJSON string
err = s.db.QueryRow(`SELECT id, report_json FROM reports WHERE customer_id = ? ORDER BY id DESC LIMIT 1`,
customerID).Scan(&id, &reportJSON)
if err == sql.ErrNoRows {
return false, 0, "", nil
}
if err != nil {
return false, 0, "", err
}
var p struct {
Offsite *struct {
State string `json:"state"`
} `json:"offsite"`
}
if json.Unmarshal([]byte(reportJSON), &p) == nil && p.Offsite != nil {
state = p.Offsite.State
}
return true, id, state, nil
}
// OneTimeSecretInfo is the delivery-state metadata of a customer's one-time offsite secret —
// timestamps ONLY, the value column is deliberately never selected (R-70 detector input; the
// customer-scoped sibling of PBSDRHealStates' SecretUnconsumedFor).