feat(hub): v0.70.0 — a deleted customer actually disappears (residue leg + ghost cleanup)

Found validating v0.69.0 against the live hub. demo-vm-felhom was deleted
on 07-18 and was still on the Customers list AND still raising offsite_stale
(10 events, latest 07-21 17:34, operator email at 19:34) — because
GetCustomers() is report-derived and no lifecycle tier ever deleted a report.

New leg 3 (residue), before the record purge: reports, app_telemetry,
app_log_tails, log_tail_requests, customer_notifications, plus the
credential-bearing appliance_registrations and selfbind_tokens. Audit
(events, notification_log) and F-14 provenance still survive.

Ghost customers are now deletable: 404 means "nothing here", not "no config
row". With no config row the offsite descriptor is unknowable, so the Hetzner
and descriptor legs record skipped_no_config rather than a bare "skipped".

Two more red-proofs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J55BQE1gE2V4ffud5jweGS
This commit is contained in:
2026-07-21 20:28:06 +02:00
parent a1d503be98
commit 9b3381be0a
13 changed files with 521 additions and 45 deletions
@@ -195,3 +195,9 @@ Notes for the operator:
the error names the leg, and re-opening the dialog offers **Resume**. Completed legs are no-ops.
- The **audit event stream survives** the delete — the customer_deleted event and the host-deletion
provenance outlive the record, by design.
- **A deleted customer disappears from the Customers list immediately** (hub v0.70.0). If one lingers
with a `MANUAL` config badge, it is a **ghost** left by a pre-v0.70.0 delete: the record is gone but
its report stream survives, which both keeps it on the list and keeps the staleness/offsite checkers
emailing you about it. Open **Delete customer…** on it and confirm — the dialog labels it as a ghost
and the cascade clears the residue. (With no config row the Hetzner leg cannot be determined and is
recorded as `skipped_no_config` — verify the Hetzner side by hand for that customer.)