Files
felhom.eu/documentation/runbooks/RUNBOOK-open-retained-package.md
T

64 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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='<host>' 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/<host>-<id>.age', identity_blob) FROM host_escrow_superseded WHERE id=<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-<date>/`** (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 <out> <blob>` 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-<date>/pw`.
Run it as `docker exec felhom-controller restic …`.
2. `restic snapshots` — the household picks the snapshot (date, app tag).
3. `restic restore <snapshot> --target /mnt/felhom-retained-<date>/restore --include <what they need>`.
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-<date>/` 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.