net-kingdom/docs/crisis-custody-list.md
tegwick dcb5bc2540
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
NK-WP-0054: founder decision 9f0f7a87 - split goes live this week, admin dispositions, crisis list confirmed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 308701@bnt-lap001
Assistant-Session: 5548e447-444c-4dcc-bed1-05c16eebfe56
2026-10-28 18:53:10 +01:00

57 lines
9.3 KiB
Markdown

# Crisis custody list
NK-WP-0054-T07. Drafted 2026-10-24 from repository documents and the founder's statements
that day. **This list holds no secret value, ever.** It names what unlocks recovery, who
holds it, where, and whether using it needs the very services being recovered. Anything
the repository cannot establish is marked `TO CONFIRM`; the founder confirms each one.
It belongs with the backup documentation:
[disaster recovery guide](disaster-recovery-storage-share.md),
[identity restore drill](identity-restore-drill.md) and
[Credential Management Standard §4](../canon/standards/credential-management_v0.2.md).
That standard names the custody categories. This list makes them concrete.
## The one rule
For every row, answer: **does using this item work when SSO and OpenBao are down?**
A recovery path that is satisfied only by logging in to something being restored is a
circular dependency and is recorded as a gap, not as custody.
## Roles used below
| Role | Identity | Used for |
| --- | --- | --- |
| Crisis operator | `admin` | Runs recovery and routine validation (founder intent, 2026-10-24) |
| Authorizer | `platform-root` / king credential | Break-glass authority from offline custody; nothing routine |
| Developer | `tegwick` | Builds and tests tooling; holds no recovery keys |
## Items
| # | Item | Unlocks | Holder and location | Works with SSO and OpenBao down? | Last proven use | Gap or action |
| --- | --- | --- | --- | --- | --- | --- |
| 1 | **`railiance-backup` age private key** (recipient `age1zvry…50syr3tsz`). Not the custodian key (item 1b) | Decrypts the identity backup bundle and the break-glass copy on Storage Share (`net-kingdom-kingpath-*.tar.age`) | Two copies: founder's password safe (stored as `railiance-backup.key`) and a copy held by a named trusted person, who can recover if the founder cannot (founder, 2026-10-28) | Yes, offline | Identity stages 2026-10-24; king-path verify drill 2026-10-27 (the helper refused the custodian key three times before the correct key was entered, as designed) | Successor copy is not drill-proven; prove it once with `kingpath-offsite.py --verify` run by or with the successor |
| 1b | **Custodian age private key** (recipient `age1aq8t…qdepsh4`, `keys/age.pub` and `.sops.yaml`). Not the backup key | Decrypts the repository's SOPS custody files and greenfield bootstrap bundles (`docs/security-bootstrap-age-custody.md`) | Founder, password safe (stored as the custodian age private key) | Yes, offline | 2026-10, bootstrap/SOPS work (founder, 2026-10-28; not yet receipt-proven: run `make sops-custody-check`) | Labels in the safe should name the recipient prefix so the two keys cannot be confused |
| 2 | Storage Share `Backup` account app password | Downloads the protected ciphertext without OpenBao or SSO | Founder, in the independent password safe (founder, 2026-10-28) | Yes, provider is outside the platform | Fresh retrieval 2026-10-24 | One provider copy only; residual risk accepted until 2027-01-31 (G1, NK-WP-0053) |
| 3 | OpenBao unseal shares (2 of 3 required in the restore drill) | Unseals a restored or production OpenBao; with the shares, `generate-root` mints a root token for break-glass (ceremony in `railiance-platform/docs/openbao.md`; production loopback listener 8210 live since 2026-10-28) | Founder as `platform-root` holds all three shares (single-holder custody: accepted exception, hub decision `37464824`, 2026-10-27), in the founder's replicated browser password safe under the `kingpath.credentials` pseudo-URL entry (confirmed 2026-10-27) | Yes: the safe is independent of NetKingdom SSO and OpenBao; it depends on the browser vendor's sync account and its own factor | Original shares used in the isolated restore RPF-WP-0064-T07, 2026-10-24 | Single holder = single point of loss (reviewed at NK-WP-0055-T09). The founder holds the initial root token offline; the king-path drill (2026-10-28) found it **valid** as of the 2026-10-14 snapshot (root policy, no TTL, orphan). Founder decision `7ce684ec` (2026-10-28): stays escrowed during builder mode, revoked at production entry (NK-WP-0055-T16) |
| 4 | `platform-root` / king account and factors | Final authority; break-glass | Independently held password safe (kingpath entry) | **No if used through KeyCape**. The king path with SSO down is offline material instead: unseal shares (item 3) plus the `generate-root` ceremony on the loopback listener, the admin kubeconfig and static tunnel key (item 9, also on Storage Share), the Host Europe console, and the admission signing key (item 5) | OTP validated against restored privacyIDEA 2026-10-24 (isolated). King path drilled 2026-10-28: Storage Share restore of item 9, `generate-root` on an isolated restore, read-only production SSO-down walk ([record](evidence/2026-10-28-king-path-drill.md)) | Not drilled: using the restored item-9 material against the cluster, and the Host Europe console. Both belong in the recurring drill (NK-WP-0053) |
| 5 | Founder admission signing key (SSH ed25519, principal `bernd`, fingerprint `SHA256:NekDABfw8K8IBYznjREg7jPpcK/BzCgO1pH1ebT/FXM`) | Signs restore and drill admissions for the OpenBao isolated restore (namespace `railiance-openbao-restore-attempt`) and secrets-engine admissions | Private key: founder workstation `~/.ssh/gexec_approver_ed25519` (passphrase-protected; signed the T40, `-02` and `-03` admissions); founder decision 2026-10-28: also keep it in the password safe under the kingpath entry, **not** in the Storage Share bundle, so the backup age key alone cannot admit a restore. Public anchor (non-secret, needed on any recovery workstation): `/etc/railiance-openbao-restore/allowed_signers` and `/etc/secrets-engine/admission/allowed_signers`, one line each: `bernd namespaces="railiance-openbao-restore-attempt" ssh-ed25519 ssh-ed25519` ; the secrets-engine file uses namespace `secrets-engine-recovery-attempt` | Yes, offline | Signed the T40 admission 2026-10-23 | Private key stored in the password safe kingpath entry (founder, 2026-10-28). Re-create both anchor files from this row on a recovery workstation. The file name says `gexec_approver`, but the key's role is admission signing |
| 6 | `admin` password and OTP token | Day-to-day platform administration and, per intent, recovery operation | Founder; OTP enrolled 2026-10-24 | **No**: login and token checks need KeyCape, LLDAP and privacyIDEA | Token not yet in any restored backup; first restore proof after the 2026-10-25 03:45 UTC capture | Same account as the directory bind used by Authelia and privacyIDEA until the split in NK-WP-0054-T05 |
| 7 | `pi-admin` credentials (privacyIDEA internal admin) | Token repair and re-enrolment | Founder's replicated browser password safe (confirmed 2026-10-27) | Custody yes (replicated, independent of SSO); use needs a running privacyIDEA | Not yet drilled | Add a pi-admin check to the drill (NK-WP-0053-T04) |
| 8 | ~~Ops bundle (`make creds-bundle`)~~ **Retired 2026-10-27** (founder decision) | — | — | — | Never drilled; none existed on the workstation | Superseded by the daily identity backup, which carries the current service secrets. `make creds-bundle` packs only greenfield `creds-generate` output and stays a greenfield bootstrap step |
| 9 | Operator access to the production host or cluster for a real restore | Applying a restore to production | Cluster: ops-bridge tunnel `k3s-api-railiance01` (SSH as `tegwick` to `92.205.62.239` with a static key file, local port 16444) plus the attended admin kubeconfig `~/.kube/config-railiance01` (client certificate), today on the founder workstation only. Host: Host Europe provider interface with console and rescue access to railiance01 (confirmed 2026-10-27) | Yes: static key, client certificate and provider console need neither KeyCape nor OpenBao. **No** for ops-warden SSH certificates (warden's backend is OpenBao) | Cluster path used 2026-10-27 | Off-workstation copy uploaded and read back 2026-10-27: `Backup/railiance-backups/net-kingdom-kingpath/net-kingdom-kingpath-20261027T223050Z-8c9d48421f1b.tar.age` (10440 bytes, sha256 `8c9d4842…7dd4aa`, items `admin-kubeconfig`, `tunnel-ssh-key`, recipient `railiance-backup`; receipt on the founder workstation). Restore drilled 2026-10-27: fetched from Storage Share, unrelated key refused, decrypted in memory, both items intact (`kingpath-offsite.py --verify`). Using the restored material against the cluster is not drilled. Re-run `kingpath-offsite.py` whenever the kubeconfig or key changes. Open: runs as `tegwick` under an agent-labelled actor; provider console never drilled |
## Non-secret recovery assets
These need no custody but must be reachable: the published recovery kit on Storage Share
(guide, tools ZIP, checksum; verify the checksum against a trusted copy), the pinned
container images, and a trusted checkout of this repository. TLS for `kc.coulomb.social`
has no custody: it is reissued through ACME and needs working public DNS and HTTP-01.
## Maintenance
- Review at every restore drill (NK-WP-0053), and record the date each item was last
proven. An item never proven stays marked as such.
- Loss or suspected exposure of any item goes to its owner's rotation and revocation
process (Standard §6); this list rotates nothing.
- A machine-readable, non-secret record with a freshness check, modelled on
`tools/custody-record`, is proposed in NK-WP-0054-T07. Until then this document is the list.