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:
+22
@@ -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
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user