From 6ae61f4c023fe1e01e24da8f369011285be12567 Mon Sep 17 00:00:00 2001 From: Garrett Allen <98648590+Gerrrt@users.noreply.github.com> Date: Tue, 8 Sep 2026 06:25:21 +0000 Subject: [PATCH] docs(secrets): name the second recipient's holder, and fix the roadmap's rejection (#294) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ADR-0024 built the mechanism — make secrets-add-recipient, per-recipient proof, the runbook text — under #106, and deliberately left one question open: who else should be able to open the estate's secrets. #294 exists to answer it, and the answer is the technical second named on the break-glass card, holding a recipient of their own generated where they keep it. That satisfies ADR-0023's off-estate constraint and the successor-handover case in one move. The location stays out of the repository, as the first key's does. Written in the honest form: whether their key is in .sops.yaml is read from the file, not from the paragraph, because the keypair is generated offline by hand and this commit cannot add it. The handover runbook's recovery path becomes a call to a named role rather than "obtain the key from the person you are replacing", which fails in exactly the case a trustee exists for. The roadmap's #94 entry still read "Rejected: a second age recipient" with no pointer to ADR-0024 — the one place in the documents that contradicted it. Narrowed to what was actually rejected: a recipient on oracle. Co-Authored-By: Claude Fable 5.1 --- docs/roadmap.md | 13 ++++++++----- docs/runbooks/back-up-the-age-key.md | 23 +++++++++++++++++------ docs/runbooks/successor-handover.md | 17 +++++++++++------ 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/docs/roadmap.md b/docs/roadmap.md index f3c0e3d..ba834f6 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1525,11 +1525,14 @@ them name the condition that would change the answer. work whose value is that it is not on the monitoring host. The wiki and the firewall export copy it already has; the volume backup sets (#92) and the dead man's switch watcher (#67) are added, decided here and built - under their own issues. **Rejected:** a second age recipient, because - `back-up-the-age-key.md` already answers that gap with an *offline* key - and a second person, and because a private key on `oracle` would put the - backups and the means to open them on one disk and retire the property - the off-host copy exists to have. Also rejected: the ADR-0007 stack, the + under their own issues. **Rejected:** a second age recipient *on `oracle`*, + because a private key there would put the backups and the means to open + them on one disk and retire the property the off-host copy exists to + have — narrowed by + [ADR-0024](adr/0024-hold-a-second-age-recipient-and-prove-each-one-separately.md), + which keeps that rejection and makes a second recipient held *off* the + estate the design (#106); its holder was decided on 2026-09-08 under + [#294](https://github.com/Gerrrt/HomeLab/issues/294). Also rejected: the ADR-0007 stack, the ADR-0008 tier, bringing `wlp22s0` up to give the watcher an independent path — that dual-homes a VLAN 99 host onto an untrusted segment — and switching the machine off, which was never really on offer: the wiki had diff --git a/docs/runbooks/back-up-the-age-key.md b/docs/runbooks/back-up-the-age-key.md index 5f8c2e9..540b435 100644 --- a/docs/runbooks/back-up-the-age-key.md +++ b/docs/runbooks/back-up-the-age-key.md @@ -278,12 +278,23 @@ master password, and that takes everything in it at once. ## What this still does not solve -**One person.** ADR-0024 answers the copy and deliberately does not answer the -holder: whether somebody else should be able to open the estate's secrets is a -question about people, not about mechanism. What has changed is that the -mechanism is now built and exercised — a second holder is the same -`make secrets-add-recipient` with their public key, not a procedure to work out -on the day it matters. +**One person — decided 2026-09-08 +([#294](https://github.com/Gerrrt/HomeLab/issues/294)).** ADR-0024 answered +the copy and deliberately left the holder open, because whether somebody else +should be able to open the estate's secrets is a question about people. The +answer is the **technical second named on the break-glass card**: they hold a +recipient of their own, generated where they keep it and never on this host, +which satisfies ADR-0023's off-estate constraint and the handover case in one +move. The location stays out of this repository, as the first key's does. + +Whether their key is in `.sops.yaml` yet is read from the file +(`grep -A3 creation_rules .sops.yaml`), not from this paragraph. Adding it is +the procedure above — `make secrets-add-recipient` with their public half — and +then `make secrets-verify-backup` with *each* key, because a re-key that drops +a recipient is the failure mode here. What this still does not solve: their +copy cannot be proved from here on their behalf. `SecretsKeyBackupUnproven` +names the recipient that is overdue, and clearing it for theirs is a visit with +the removable medium, not a timer. **Revocation is still rotation.** Removing a recipient and re-keying protects values encrypted from then on. Every historical ciphertext in git stays readable diff --git a/docs/runbooks/successor-handover.md b/docs/runbooks/successor-handover.md index eb3ae0a..b331721 100644 --- a/docs/runbooks/successor-handover.md +++ b/docs/runbooks/successor-handover.md @@ -259,12 +259,17 @@ grep -A3 creation_rules .sops.yaml # every key that can open the secrets ``` If a recipient there is one somebody else holds, the secrets are recoverable and -this is a phone call rather than a rotation. - -**A handover is the moment to add one.** ADR-0024 answers the copy and -deliberately leaves the holder open, which is exactly the question a successor -is. Generate the keypair where *they* will keep it, and add its public half from -a host that can already decrypt: +this is a phone call rather than a rotation. Since 2026-09-08 the design is that +there is one: the **technical second named on the break-glass card** holds a +recipient of their own ([#294](https://github.com/Gerrrt/HomeLab/issues/294), +[`back-up-the-age-key.md`](back-up-the-age-key.md)). If `.sops.yaml` lists two +keys, the second is theirs, and the call is to them. + +**A handover is the moment to add yours.** ADR-0024 built the mechanism and +[#294](https://github.com/Gerrrt/HomeLab/issues/294) named the second holder; +a successor is a third. Generate the keypair +where *you* will keep it, and add its public half from a host that can already +decrypt — theirs, if the one you were handed is gone: ```bash make secrets-add-recipient PUBKEY=age1...