From 1613bc71200bcbb9d1dbae08031c3a9d840203d1 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Wed, 22 Jul 2026 09:26:14 +0200 Subject: [PATCH] =?UTF-8?q?docs(report):=20hub=20v0.70.1=20shipped=20?= =?UTF-8?q?=E2=80=94=20ghost=20Delete=20reachable;=20operator=20live=20leg?= =?UTF-8?q?=20pending?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- REPORT.md | 109 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/REPORT.md b/REPORT.md index 09b44f9..1742c81 100644 --- a/REPORT.md +++ b/REPORT.md @@ -1,49 +1,80 @@ -# REPORT — Agent-only publish train 0.93.0 executed (operational run, docs-only in this repo) +# REPORT — hub v0.70.1: the ghost customer's Delete button must exist -**Date:** 2026-07-22 · **Repo:** `felhom.eu` (runbook record + §A5 discharge; no code, no version -bump, no hub deploy) · **Full record:** `documentation/pilot/RUNBOOK-publish-agent-0.93-2026-07-22.md` +**Date:** 2026-07-22 · **Repo:** `felhom.eu` (hub only) · **XS render-gate fix, DEPLOYED** · +**STOP honoured: the ghost delete itself is NOT run — awaiting the operator's click.** -## What happened +## The defect (fourth inert seam — a template gate this time) -felhom-agent **v0.93.0** (hyphen-free escrow wordlist, source-only since 2026-07-21 at `a452dc33`) -was **built, published, manifest-vouched and deployed to both fleet boxes** by CC, with one -password-gated STOP → Viktor (the Day-0 manifest save, verified by CC in the hub DB **before** any -box moved — publish-train rule 1). +v0.70.0's ghost-delete was fully implemented server-side (`handleCustomerDelete`/`Preview` accept +`cfg == nil`) and fully unreachable: the Danger-zone card — and the `customerDeleteOpen/Submit` +script — sat inside the `{{if .HasConfig}}` block that also wraps the RESET card +(`customer_unified.html` old ~L736–L945). A ghost rendered no Danger zone at all. Handler tests +POST directly and proved nothing about reachability. Confirmed live on `demo-vm-felhom` pre-fix. -- **Artifact:** sha256 `a68b2ff73200622ea9e23aed71a0a8ff885808626cab9e9d554a5a5df5ced28f` - (13 817 690 bytes), sha-chain identical: built binary → Gitea package (PUT 201) → independent - anonymous GET. -- **Manifest:** agent 0.92.1→**0.93.0** + new sha. Golden (0.153.0), floor (**0.156.0**) and - wrapper sha **byte-identical before/after**. **Deviation, ruled:** MinAgent moved 0.92.1→0.93.0 - at the operator save (spec said do-not-touch); flagged before deploy, Viktor ruled leave it — - the held-floor window was transient (minutes) and harmless. -- **Deploys** (felhom-pve first, then demo-hp over G1 break-glass — secret file→file, shredded): - both boxes clean-restart **5/5** — active/NRestarts=0, capabilities **68/68 degraded=0**, - ReassertGuestBinds touched only enrolled drives, guestnet sweeps quiet (0 ERROR/WARN), hub - `hosts.agent_version` = **0.93.0** for both (06:56:52Z / 06:57:52Z). `.bak-0.92.1` retained on - both; escape hatch not needed. -- **Green gate** on the exact HEAD: build/vet/test green; the ex-flaky escrow package **10/10** - fresh runs (`-count=10`) — that flake was this defect, so the clean run is itself evidence. +## The change -## Changes in this repo +- **`configs.go` `handleCustomerUnified`**: new `Deletable` flag = the **exact negation** of the + preview's 404 predicate (`cfg == nil && no hosts && residue empty`). Hosts were already fetched + for the Host tab, so only the residue count is a new read — and it runs solely on the ghost + shape. Lookup error → log + `Deletable=false` (fail toward hiding a destructive control). +- **Template**: gate split — RESET card + its JS stay `{{if .HasConfig}}`; Danger zone + delete + dialog + delete JS gate on `{{if .Deletable}}`; Block/Unblock forms get an inner + `{{if .HasConfig}}`; ghost shape gets a one-sentence intro prefix (the dialog explains the rest). -1. **`documentation/pilot/RUNBOOK-publish-agent-0.93-2026-07-22.md`** — the executed record - (timestamps, hashes, per-box evidence, the MinAgent deviation + ruling, observations). -2. **`documentation/runbooks/RUNBOOK-onboarding-draft-v4.md`** §A item 5 — the "agent ≥ 0.93.0 - box-side before the first real escrow ceremony" gate marked **DISCHARGED 2026-07-22**, citing - the runbook record. (The spec pointed at a ROADMAP "wordlist row" — **none exists**; the gate's - real home is §A5, so the annotation went there. Recorded as a deviation, not improvised into a - new ROADMAP row.) +## Tests (`customer_ghost_delete_render_test.go`) + red-proofs -## Fleet after this train +Render tests against the real template set, real store on `t.TempDir()`, asserting the delete +form's `action` attribute and the `customerDeleteOpen(` call site (not free-text): -Both boxes agent **0.93.0**; Day-0 manifest agent 0.93.0 / MinAgent 0.93.0 / golden 0.153.0 / -floor 0.156.0. `peti-felhom` untouched by design — Friday's reinstall pulls the vouched manifest -and lands on 0.93.0. +- **A — ghost with residue** (reports only, no config, 0 hosts): delete form + opener + script + present; RESET form ABSENT; Block/Unblock ABSENT. **PASS** +- **B — configured customer**: every affordance of today present (RESET, Block, delete machinery); + plus the blocked→Unblock branch (fixture note: `SaveCustomerConfig` never writes status — + blocking goes through `SetCustomerConfigStatus`, same as the /block handler). **PASS** +- **C — nothing left**: page-level **404**, mirroring the preview's semantics. There is **no + renderable `Deletable=false` state** with real store reads — `customer != nil` requires a report + row (`GetCustomer` selects from `reports`), and a report row makes `residue.Total() ≥ 1`. The + only false-branch shape short of that is a residue-lookup error (fail-safe, compile-trivial). -## Observations (not acted on) +**Red-proof 1 (RUN):** Danger-zone gate reverted to `{{if .HasConfig}}` → test A **FAILED** on all +three delete-affordance assertions ("ghost page must render the delete form … dead UI"). Restored → +green. +**Red-proof 2 (RUN):** RESET card gated on `Deletable` (the lookalike) → the RESET-absent assertion +**FAILED** ("RESET card must NOT render for a ghost (found action=/configs/ghost/reset)"). +Restored → green. `git diff` clean of scaffolding (0 REDPROOF markers). -- demo-hp's 1TB NVMe is now **enrolled** (`/mnt/nvme-1tb`, reasserted into 9201) — TASK-H's - "unenrolled/NTFS" note is outdated; `operations/nodes.md` may want a refresh. -- demo-hp still key-less (break-glass worked cleanly); tailnet key-expiry toggle still open. -- Host journals are CEST; all runbook evidence stamps note the offset. +Green gate: `go build ./... && go vet ./... && go test ./...` — **green** (web suite 12.0 s). + +## Ship (GitOps) + +| Step | Evidence | +|---|---| +| Feature commit | `f4c2c41` (code + template + tests + CHANGELOG + ROADMAP + CONTEXT + CLAUDE.md) | +| Image | `felhom-hub:0.70.1` built + pushed, ID `f1741b46bfbb` | +| Manifest bump | **separate chore commit** `068bce6` (operator preference honoured) | +| Sync | ArgoCD hard-refresh + patch-sync → **Synced/Healthy**, rollout complete | +| Live verify | pod image `felhom-hub:0.70.1`, imageID digest `sha256:f1741b46bfbb…` (= the built image), clean startup log, `/login` 200. Footer is on password-gated pages — the visual check lands on the operator's next login (endpoint-level method stated per convention) | + +## AWAITING OPERATOR — the live leg is yours + +Open `demo-vm-felhom` → Edit tab (Danger zone now renders with the ghost prefix) → **Delete +customer…** → three acks + typed id → confirm. Expected: customer gone from the Customers list, +journal legs `residue=ok customer_delete=ok` with `skipped_no_config` on the Hetzner/descriptor +legs, staleness emails stop. That click doubles as the v0.70.0 + v0.70.1 live validation; the +ROADMAP R-25b row flips its "PENDING" note once done. + +## Docs also in this train + +- `hub/CHANGELOG.md` v0.70.1 (inert-seam framing, template/handler lines cited). +- `CLAUDE.md`: **the seam-wiring rule now covers template gates** — any conditional UI affordance + ships with a render test per branch. +- ROADMAP: R-25b annotated (v0.70.1 render fix, operator live leg PENDING); **R-17 → CLOSED** + (operator console action: `u629193-sub1` deleted, no sub-accounts remain on PBS-storage-1, + 2026-07-22). + +## Observations (recorded, not acted on) + +- Pre-existing page-reachability quirk: a customer with host rows but neither config nor reports + 404s on the unified page (configs.go `cfg == nil && customer == nil`) while the delete preview + would 200. No such state exists in practice (hosts imply enrollment implies reports); noted only. +- The Create Config button for ghosts is untouched (re-adopting a ghost stays a legitimate path).