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
+22
View File
@@ -3,6 +3,28 @@
> Created with the REUSE.md rollout (2026-07-03). Authoritative history: `hub/CHANGELOG.md` (hub),
> `website/CHANGELOG.md`, `scripts/CHANGELOG.md`; end-of-task detail in `REPORT.md`.
- **2026-07-13 — CLOSING BUNDLE SHIPPED: hub v0.53.0** — the last engineering items on the
pre-tester board: F-14 gated auto-Reissue (deletion provenance `host_deletions` in-tx +
`token_exists` gate → the EXISTING Reissue op + `pbsdr_auto_reissue` audit event; no record /
un-acked → refusal byte-unchanged), dead-host roll-up honesty (customer status = worst of
controller-derived + per-host `hostStatus` on dashboard//configs/detail, cause chip names the
host; the Peti 23h-masking shape is the pinned fixture), operator bearer OUT OF GIT
(`Secret/report-api` secretKeyRef non-optional + `REPORT_API_KEY` env override +
`scripts/manifest_bearer_gate.py`; VALUE ROTATION = supervised step in
documentation/runbooks/secrets.md — the git-history copy is dead only after it).
**Two operator rulings (2026-07-13), recorded verbatim — future sessions must treat these as
settled:**
1. ***F-14:** auto-Reissue of offsite credentials is permitted ONLY when the hub's own deletion
record shows the tenancy's owning host was removed through the escrow-ack flow — acknowledged
destruction is not silent re-keying. No record → manual Re-issue stays the only path.*
2. ***Roll-up:** a customer's status may never look better than its worst expected host. Single
staleness definition (`hostStatusOf`) — no second threshold anywhere.*
Gate additions: `python scripts/manifest_bearer_gate.py` after ANY manifests/ change (64-hex
bearer shapes; felhom.secret.yaml carve-out = visible KNOWN-BACKLOG line). GOTCHA: the repo
.gitignore `*secret*` pattern silently un-tracks any "secret"-named script — hence the
"bearer" name. The controller repo's controller.yaml.example carried the REAL bearer literal —
scrubbed (felhom-controller 51c871a).
- **2026-07-13 — POLISH BATCH SHIPPED: hub v0.52.0 (+ controller v0.123.0)** — take-two F-15
CLOSED (reset-request response carries the rotated code hash — ACK shape/guarantee — emailed
codes work immediately; live 1 s apply + first-try accept on Viktor's exact failure path) and
@@ -59,7 +59,7 @@ capability chip table (v0.51.0) live.
| # | Sev | Finding | Direction |
|---|---|---|---|
| **F-14** | MEDIUM | Host delete + re-enroll while the ep0 tenancy survives = DR re-attach dead-end: auto-provision AND config save hard-error `token_exists`; "Re-issue PBS credentials" 400s (requires the descriptor the deleted host took with it). Recovery today = manual ep0 root token-delete (done during this reset) | candidate: flag-ON + no-descriptor + token-exists ⇒ auto-Reissue (re-adopt; the old secret is unrecoverable anyway) — needs an operator ruling vs the never-silently-re-key law |
| **F-14** | MEDIUM | Host delete + re-enroll while the ep0 tenancy survives = DR re-attach dead-end: auto-provision AND config save hard-error `token_exists`; "Re-issue PBS credentials" 400s (requires the descriptor the deleted host took with it). Recovery today = manual ep0 root token-delete (done during this reset) | **SHIPPED 2026-07-13** (hub v0.53.0, operator ruling): auto-Reissue permitted ONLY when the hub's own deletion record (`host_deletions`, written in the DeleteHost tx) shows the owning host was removed through the escrow-ack flow — acknowledged destruction, not silent re-keying; no record (incl. THIS drill's pre-record reset) / un-acked → the refusal + manual path, byte-unchanged. Scenario A/B tests + red-proofs; live validation = the next real host-reset cycle (fixtures carry it until then) |
| **F-15** | MEDIUM/UX — **operator-flagged must-fix** | Claim/reset code NOT immediately usable: the hub rotates the hash at reset-request, but the box learns it only on its next report ACK (~15 min). Viktor hit it live ("Hibás vagy lejárt kód" with a fresh code) | **SHIPPED 2026-07-13** (hub v0.52.0 + controller v0.123.0): the reset-request response carries the rotated hash, applied via the ACK's generation-guarded consumer. Live re-run of the exact failure path: applied 1 s after the request, code accepted first try |
| **F-16** | LOW | Native `confirm()` on hub buttons (offsite/PBS re-issue, freeze) froze CC's browser automation — the hub-side siblings of drill F-11 | **SHIPPED 2026-07-13** (hub v0.52.0 + controller v0.123.0): inline "Igen/Mégse" two-step everywhere, both repos; `hub_confirm_gate.py`/`native_confirm_gate.py` enforce zero native confirms. Live: the offsite re-issue completed under automation without freezing |
| obs. | — | A re-provisioned guest over an EXISTING offsite repo needs the old repo password (gone with the deleted escrow) or a repo wipe — this IS the S5 DR-restore scenario, already queued as its own drill; the wipe was the correct reset action here, not a product gap | S5 drill |
+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.