docs(report): hub v0.70.1 shipped — ghost Delete reachable; operator live leg pending
This commit is contained in:
@@ -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).
|
||||
|
||||
Reference in New Issue
Block a user