# RUNBOOK — open a retained escrow package for a household (R-304, design option C, second slice) > **When:** the hub mailed you `recovery_older_package` — a household's recovery code opens (422), or may open (424), > an OLDER sealed package that the hub keeps as retained custody (R-222), and the household asked for data from that > older off-site store. The product has no path to a retained package (R-312: reopening old history is > operator-only). This is that path, written down from the drill that proved it end to end > (`audits/DRILL-retained-key-2026-08-12.md` §3.5–3.6; memory note „opening an escrow blob by hand"). > > **Promise:** none new. The household's dashboard says „contact support"; this is what support does. ## Rules for the whole procedure - **The household types its recovery code, on its own box.** You never ask for it in a mail or chat, and it is never on a command line or in a file outside the box's `/mnt/` work folder (deleted at the end). - **Nothing is printed.** A recovered password is verified by its SHA-256 against the hub's record, never shown. - **Restore into a NEW folder**, never over the household's live data. The household moves files afterwards. - One package, one session; do it with the household present (phone or screen-share). Write what you did in the household's support log. ## 1. Find the package (DooPlex, read only) 1. Snapshot the hub database **with its `-wal` and `-shm`** (a copy of `hub.db` alone can be hours stale). 2. In the copy: `SELECT id, host_id, length(identity_blob), restic_pw_sha256, superseded_at FROM host_escrow_superseded WHERE host_id='' ORDER BY superseded_at DESC;` — the mail names the box and the date; pick that row. 3. Write the blob out with `writefile` (never `SELECT` a BLOB to a terminal): `SELECT writefile('/tmp/-.age', identity_blob) FROM host_escrow_superseded WHERE id=;` 4. Note the row's `restic_pw_sha256` — the check value for step 3. ## 2. Bring it to the box 1. Copy the blob into the household's guest under **`/mnt/felhom-retained-/`** (bind-mounted into the controller container at the same path — `restic` lives INSIDE the `felhom-controller` container, and a path under `/root` is invisible to it). 2. Copy the drill's pty wrapper (a ~30-line Python `pty.fork()` that runs `age -d -o ` and answers the passphrase prompt) to the same folder. `age -d` will not read a passphrase from stdin; it needs the pty. ## 3. The household unseals it 1. The household types the recovery code (the ten words) into the wrapper's prompt on its box. A wrong code fails closed at the scrypt step — no partial output. 2. The output is the identity bundle. Take `restic_repo_password` from it into a 0600 file in the same folder. 3. **Check it:** `sha256sum` of the trimmed password must equal the row's `restic_pw_sha256` (step 1.4). If not: stop — wrong package or wrong code. ## 4. Read the old store 1. Mirror the controller's off-site arguments (`controller/internal/backup/offbox.go`, `offboxBaseArgs`): the sftp backend with the box's own `known_hosts` and `ssh_key`, and `RESTIC_PASSWORD_FILE=/mnt/felhom-retained-/pw`. Run it as `docker exec felhom-controller restic …`. 2. `restic snapshots` — the household picks the snapshot (date, app tag). 3. `restic restore --target /mnt/felhom-retained-/restore --include `. 4. Show the household the restored files. They move what they want into place through the dashboard's file tools or their share. ## 5. Clean up — always, also after a failure 1. `shred -u` the password file, the bundle and the blob copy; remove `/mnt/felhom-retained-/` once the household has its files. 2. Delete the hub DB copy on DooPlex. 3. Note in the household's support record: the date, the package id, the snapshot, what was restored. No secret. **Negative control used in the drill:** the box's CURRENT password against the old store → `Fatal: wrong password or no key found`. If you are unsure which store you are reading, run that first.