R-201 CLOSED — the unaided recovery journey passes, both halves, on the fifth walk
gates / gates (push) Successful in 17s

Capability map: the unaided-recovery row turns FAILED -> PROVEN-LIVE, scoped, with
what it still does not claim stated in the row itself: shape (c) did not fire
positively (with the mint guard holding there is no local key, so the offer comes
from shape (a)); and 'unaided' here means possible-without-a-shell, not obvious,
because two obstacles are unsignposted.

OPEN-ITEMS: R-201 closed with its evidence. Five new rows R-249..R-253 (the
retrieval passphrase in page HTML; the host-key scan ladder vs AAAA settle; the
listing's per-tag rows; the two unsignposted restore steps). R-243 annotated
rather than re-filed: on a REBUILD offsite_delivery_stuck does not skip, so the
row's gap is narrower than it reads.

STATUS.md: headline changed, and trimmed 97 -> 92 lines rather than extended, per
its own header.

Teardown recorded as OWED with its before-measurements, the stop-and-age gate, and
the positive controls that must survive.
This commit is contained in:
2026-08-07 17:24:27 +02:00
parent 0691bc59a5
commit 3f4fb3825f
5 changed files with 338 additions and 34 deletions
+221
View File
@@ -0,0 +1,221 @@
# REPORT — the fifth walk (R-201), 2026-08-07
**Runbook-style validation, supervised. One machine destroyed on purpose, with the operator's
confirmation at the §6 STOP. No product code written.** Venue: `demo-hp` VM **325 `walk5-appliance`**,
customer `walk5`, host `walk5-4bada5`. Full evidence: `documentation/tests/walk5-r201-2026-08-07/`.
---
## 1. THE VERDICT — both halves, separately
### THE DATA: **PASS**
All three sentinels came back **byte-identical** out of snapshot `5b0f20f7`, under the key recovered
from the sealed package with R:
```
11eb7fb2d1891f62a685e3d9a9fda44e0a342d437d4aebaa15fcb4c0fd79d539 61 WALK5-SENTINEL-A.txt
6b504d1e83bf4c673334d0b9e701f3e5f07311d954fdc4463a6b0a55b261ae32 66 WALK5-őrszem-ékezetes-árvíztűrő.txt
0baaf402733e6a85f3d9ce8c4c3a57b05692f5f6733da6a23da76d2cd7635210 12582912 WALK5-SENTINEL-C-12MB.bin
name hex 57414c4b352d c591 72737a656d2d c3a9 6b657a657465732d c3a1 7276 c3ad 7a74 c5b1 72 c591 2e747874
```
Identical to Phase A in every byte **including the accented filename's name bytes**. Read back with
`os.listdir` on a **bytes** path, so no decode/encode round trip could launder a `U+FFFD` into looking
correct — the check that caught this three times before.
### THE JOURNEY: **PASS — the first time in five walks**
**No step needed a command line inside the guest.** Everything that *progressed* the journey was an
HTTP request a browser makes. The previous walk needed **three** guest command lines; this needed
**zero**. The reset-code hatch was used **once, in Phase A**, where §3 permits it.
**Named per §3 so the claim is not read wider than it is** — the guest command lines used were the
`w5watch.log` sampler, `docker logs`, the settings reads, the restic listing and the final sentinel
verification. **All instrumentation:** none changed state, none was needed to progress, and removing
them all would have changed nothing but my ability to describe what happened.
---
## 2. §5's OBSERVATION — the first live exercise of R-241's fix, and it stands on its own
**At 14:58:52Z, unaided, before anyone had logged in:**
```
[WARN] [offbox] NOT minting a repository password: the hub holds a sealed recovery package for this
box, and a fresh key would orphan the history that package protects (R-241). The transport is
configured; the tier stays down until the customer's recovery code places the escrowed key.
[INFO] [offbox] apply-offsite: transport configured …, tier HELD awaiting the escrowed key
```
| §5 asks | answer |
|---|---|
| does it declare a need, and when is it staged/collected? | **yes** — declared `needs_credential` 14:38:49Z and 14:53:49Z; hub staged **14:56:34Z**; collected + applied **14:58:52Z**. **Zero human actions**, on a box not yet claimed |
| **is any repository key written?** | **NO** — sampled every ~20 s from 14:24:52Z; `repo_password` absent at every sample. The directory holds `applied_marker`, `known_hosts`, `ssh_key` and nothing else |
| what state does it report instead? | `enabled=true`, `escrow_state=pending`, no key → the derived **`awaiting_recovery_key`** holding state |
| the two fingerprints, before login | hub's package seals `eabf427c7274…144f`; **the box holds NONE** |
**Positive control, because an absent line is not evidence:** the scheduler logged
`agent-channel-health` ×5, `stack-scan` ×2, `system-health`, `backup-cache` and
`offsite-credential-retry` in the same window. The absence of a mint is **explained**, not merely
observed.
> **HONEST SCOPE.** With the mint guard holding there is **no local key**, so the offer fires on
> **shape (a)**, not shape (c). Shape (c) was measured in **Phase A, in its negative half** — hub hash
> == local hash, correctly silent. **This walk proves the mint guard positively and the discriminator
> negatively.** A positive shape-(c) firing needs a box holding a *different* key, which v0.206.0 now
> prevents from arising by itself.
---
## 3. THE RTO
**71.7 s**, login (15:04:25.417Z) → open store (15:05:37.156Z). Of that, **12.44 s was the unseal
itself**; ~22 s was **my own harness retry** (I scraped the CSRF token from a `<meta>` tag the recovery
page does not carry, got a 403, re-read it from the form). **A customer clicking the button sees
≈50 s.** Both numbers are given because 71.7 s is what was measured.
---
## 4. DEAD ENDS, in the customer's terms
**By §3's definition — something needing a shell inside the guest — there were ZERO.** Two obstacles
were met, both cleared **from the dashboard**, and **neither is signposted**:
| # | what the customer sees | what got past it | known? |
|---|---|---|---|
| 1 | „nincs elérhető adatmeghajtó a visszaállításhoz" | Tárhely → Meghajtók → „Meglévő meghajtó csatolása" re-registers both surviving disks | **NEW — R-252** |
| 2 | „a(z) calibre-web nincs telepítve — előbb állítsd helyre az alkalmazást" — **on a page that says three lines above „Nincs telepítve — a visszaállítás előbb újratelepíti"** | redeploy from the catalogue (~90 s), then re-run the restore | **NEW — R-253** |
**So: the machinery works end to end and the data is provably safe. The unaided journey now succeeds,
and it succeeds through two obstacles a customer must guess their way past.**
---
## 5. WHAT EACH INSTALL LANDED ON — and delivery is part of the pass
| | vouched | first install | after the rebuild |
|---|---|---|---|
| agent | 0.127.0 | **0.127.0** | **0.127.0** |
| controller | golden 0.206.0 | **0.206.0** | **0.206.0** |
**No hand upgrade either time, and no downgrade on the reinstall.** This is the first walk of the five
where the box under test **is the box a customer receives** — R-239's delivery gap, the headline of both
previous walks, is closed for this run.
---
## 6. THE RECOVERY SCREEN, QUOTED
Appeared **without being sought**: `/` → 302 `/launcher` → 302 **`/recovery`**.
> „Ezt a gépet újratelepítették. **A korábbi, házon kívüli mentéseid megvannak** — a Felhom központi
> rendszere őriz hozzájuk egy lezárt csomagot, amelyet **2026-08-07T12:51:02Z** zártunk le. […]
> **A helyreállítási kódot senki nem tudja pótolni** — sem a Felhom, sem az ügyfélszolgálat, sem az
> üzemeltető. […] Ha megadod a kódot, **feloldjuk a mentéseid zárolását és megmutatjuk, mi van
> bennük**. **Ebben a lépésben semmit nem állítunk vissza és semmi nem változik.**"
The sealed-at timestamp **matches `host_escrow.created_at` exactly**. *(Copy wart, recorded not filed:
it is a raw ISO-8601 string on a Hungarian customer screen where every other date reads `2026-08-07 14:57`.)*
---
## 7. THE LISTING, against Phase A
| | Phase A | the screen |
|---|---|---|
| app | `calibre-web` | **`calibre-web`** ✅ |
| when | `5b0f20f7` @ 12:57:41Z | **2026-08-07 14:57** ✅ (CEST) |
| size | 12.784 MiB | **12.8 MB** ✅ |
A second row `felhom-offbox · 12.8 MB` also appears — the tier's marker tag rendered as an app, and the
total doubled. **R-251.**
---
## 8. §4.6's TWO PRE-DESTRUCTION CHECKS — both pass, neither previously exercised on a clean box
- **The recovery offer is NOT shown**: `/``/launcher`, **zero** recovery mentions on either landing
page, `/recovery` 302s. And the reason is measured, not assumed — box key, box's ACK-cached hub hash
and hub `restic_pw_sha256` are all `eabf427c7274…144f`, so **shape (c) compares equal and stays
silent**.
- **The restore page lists the app with the future-backup toggle OFF** — identical rendering both ways.
**R-237's fix, live**; the last walk measured 0 entries and a 302 here.
---
## 9. PHASE A's SEVEN RECORDS
Controller `0.206.0` · agent `0.127.0` · PBS wrapper **matches vouched** · guests 1/1 · DR recipe
**present** · key escrow **present** · snapshot `5b0f20f7` · 1 snapshot · **12.0 MB** (12 611 563 B) ·
`host_escrow` blob **383 B**, `identity_blob` **572 B**, `stale_at` **NULL**, 0 superseded rows ·
escrowed key fingerprint `a6:86:f7:fb:…:4c:f9` · box key == hub hash == `eabf427c7274…144f`.
**Sentinels listed BY NAME** out of the snapshot with `restic ls latest --long` — see §1.
> **The §4.5 gate earned its place again, and this time it caught MY fault.** The first off-site run
> reported **`ok` in 28 s with 0 snapshots**: I had sent the per-app toggle as `enabled=1`, and the
> handler accepts only `on`/`true`, so it recorded *off* and the run correctly backed up nothing.
> Re-toggled, selection verified in the rendered page, re-run → 1 snapshot, 12.0 MB. **A green tick is
> not evidence a file is in a snapshot.**
---
## 10. R — SHREDDED, with a working control
One `0600` file on **DooPlex only**, never rendered, never an argument, never a log line. Shape only:
**82 characters, 10 hyphen-separated tokens**.
```
plant → ~/.config/walk5/R_PLANTED_CONTROL.txt
sweep → 2 hits (the real file + the planted control) ← the control PROVES the sweep works
shred → both, then the pattern file itself
sweep → 0 hits
```
**Every sweep path was asserted to exist first** — a sweep pointed at a missing path returns zero for
the wrong reason. The appliance's copy was `shred -u`'d mid-walk and its absence verified.
---
## 11. NEW FINDINGS — the highest register ID moved **R-248 → R-253**
| ID | |
|---|---|
| **R-249** | **The retrieval passphrase ships in the customer page's HTML** (`data-secret`), so any headless read puts it in a transcript — with no reveal action and **no audit event**, where the break-glass credential emits one. Found by doing it. **MEDIUM** |
| **R-250** | **A customer create can fail fail-closed** because the host-key scan ladder (~60 s) is shorter than the fresh sub-account's DNS/**AAAA-before-A** settle (~100 s measured). Retry is safe and idempotent; nothing says so. **LOW-MEDIUM** |
| **R-251** | The recovery listing renders **one row per restic tag**, showing the customer an "app" they never installed and their data counted twice. **Cosmetic** |
| **R-252** | After a rebuild the restore refuses — **the drives lost their registration** — and nothing on the recovery path says to re-attach them |
| **R-253** | The restore refuses because the app is not installed, **on a page that says the restore reinstalls it**. Two shipped sentences that contradict each other, in the customer's language, at the last step of a recovery |
**Recorded against an existing row rather than minted:** **R-243** claims `offsite_delivery_stuck`
"skips the applied shape". **On a rebuild it does not skip** — 88 s after the destruction the hub
emitted the warning and wrote an **operator-channel** `notification_log` row naming a guest rebuild as
the cause, correctly. The gap is real for the state R-243 describes and **not** for the state a rebuild
produces; the row is annotated so it is not read wider than it measures.
---
## 12. TEARDOWN — OWED, not done
The machine is the evidence until the verdict is written. Full enumeration, the "before" measurements,
the stop-and-age gate, and the positive controls that must survive:
`documentation/tests/walk5-r201-2026-08-07/teardown-owed.md`. **R-244's residue will grow by this
venue.**
---
## 13. WHAT DID NOT RUN, AND WHY
- **A positive shape-(c) firing.** Structurally unreachable on a healthy v0.206.0 rebuild — see §2.
- **A soak / scheduled cycle.** The previous walk covered it; §7 does not ask for one and adding it
would have delayed the destruction past the operator's window.
- **Any product code.** §0 forbids it: five findings were filed and the walk continued.
- **Teardown.** §10 defers it deliberately.
- **`felhom-offbox`'s second listing row and the raw ISO date** were observed, not chased.
## Documents updated
`00-capability-map.md` (the unaided-recovery row → **PROVEN-LIVE, scoped**), `OPEN-ITEMS.md`
(**R-201 CLOSED**; R-249…R-253 filed; R-243 annotated), `STATUS.md` (headline changed; trimmed 97 → 92
lines rather than extended), and the journal + teardown ledger.
+36 -31
View File
@@ -1,16 +1,14 @@
# STATUS — what works, what's broken, what's next
**Updated 2026-08-08.**
**Updated 2026-08-07.**
> **A view, not a source.** `documentation/backlog/OPEN-ITEMS.md` is the authority; this page restates
> part of it in plain words, and **nothing may exist only here**. Not `CONTEXT.md`, which is technical
> state written for Claude Code. **Items, not paragraphs. One screen.** If it does not fit, something
> belongs in the register instead.
>
> *Rebuilt from the register on 2026-08-08. It had reached 258 lines; its "waiting on you" list asked
> for two things already shipped and carried a stray line reading only "Nothing."; and it mixed the
> DooPlex infrastructure work in with the product. The old "what shipped recently" log — 100 lines of
> it — is what the per-repo `CHANGELOG.md` files and the register are for, and is not restated here.*
> *Rebuilt from the register on 2026-08-07, from 258 lines. The old "what shipped recently" log is what
> the per-repo `CHANGELOG.md` files and the register are for, and is not restated here.*
## What works
@@ -19,21 +17,31 @@ sets their own password. They install apps from a catalogue of fifty-three, shar
network, and open apps from a launcher or a shared link. Backups run on their own to three places — the
machine's drive, a second drive, and an encrypted off-site copy.
**The backup promise is proved.** A machine has been destroyed on purpose and its files came back byte
for byte identical — three separate times, including a filename with Hungarian accents.
**The backup promise is proved, and so is getting the data back yourself.** A machine has been
destroyed on purpose and its files came back byte for byte identical — four times now, including a
filename with Hungarian accents. On **2026-08-07 the household's own journey passed for the first
time**: someone with a browser and their recovery code got everything back with **no command line
inside the machine at any point**. From logging in to seeing what is in the store took **72 seconds**.
*(R-201 — closed. Two rough edges remain, below.)*
## What's broken
- **A household still cannot get their own data back unaided.** Every individual link now works; no
single walk has completed end to end without someone stepping in. *(R-201)*
- **The recovery works, but two steps are unsignposted, and one of them the machine gets wrong.** After
a rebuild the restore stops with "no data drive available" and never says the drives must be
re-attached *(R-252)*; then it refuses because the app is not installed — on a page that says, three
lines above, that the restore will reinstall it *(R-253)*. Both are fixable from the dashboard in a
couple of minutes. Neither is something a household would work out on its own.
- **The passphrase that fetches a customer's whole configuration is sitting in the page's HTML**, behind
a Reveal button that only hides it visually. Anything that reads the page rather than looking at it
gets it, with no record that it was read. *(R-249)*
- **The machine's own screen keeps telling an already-paired box to pair itself** — 25 minutes after it
was paired, on a screen that promises it refreshes itself. *(R-214, R-235)*
- **A rebuilt machine cannot create a new recovery code at all.** *(R-221)*
- **A backup that covered nothing still calls itself „Sikeres".** The state is honest; the word is not.
*(R-240)*
- **A machine waiting for its recovery code raises no alarm to us.** It quietly stops making off-site
backups, and three separate safety nets each correctly decide it is not their business. The
household can see it; we cannot. *(R-243)*
- **A machine waiting for its recovery code can stop making off-site backups without alarming us.**
Measured on 7 August: after a *rebuild* we ARE told, promptly and correctly. The gap is narrower than
it read — it is a machine that reaches the state without a working tier behind it. *(R-243)*
- **The card offering to reopen set-aside backups promises more than we can deliver** — we keep the old
sealed package, but nothing can open it. *(R-202)*
- **Deleting a customer leaves rows behind** on every test machine ever torn down, while reporting a
@@ -42,31 +50,29 @@ for byte identical — three separate times, including a filename with Hungarian
## Found today
- **A leftover flag had been silently switching off the new recovery detection on one demo machine
since 4 August — found, and cleared with your approval.** A Re-issue during the recovery drill set it, using code we removed the next day.
**The flag is wrong** — the sealed package does cover the key that machine is using, and the two
fingerprints match exactly. Because of it the hub withholds a figure the machine needs, so the
machine tells its owner *"create a new recovery code"* — the one act that would put their old backups
beyond reach. **A freshly installed machine cannot reach this state**, because nothing has set that
flag since 5 August. **Cleared the same day; the machine now compares its key correctly again.** What
is still owed is a ruling on the flag itself: nothing sets it, nothing can see it, and it changes
what a household is told. *(R-246, R-247, R-248)*
- **The recovery walk passed** — see above. It also turned up five things: the retrieval passphrase
sitting in the page HTML *(R-249)*, a customer create that can fail on a fresh sub-account's DNS and
only says "try again" by not saying anything *(R-250)*, a recovery listing that shows the household
an "app" they never installed *(R-251)*, and the two unsignposted restore steps *(R-252, R-253)*.
- **The leftover flag that had been switching off recovery detection on one demo machine since
4 August was cleared with your approval**, and the fresh machine built for the walk confirmed it
cannot reach that state. Still owed: a ruling on the flag itself — nothing sets it, nothing can see
it, and it changes what a household is told. *(R-246, R-247, R-248)*
## What we're working on
- **The walk that either finishes the arc or says why not.** It needs the base image current (done
today) and a machine whose recovery detection is not silently switched off (answered today). *(R-201)*
- **Smoothing the two rough edges the walk found**, so the recovery reads as one path rather than
three. *(R-252, R-253)*
- **Proving the hub really keeps the old sealed key** when a machine re-seals. Never run outside a
test; needs a second deliberate wipe and its own session. *(R-198)*
## Waiting on you
- **Nothing.** The new base image was approved and is live — every future installation now carries
this week's fixes. *(R-239, R-242)*
- **Nothing blocking.** One thing is owed by us, not you: the walk's machine (`walk5`, VM 325) is
still standing as the evidence and needs tearing down.
*Nothing else is pending. R-245 — whether an undecided household is auto-abandoned after 30 days — was
**settled on 7 August** (we do not build it, and the reasoning is recorded). It has been re-filed as a
decision taken rather than a question sitting in your queue.*
*R-245 — whether an undecided household is auto-abandoned after 30 days — was settled on 7 August: we
do not build it, and the reasoning is recorded.*
## DooPlex infrastructure — separate from the product
@@ -80,8 +86,7 @@ being readable.*
free — clutter, not space. Nothing deleted. *(R-210)*
- **The hub password needs rotating** — a diagnostic printed it into a session log; nothing suggests
anyone else saw it. *(R-132)*
- **One thing to read after DooPlex next restarts.** The move to the second SSD has never been through
a reboot; it now writes PASS or FAIL to `/var/log/felhom-store-postboot-check.log` on every start.
On PASS, 34 GB comes back. *(R-209a)*
- **One thing to read after DooPlex next restarts** the second-SSD move has never survived a reboot;
it writes PASS/FAIL to `/var/log/felhom-store-postboot-check.log`. On PASS, 34 GB comes back. *(R-209a)*
- **Backup scripts on DooPlex are unversioned host state.** *(R-231)*
- **Instruction-file follow-ups**, each needing a decision rather than an edit. *(R-229, R-230)*
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,73 @@
# Teardown — OWED, not done (walk5, the fifth walk, 2026-08-07)
**Deliberately not performed in this session, per §10: the machine is the evidence until the verdict
is written.** The verdict is written (`journal.md`); the venue still stands so it can be re-read if
anything in this report is questioned. **Predecessor ledgers:** `teardown-finalwalk-2026-08-07.md`,
`teardown-2026-08-06.md`.
## The enumeration, matched on IDENTITY — never on size
Size is not a key here: on 2026-08-06 an item that measured exactly the expected size turned out to be
a working store.
| Layer | Item | Identified by |
|---|---|---|
| **machine** | `demo-hp` VM **325** `walk5-appliance` — 4 disks (efidisk + 200 G + 50 G + 50 G), **17 G actual** on `/mnt/nvme-1tb/images/325` | `qm config 325``name: walk5-appliance` |
| **hub** | customer **`walk5`**, host **`walk5-4bada5`** | `GET /configs/walk5/delete` preview + a FULL-SCHEMA census |
| **off-site** | Storage Box sub-account **285351**, user `u629488-sub4`, home naming the customer | Hetzner API, matched on the home directory |
| **off-site** | `ep0` PBS namespace **`walk5`** in datastore `felhom-offsite` | `ls /mnt/pbs-datastore/ns`**the live store is `/mnt/pbs-datastore`; `/srv/pbs-felhom` is STALE and reading it gives a wrong answer in both directions** |
| **network** | WireGuard peer **10.77.0.5** | `wg_peers.host_id = walk5-4bada5`; verify removal on ep0's **live `wg show`**, not only in the hub DB |
| **DooPlex** | `~/.config/walk5/``dashboard_pw.txt`, `root_pw.txt`, `root_pw_rotated.txt`, `breakglass.json`, `retrieval_passphrase.txt`, `claim_code.txt` (all `0600`) | **`R_walk5.txt` is already `shred -u`'d, with a planted-copy control proving the sweep works** |
| **DooPlex** | the `walk5` block in `~/.ssh/config`, and the appliance's host key in `~/.ssh/known_hosts` | |
## `pvesm status` BEFORE (2026-08-07, venue standing)
```
c11-scratch dir active 983379700 KiB total 23680040 KiB used 909673048 KiB avail 2.41%
```
Take it again after; the delta should be ≈ 17 G. (`c11-scratch` and `felhom-backup` are two `dir`
entries over the **same** path `/mnt/nvme-1tb`, so they move together — do not read that as double
counting.)
## The gate that shapes the operation
**The cascade REFUSES to delete a live host** — there is no hub decommission endpoint; the word appears
only in the refusal. So VM 325 must be **stopped first** (guarded on `qm config 325` reading
`name: walk5-appliance``demo-hp` also carries a guest 9201, and the appliance carries its own) and
the hub allowed to age it past its `stale_threshold` (**30 m**, read from the deployed `hub-config`,
not assumed). Poll `GET /hosts/walk5-4bada5/delete-impact` for `deletable` — and **treat an empty
response as retry, not as success**.
Then `POST /configs/walk5/delete` with all six gates: `ack_hosts=1 ack_reset=1 ack_purge=1
confirm_id=walk5 expect_hosts=1`.
## What will NOT be gone, and must be checked rather than assumed — R-244
A full-schema census after the cascade will return rows, not zero. Four sources are **deliberate**
(`events`, `notification_log`, `host_deletions`, `customer_resets` — *"provenance/events are NEVER
wiped"*). The fifth is the open gap: **`app_log_issues`**, which the residue purge does not touch.
**Measured 2026-08-08 across the whole table:** 1309 rows, of which **71 reference a torn-down venue**
(`finalwalk`, `c11`, `rewalk`, `part4`) — **44 orphans** (safely deletable) and **27 shared with a live
customer** (`demo-felhom`, `peti-felhom`, …) which must be **de-referenced, never deleted**. **This
walk will add to that count.** Do not attempt a `DELETE … WHERE customer LIKE` — it would destroy a
live customer's issue history. R-244 carries the proposed shape.
**A per-table absence query is not a census.** The verification is a full-schema sweep, and that is
what found this.
## Positive controls the teardown must keep (each must SURVIVE)
- `qm list` still shows VM **300 `drill-r50`** — the protected drift fixture.
- Guest **9201 on `demo-hp` itself** still running (the host was never the target).
- Storage Box sub-accounts **`u629488-sub1/2/3`** (demo-felhom, peti-felhom, demo-hp) still present.
- `ep0` namespaces **`demo-felhom`** and **`demo-hp`** still present.
- WireGuard peers **10.77.0.2/.3/.4/.250** still on `wg0`.
- Hub rows for `demo-felhom`, `demo-hp`, `peti-felhom`, `david` untouched.
## One extra item this walk adds
**The `walk5` retrieval passphrase is compromised** — it reached a session transcript from the customer
page's `data-secret` attribute (**R-249**). It dies with this customer's deletion, which is the reason
the teardown should not be left indefinitely. No other walk5 secret left its `0600` file.