From 698145011021060d527173d624c13b6598d70af9 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Sat, 8 Aug 2026 08:46:17 +0200 Subject: [PATCH] docs: a comment claimed the hub reads a field it has no field for (R-260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Comment-only; no behaviour, no wire change, no version bump, nothing to rebuild. HostReport.SelfUpdatePending / SelfUpdatePendingVersion carried "The hub reads an absent field as pending=false, the correct default." The hub has NO FIELD for either, so it reads nothing — present or absent — and encoding/json discards them on arrival. The sentence described an intent rather than the code and read as settled long enough that a class sweep had to find it. The emission is correct and stays: the agent reports the truth and the fault is entirely in the receiving. The missing consumer is R-264 (OPEN). felhom.eu/scripts/wire_contract_gate.py now refuses any NEW field of this shape and records the existing ones as reasoned allowlist entries. --- CHANGELOG.md | 14 ++++++++++++++ internal/hub/report.go | 10 ++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9fe852..029f73d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## (no version bump) — a comment that claimed the hub reads a field it has no field for (2026-08-08, R-260) + +Comment-only; no behaviour, no wire change, nothing to rebuild. + +`HostReport.SelfUpdatePending` / `SelfUpdatePendingVersion` carried the sentence *"The hub reads an +absent field as pending=false, the correct default."* **The hub has no field for either**, so it reads +nothing — present or absent — and `encoding/json` discards them on arrival. The sentence described an +intent rather than the code and read as settled for long enough that a class sweep had to find it. + +The emission is correct and stays: the agent reports the truth, and the fault is entirely in the +receiving. The missing consumer is tracked as **R-264** (OPEN), and +`felhom.eu/scripts/wire_contract_gate.py` now refuses any NEW field of this shape while recording the +existing ones as explicit, reasoned allowlist entries rather than silence. + ## v0.127.0 — a mount Felhom itself made is not "something else" (2026-08-06, R-220) **After a rebuild the customer's own drives could not be re-attached, and the refusal named an action diff --git a/internal/hub/report.go b/internal/hub/report.go index 78df5c1..f22bd48 100644 --- a/internal/hub/report.go +++ b/internal/hub/report.go @@ -68,8 +68,14 @@ type HostReport struct { // report is stored opaquely hub-side, so these additive fields need no hub-schema change. // Both are `omitempty` (the Wireguard precedent): in the steady state (no update in flight) // they are absent — which keeps the cross-repo host-report golden contract byte-stable without - // a hub change. They appear only while an update is pending. The hub reads an absent field as - // pending=false, the correct default. + // a hub change. They appear only while an update is pending. + // + // ⚠ CORRECTED 2026-08-08 (R-260). This comment used to end "The hub reads an absent field as + // pending=false, the correct default." THE HUB HAS NO FIELD FOR EITHER OF THESE, so it reads + // nothing — present or absent — and encoding/json discards them on arrival. The sentence + // described an intent, not the code, and it read as settled for long enough that a sweep had to + // find it. The emission is correct and stays; the missing consumer is tracked as R-264, and + // `felhom.eu/scripts/wire_contract_gate.py` now refuses any NEW field of this shape. SelfUpdatePending bool `json:"selfupdate_pending,omitempty"` SelfUpdatePendingVersion string `json:"selfupdate_pending_version,omitempty"`