R-204 item 4 (box half): a rebuilt box DECLARES that it needs a credential (v0.199.0)
An absent off-site object has four meanings — never configured, mid-restart, a transient config read failure, and rebuilt-and-stranded — and the hub cannot tell them apart. The box can, from two local facts it holds with certainty, so it says so instead of leaving the hub to deduce it from a silence (operator ruling). The ACK's identity_blob_present is now recorded on EVERY ACK, before the gates that used to discard it: on a box with no off-site target the auto-confirm returns immediately, which is exactly a rebuilt box, so the one fact distinguishing it from a box that never had off-site backups was thrown away every cycle. The declaration needs BOTH halves — a fresh data area AND a hub-held recovery package. Freshness alone is a box that never had off-site backups; dropping that condition makes the whole fleet ask for credentials, which is what the Scenario B test exists to catch. The object carries enabled:false and zero sizes, which is what makes it inert to the hub's existing fill and staleness checkers and to a pre-upgrade hub. A configured box's JSON is byte-identical to v0.198.0's.
This commit is contained in:
@@ -55,6 +55,21 @@ type Settings struct {
|
||||
// re-enabled it on every read — this replaces it).
|
||||
OffboxEnlargeNoticeSeeded bool `json:"offbox_enlarge_notice_seeded,omitempty"`
|
||||
|
||||
// HubEscrowIdentityPresent (v0.199.0, R-204 item 4 / R-193) caches the report ACK's
|
||||
// `escrow.identity_blob_present` — whether the HUB is holding a sealed recovery package for this
|
||||
// box. It is recorded on EVERY ACK that carries an escrow object, including when no off-site
|
||||
// target is configured, which is the whole point: until now that field was read only by the
|
||||
// auto-confirm, which returns early on an unconfigured box, so a REBUILT box threw away the one
|
||||
// fact that distinguishes it from a box that never had off-site backups.
|
||||
//
|
||||
// It is half of the "I am rebuilt and stranded" predicate (see backup.OffboxReportStatus). The
|
||||
// other half is local: no repository password on disk. **Freshness alone is a box that never had
|
||||
// off-site backups; an escrow alone is a healthy box. Only both together mean rebuilt.**
|
||||
//
|
||||
// Cached, not derived: a rebuilt box has an empty settings.json, so this is re-learned from its
|
||||
// first ACK — which is correct, because the hub is the authority on what the hub holds.
|
||||
HubEscrowIdentityPresent bool `json:"hub_escrow_identity_present,omitempty"`
|
||||
|
||||
// Cached state
|
||||
DBValidations map[string]DBValidationCache `json:"db_validations,omitempty"`
|
||||
|
||||
@@ -601,6 +616,30 @@ func (s *Settings) SetLauncherSharePasswordHash(hash string) error {
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// ── Hub-held recovery package (v0.199.0, R-204 item 4) ─────────────────────────
|
||||
|
||||
// GetHubEscrowIdentityPresent reports whether the hub is holding a sealed identity/recovery package
|
||||
// for this box, as last stated by a report ACK. False when no ACK has carried an escrow object yet.
|
||||
func (s *Settings) GetHubEscrowIdentityPresent() bool {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return s.HubEscrowIdentityPresent
|
||||
}
|
||||
|
||||
// SetHubEscrowIdentityPresent records the ACK's `escrow.identity_blob_present`. It is a plain
|
||||
// last-write-wins mirror of the hub's statement — NOT set-only, because the hub losing an escrow row
|
||||
// (a customer RESET) must be able to turn the box's declaration back off. Saves only on a change, so
|
||||
// the ordinary 15-minute ACK does not rewrite settings.json every cycle.
|
||||
func (s *Settings) SetHubEscrowIdentityPresent(present bool) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
if s.HubEscrowIdentityPresent == present {
|
||||
return nil
|
||||
}
|
||||
s.HubEscrowIdentityPresent = present
|
||||
return s.save()
|
||||
}
|
||||
|
||||
// ── Customer-claim arc (v0.122.0) ──────────────────────────────────────────────
|
||||
|
||||
// GetClaimed reports whether this box has completed a claim (set-only).
|
||||
|
||||
Reference in New Issue
Block a user