docs: hub v0.52.0 polish batch — CHANGELOG + REPORT + CONTEXT + REUSE (inline_confirm partial); take-two §4 dispositions: F-15/F-16/zero-toggle SHIPPED
Claude-Session: https://claude.ai/code/session_01GzammAMzsJTgpQHqxwM2bC
This commit is contained in:
+10
@@ -3,6 +3,16 @@
|
||||
> 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 — 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
|
||||
F-16 CLOSED (zero native `confirm()` in the hub UI — `inline_confirm.html` partial, Igen/Mégse
|
||||
inline two-step, `scripts/hub_confirm_gate.py` enforces; danger-zone typed-confirm untouched;
|
||||
live: offsite re-issue completed under browser automation without freezing). Operator resend
|
||||
keeps the ACK lag — flash says so. Take-two §4 dispositions updated (F-15/F-16/zero-toggle obs
|
||||
→ SHIPPED). Remaining from take-two: **F-14** (needs operator ruling: auto-Reissue re-adopt vs
|
||||
never-silently-re-key) + S5 DR-restore drill; hub bearer key rotation still DUE.
|
||||
|
||||
- **2026-07-12 — DR-TIER-BY-DEFAULT BATCH SHIPPED: installer v1.15.0 + hub v0.51.0 (+ agent
|
||||
v0.86.0 in felhom-agent)** — closes DRILL-day0-vm F-1/F-2/F-3/F-7/F-8/F-9/F-10 and F-6 (by
|
||||
policy). **The five operator decisions (2026-07-12), recorded verbatim — future sessions must
|
||||
|
||||
@@ -2,54 +2,47 @@
|
||||
|
||||
> **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md).
|
||||
|
||||
## DR-tier-by-default batch — installer v1.15.0 + hub v0.51.0 (+ agent v0.86.0) — 2026-07-12
|
||||
## Polish batch — hub v0.52.0 (F-15 instant reset codes + F-16 inline confirms) — 2026-07-13
|
||||
|
||||
**Spec:** the DR-tier-by-default batch (uniform deployment, hub-controlled activation). Closes
|
||||
drill findings F-1/F-2/F-3/F-7/F-8/F-9/F-10 shipped + **F-6 closed by policy** (decision 4:
|
||||
identity-only escrow PARKED). Baselines re-confirmed at start: password arc fully deployed (hub
|
||||
0.50.0 live, ctrl 0.122.0 + floor raised, drill box claimed); hub target shifted 0.50.0→**0.51.0**
|
||||
(the arc took the spec's number — the 0.48→0.49 precedent).
|
||||
Hub half of the polish batch (take-two findings F-15/F-16); companion controller v0.123.0.
|
||||
Commits `bad9203` (F-15), `5d66c62` (F-16), `0e05c69` (manifest 0.52.0).
|
||||
|
||||
### Shipped (this repo)
|
||||
### What shipped
|
||||
|
||||
- **`scripts/felhom-host-install.sh` v1.15.0** — F-7 ships `felhom-pbs-apply` (wrapper pattern,
|
||||
uninstall parity); F-10 installs `age`; F-9/decision-5 renders `wg_tunnel.enabled: true` BOTH
|
||||
modes (byo wg-off assert retired; consent = typed disclosure ack, WG now on the disclosed
|
||||
list); default ACL keeps `felhom-pbs` (byo missing-storage refusal exempts it — pre-positioned
|
||||
grant); F-1 single `SCRIPT_VERSION` source; F-2 honest dry-run auth lines; F-8 loud root@pam
|
||||
rotation pointer (4b + final summary). `bash -n` clean; mode-harness 31/31 green.
|
||||
- **`scripts/hostinstall_gates.py`** (NEW committed gate) — version single-source + hub-const
|
||||
cross-check, age, pbs-apply ship+remove, wg default-on + assert retirement, felhom-pbs in ACL.
|
||||
All red-proofed; the age assertion hardened TWICE by its own red-proof (prefix regex matched
|
||||
`agekit`; loose regex matched the dry-run print).
|
||||
- **Hub v0.51.0** — per-customer `dr_tier` flag (column + one-time backfill from descriptor
|
||||
reality; new-customer default ON); cascade-not-error semantics + per-stage status (scenario D);
|
||||
`PBSDRAutoProvision` fired by the WG-registration hook (scenario A hands-free); offsite-
|
||||
requires-DR guard with the exact F-6 message (scenario C); host-page capability chips
|
||||
(`inactive` = neutral, degraded stays loud + migration hint); Setup-tab copy 1.15.0.
|
||||
Green gate: build/vet/test — 14 packages ok. Red-proofs: coupling guard, flag default,
|
||||
backfill enabled-check, auto-provision unhook — all proven red then restored.
|
||||
- **Docs:** day0-install.md (ACL narrowing advice REVERSED — the drill 403; DR-default note;
|
||||
commands drop `--acl-storages`; byo wg disclosure), RUNBOOK-escrow-ceremony.md (decision-4
|
||||
policy block), PETI-tester-agreement.md + GO-LIVE-PACKAGE.md D3 (WG disclosure/supersede),
|
||||
CONTEXT.md (decisions 1–5 verbatim), DRILL-day0-vm §7 F-disposition table, REUSE.md rows
|
||||
(+ path-citation fixes; reuse_refs_check green).
|
||||
1. **F-15** (`internal/api/handler.go`): `POST /api/v1/claim/reset-request` returns the ACTIVE
|
||||
claim state — `{claim: {code_hash, generation, issued_at}}`, the report ACK's exact shape and
|
||||
bcrypt-only guarantee — so the box applies the rotated hash in the SAME request cycle and the
|
||||
emailed code works immediately (was: next-ACK, ~15 min — Viktor's take-two live failure).
|
||||
Served on every authorized outcome; a cap-reached refusal returns the unrotated row (a
|
||||
controller-side no-op by generation). The operator "Kód újraküldése" keeps its ACK lag —
|
||||
its flash + confirm copy now state it; the unmapped `claim-resent`/`claim-resend-failed`
|
||||
flash codes finally render.
|
||||
2. **F-16** (`templates/inline_confirm.html` + 4 templates + `scripts/hub_confirm_gate.py`):
|
||||
every native `confirm()` in the hub UI replaced by the inline "question + Igen/Mégse"
|
||||
two-step (`felhomConfirm` / `data-confirm` + `requestSubmit`, so `formaction` buttons riding
|
||||
the parent form still work). Danger-zone typed-confirm untouched by design. Gate enforces
|
||||
zero native confirm/prompt.
|
||||
|
||||
### Sibling repo (felhom-agent v0.86.0, commit `c20814e`)
|
||||
### Tests + red-proofs
|
||||
|
||||
Capability `inactive` state ("disabled by configuration"; broken plumbing stays degraded) gated
|
||||
by `pbsdr.Manager.DRConfigured` (marker-backed); F-3 root-run provision parent chown
|
||||
(`--reference`, non-recursive). felhom-pve's latent F-3 state confirmed + fixed live; Peti's box
|
||||
unreachable (check deferred).
|
||||
- `TestClaimResetRequest_ResponseCarriesRotatedHash` (rotated hash == stored row, != pre-rotation
|
||||
row, bcrypt-only). **Red-proof:** handler mutated to serve the pre-rotation row → FAIL
|
||||
"response generation = 1, want the rotated one (stored 2)". Restored → green.
|
||||
- `hub_confirm_gate.py` **red-proof:** one `onclick="return confirm('redproof')"` reintroduced →
|
||||
exit 1; restored → 0. Full hub green gate (build+vet+test) before each commit.
|
||||
|
||||
### Deployed + LIVE-VALIDATED (same evening)
|
||||
### Deployed + live-validated
|
||||
|
||||
All three artifacts deployed: hub 0.51.0 (ArgoCD Synced/Healthy, auto-provision hook armed),
|
||||
agent 0.86.0 (felhom-pve `ok=62 degraded=0`, published `d77355c5…`, Day-0 manifest vouched),
|
||||
installer v1.15.0 served. **§13 take-two re-drill EXECUTED with Viktor (GO given): the entire
|
||||
drill §5 sequence completed with ZERO fix-and-continue stops in 1h 22m (vs 1h 55m)** — all
|
||||
F-fixes proven on a fresh box, scenario A hands-free cascade fired 1 s after WG registration,
|
||||
auto-confirm 6m 39s, floor-driven self-update 0.120→0.122 FIRST LIVE PROOF, offsite round-trip
|
||||
proven (1 snapshot → 48K verification restore). Full record + metrics + new findings
|
||||
(F-14 tenancy re-attach dead-end, F-15 reset-code lag — operator must-fix, F-16 hub native
|
||||
confirm()): `documentation/audits/DRILL-day0-take2-2026-07-12.md`.
|
||||
- ArgoCD app `felhom` **Synced/Healthy**, deploy/hub image `felhom-hub:0.52.0`, clean startup log.
|
||||
- **F-15 live:** drill-box reset request → controller cached the response hash **1 s** after the
|
||||
POST; Viktor re-ran his exact take-two failure path — emailed code **accepted immediately**.
|
||||
- **F-16 live (its own regression test):** "Re-issue offsite credentials" on demo-vm-felhom
|
||||
driven fully by browser automation — inline strip rendered, Igen → `?flash=offsite_reissued`,
|
||||
**zero CDP freezing** (with v0.51.0 this exact click froze the session).
|
||||
|
||||
### Observations
|
||||
|
||||
- Take-two §4 dispositions updated: F-15 and F-16 SHIPPED (this batch); the zero-toggle obs.
|
||||
shipped controller-side (v0.123.0).
|
||||
- Remaining from take-two: **F-14** (tenancy re-attach dead-end — needs the operator ruling on
|
||||
auto-Reissue vs never-silently-re-key) and the S5 DR-restore drill.
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
| Symbol | File | Short signature | Use for | Gotchas |
|
||||
|---|---|---|---|---|
|
||||
| funcMap in `web.New` | hub/internal/web/server.go (~L67) | `template.FuncMap{...}` | ALL template helpers (`timeAgo`, `statusColor`, `json`, `hubVersion`…) | Add new template funcs HERE, nowhere else. Tested by hub/internal/web/funcmap_test.go + render_test.go. |
|
||||
| `inline_confirm_js` partial (v0.52.0) | hub/internal/web/templates/inline_confirm.html | `{{template "inline_confirm_js"}}` in the page `<head>` | Inline "question + Igen/Mégse" confirm for consequential buttons — `data-confirm="…"` on the button, or `felhomConfirm(el, q, onYes)` from JS | NEVER native `confirm()`/`prompt()` — OS-modals freeze browser automation (F-16); `scripts/hub_confirm_gate.py` enforces zero. Uses `requestSubmit` so `formaction` sub-buttons riding a parent form work. NOT for the danger-zone typed-confirm cascade. |
|
||||
| `timeAgo` | hub/internal/web/server.go (~L603) | `(t time.Time) string` | Human-relative timestamps in UI | — |
|
||||
| `statusColor` | hub/internal/web/server.go (~L630) | `(status string) string` | Status → design-system-v2 token (nominal/warn/crit/neutral) | Class SUFFIX only, never inline color (D4). Exception-color principle: healthy = blue/neutral. |
|
||||
| `(*Server).hostStatus` + `hostStatusClass`/`hostStatusLabel` | hub/internal/web/hosts.go (~L16/34/48) | `(lastReport *time.Time) string` | Host liveness badge | Uses the SAME threshold as HostStalenessChecker (down = 2× stale) — never invent a second definition. |
|
||||
|
||||
@@ -60,10 +60,10 @@ 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-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) | the box's reset-request POST already round-trips to the hub — return the new code hash in the RESPONSE so the box accepts the code immediately |
|
||||
| **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 | convert to the inline-confirm pattern together with F-11 |
|
||||
| **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 |
|
||||
| obs. | — | The controller's very first offbox run with zero toggled apps reports "backup OK, 0 snapshots" — arguably should hint "no apps toggled" in the UI | cosmetic |
|
||||
| obs. | — | The controller's very first offbox run with zero toggled apps reports "backup OK, 0 snapshots" — arguably should hint "no apps toggled" in the UI | **SHIPPED 2026-07-13** (controller v0.123.0): toggle-list hint + "Sikeres — nincs mentésre jelölt alkalmazás" run copy, live-proven |
|
||||
|
||||
## 5. Disposition
|
||||
|
||||
|
||||
@@ -1,5 +1,28 @@
|
||||
# Felhom Hub — Changelog
|
||||
|
||||
## v0.52.0 — polish batch: F-15 instant reset codes + F-16 inline confirms (2026-07-13)
|
||||
|
||||
Hub half of the polish batch (take-two findings F-15/F-16). Companion: controller v0.123.0.
|
||||
|
||||
- **F-15 instant reset codes**: `POST /api/v1/claim/reset-request` now returns the ACTIVE code
|
||||
state in the response — `{claim: {code_hash, generation, issued_at}}`, the exact shape and
|
||||
bcrypt-only guarantee of the report ACK — so the box applies the rotated hash in the same
|
||||
request cycle and the emailed code works immediately (previously the box learned it only on
|
||||
its next report ACK, ~15 min — Viktor's take-two live failure). Served on every authorized
|
||||
outcome (a cap-reached refusal returns the unrotated row = controller-side no-op by
|
||||
generation). Never a plaintext code. Live-proven: apply 1 s after the request; code accepted
|
||||
on first try. The operator "Kód újraküldése" (no box round-trip) still has the ACK lag — its
|
||||
flash + data-confirm copy now say so ("A kód a doboz következő jelentésekor (~15 percen belül)
|
||||
aktiválódik."); the previously unmapped `claim-resent`/`claim-resend-failed` flashes render.
|
||||
- **F-16 inline confirms**: every native `confirm()` in the hub UI (offsite re-issue, freeze/
|
||||
unfreeze, PBS re-issue, telemetry reset, dismiss-all-issues, regen-password, claim-resend,
|
||||
block/delete, geo-disable) replaced by the LIGHT inline two-step — the shared
|
||||
`inline_confirm.html` partial (`felhomConfirm` + `data-confirm` delegation, `requestSubmit` so
|
||||
formaction survives). Native confirms are OS-modals that froze CDP browser automation (F-16;
|
||||
the drill F-11 siblings). NOT the danger-zone typed-confirm — that heavyweight cascade flow is
|
||||
untouched. New gate `scripts/hub_confirm_gate.py` (zero native confirm/prompt; red-proven).
|
||||
Live-proven: the offsite re-issue completed under automation without freezing.
|
||||
|
||||
## v0.51.0 — DR-tier-by-default: per-customer flag + hands-free cascade + offsite coupling + capability chips (2026-07-12)
|
||||
|
||||
Hub half of the DR-tier-by-default batch (DRILL-day0-vm-2026-07-12; operator decisions 1–5:
|
||||
|
||||
Reference in New Issue
Block a user