# Teardown ledger — `walk5`, the fifth walk's venue (2026-08-08) **Done.** Supersedes `teardown-owed.md` in the same directory, which was the pre-agreed enumeration. Operator-confirmed before anything was deleted. Predecessor: `teardown-finalwalk-2026-08-07.md`. **Matched on IDENTITY, never on size** — customer id → host id → sub-account → PBS namespace → wg peer. --- ## The cascade VM 325 was **stopped at 16:31:30Z** under a `qm config` name guard (`demo-hp` also carries its own guest 9201) and aged past the hub's `stale_threshold` — **`30m`, read from the deployed `hub-config` ConfigMap, not assumed**. `GET /hosts/walk5-4bada5/delete-impact` was polled until it answered `deletable:true` (**16:51:56Z**, `status: stale`), **treating an empty response as a retry and never as success**. `POST /configs/walk5/delete` with all six gates (`ack_hosts`, `ack_reset`, `ack_purge`, `confirm_id=walk5` typed, `expect_hosts=1`) → **303 `/configs?flash=deleted`**. **The hub's leg-by-leg log is the evidence, not the flash:** ``` 18:52:12 customer DELETE cascade started for walk5 (journal #15, 1 host(s)) 18:52:12 delete walk5: host walk5-4bada5 deleted (escrow DEMOTED to retained custody) 18:52:19 [offsite] deprovisioned shared sub-account 285351 for walk5 (repo data destroyed) 18:52:20 tenantsync: deprovision ok for walk5 (ns=walk5, existed=true) 18:52:20 [claim] reset to unclaimed for walk5 (customer RESET) 18:52:20 delete walk5: residue purged (reports=30 app_telemetry=48 app_log_tails=0 log_tail_requests=0 notif_prefs=1 selfbind_tokens=1 appliance_registrations=1) 18:52:20 customer DELETE cascade COMPLETE for walk5 (journal #15) — full teardown ``` `existed=true` on the PBS leg is the positive observable that it deleted something rather than no-op'ing on an absent namespace. Then, guarded a second time on `qm config 325` reading `name: walk5-appliance`: **`qm destroy 325 --purge` at 16:52:41Z**. --- ## After — every layer, each with a positive control that must survive, and does | Layer | Item | After | Positive control | |---|---|---|---| | machine | VM 325 + 4 disks | **absent**; `/mnt/nvme-1tb/images/` **empty** | VM **300 `drill-r50`** still listed | | host | — | — | `demo-hp`'s **own guest 9201 still running** | | hub | `hosts`, `customer_configs`, `host_escrow`, `wg_peers`, `guests`, `reports`, … | **0 rows** | `demo-felhom` hosts=1 · `demo-hp` hosts=1 · `peti-felhom` config=1 | | off-site | Storage Box sub-account **285351** (`u629488-sub4`) | **deprovisioned, repo data destroyed** (hub log) | — *(see the access note below)* | | off-site | `ep0` PBS namespace `walk5` | **gone** | namespaces `demo-felhom`, `demo-hp` both present | | network | WireGuard peer **10.77.0.5** | **gone from the LIVE `wg show`** | peers `.2 .3 .4 .250` all still on `wg0` | **Space returned, measured.** `c11-scratch` used **23 715 036 → 6 262 060 KiB = 17 452 976 KiB (16.64 GiB)** against the 17 G measured on disk before deletion. Available 909 638 052 → 927 091 028. ### ⚠ The WG peer is removed on a SCHEDULE, not by the cascade — check the live interface, not the DB Immediately after the cascade the hub's `wg_peers` row was gone **while `10.77.0.5` was still on `ep0`'s live `wg0`**. That is **not** residue: `wgsync` pushes every ~5 minutes and had last run at **16:51:35Z, 37 seconds before the cascade**. The next push — `18:56:35 wgsync: pushed 4 peers` — removed it, **verified on the live interface at 16:57:07Z**. **Recorded because the previous ledger checked this layer after it had already converged and so read as instantaneous.** A teardown that checks `wg show` inside ~5 minutes of the cascade will see a peer that is on its way out, and filing that as a finding would be wrong. **The DB row is not the evidence; the live interface is — and it needs a moment.** --- ## Residue — counted, not claimed away (R-244) **Full-schema census** (every table, every column, `like '%walk5%'`, no truncation): **168 rows before → 67 rows after.** 101 removed. | table | rows | verdict | |---|---|---| | `events` | 21 | **by design** — *"provenance/events are NEVER wiped; audit outlives every tier"* | | `notification_log` | 14 | **by design** | | `host_deletions` | 1 | **by design** — the deletion tombstone | | `customer_resets` | 1 | **by design** — the journal row (#15) | | **`app_log_issues`** | **30** | **THE GAP — R-244, exactly as predicted before the run** | **R-244 grew by 30 rows, as this ledger's own pre-run enumeration said it would.** The prediction is the point: the previous ledger's *"0 occurrences"* came from a narrower query and did not survive a full census. **Nothing here claims a clean teardown.** --- ## Access note, per the standing rule that a "no access" claim must name its attempts The Storage Box sub-account could **not** be verified directly from DooPlex. Tried, with `HETZNER_API` from `~/.config/credentials`: `GET /v1/storage_boxes/611421/subaccounts` → **404 `not_found`**; `GET /v1/storage_boxes` → **200 with `total_entries: 0`**. **That token is scoped to a different project than box 611421** — the hub holds its own. The layer is therefore evidenced by the hub's own `[offsite] deprovisioned shared sub-account 285351 … (repo data destroyed)`, matched on the id recorded at provisioning. **Recorded so the next teardown does not re-derive it.** --- ## Not deleted, deliberately The **escrow was DEMOTED to retained custody**, not destroyed (the cascade's own wording). That is R-198's retention behaving as designed. The customer record itself is gone; what survives is the sealed material under the operator's retained-custody path, plus the audit rows above. ## One thing that died with the box During v0.207.0's live validation a **test retrieval passphrase was planted** on this appliance, and its settings were mutated (app removed, a drive deregistered, `storage_paths` emptied). All of it was on the machine destroyed above. **The `walk5` retrieval passphrase was also compromised earlier** — it reached a session transcript, which is R-249 — and it is now gone with the customer record.