docs: hub v0.53.0 closing bundle - CHANGELOG + CONTEXT (both operator rulings verbatim) + take-two F-14 disposition (SHIPPED, gated on escrow-acked deletion provenance)

This commit is contained in:
2026-07-13 15:02:44 +02:00
parent 3682303131
commit 3efb1b1af1
3 changed files with 59 additions and 2 deletions
+36 -1
View File
@@ -1,6 +1,41 @@
# Felhom Hub — Changelog
## v0.52.0 — polish batch: F-15 instant reset codes + F-16 inline confirms (2026-07-13)
## v0.53.0 — closing bundle: F-14 gated auto-Reissue + dead-host roll-up honesty + bearer out of git (2026-07-13)
The last engineering items on the pre-tester board. Two operator rulings in force (CONTEXT.md):
F-14 auto-re-issue only on a recorded escrow-acked deletion; customer status never better than
its worst expected host.
- **F-14 deletion provenance + gated auto-Reissue** (take-two MEDIUM: host delete + re-enroll
with a surviving ep0 tenancy = DR re-attach dead-end, `token_exists` on both auto-provision
and config save). New `host_deletions` table — host_id, customer_id, deleted_at,
`escrow_acked` (= ack given over a PRESENT escrow row) — written INSIDE the DeleteHost
transaction; NO backfill (pre-record deletions keep the manual path by design). The provision
atom, on `token_exists`, reads the customer's MOST RECENT deletion record: escrow_acked →
invoke the EXISTING tenantsync Reissue op, store the `pbsdr_auto_reissue` audit event
("Previous key destroyed (acknowledged deletion) — credentials re-issued automatically."),
proceed; no record / un-acked → the pre-existing refusal byte-unchanged (never-silently-re-key
law). Red-proofs: provenance-write drop → scenario-A fails; gate bypass → scenario-B's
zero-reissue assertions fail (silent re-key visible as a 303).
- **Dead-host roll-up honesty** (drill-1 observation, live on the Peti cluster: proxmox1 down
23h behind a GREEN customer row — controller reports ride the internet, independent of the
agent). Customer status on the dashboard, /configs list and customer detail (header + strip)
is now `worst(controllerDerived, hostStatusOf(each expected host))` via THE single staleness
definition (`Server.hostStatus`; no second threshold anywhere): any host down/stale caps the
customer at WARN with a cause chip naming the host ("host down: <id>"); pending hosts worsen
only after the customer has ever reported (onboarding exclusion). The three inlined
controller-status chains collapsed into `controllerStatus()` (rollup.go). Display +
derivation only — HostStalenessChecker alerting untouched. Red-proof: fold removal → the
exact Peti fixture renders green → TestRollup_DeadHostMasking fails.
- **Operator bearer out of git** (the two publish runbooks' ROTATION item): `manifests/hub.yaml`
no longer commits `report_api_key` — the Deployment injects `REPORT_API_KEY` from out-of-band
`Secret/report-api` (deliberately NOT `optional:` — a missing Secret fails Ready instead of
booting an unauthenticatable hub); main.go gains the env override (RESEND_API_KEY twin). New
gate `scripts/manifest_bearer_gate.py` blocks bearer-shaped (64-hex) literals in manifests/
(red-proven: reintroduction → exit 1). The controller repo's example-config copy of the
literal is scrubbed. The exposed git-history value dies with the SUPERVISED rotation —
procedure + full consumer list in documentation/runbooks/secrets.md §"Operator/global bearer
key" (per-customer/per-host keys unaffected).
Hub half of the polish batch (take-two findings F-15/F-16). Companion: controller v0.123.0.