slice 10D (agent): DR capstone — identity escrow + restore-mode consumption (v0.18.0)
Identity escrow wraps {tunnel_token,pbs_token} under the SAME R via age
(scrypt+ChaCha20-Poly1305), reusing the K-escrow pty; wrong R fails closed.
escrow.Create optionally emits the identity blob; escrow-create uploads it +
the non-secret directive; identity-consume recovers it (R by hand, never
logged). K-escrow + 10C Consume untouched. Closes slice 10 with hub v0.11.0;
operator-side rotation model (hub holds no Cloudflare write-power).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,34 @@
|
||||
All notable changes to **felhom-agent** are recorded here. Update on every code
|
||||
change that gets pushed.
|
||||
|
||||
## v0.18.0 — slice 10D: DR capstone — identity escrow + restore-mode consumption (agent side) (2026-06-10)
|
||||
|
||||
The agent half of the slice-10 DR capstone (closes slice 10). Grounded by both 10-series spikes
|
||||
(escrow-consumption + identity-restore). The hub half (recovery-mode toggle, re-enroll + credential
|
||||
rotation, directive serving) is hub v0.11.0. **Operator-side rotation model (locked):** the hub holds
|
||||
no Cloudflare write-power; the destructive tunnel/PBS rotation is the operator's step from a trusted
|
||||
environment (same spirit as 10B).
|
||||
|
||||
### Added (`internal/escrow`)
|
||||
- **Identity escrow** (`identity.go`): `WrapIdentity`/`UnwrapIdentity` (+ `…Bundle`) wrap the
|
||||
`{tunnel_token, pbs_token}` bundle under the SAME recovery code `R` via **`age`** (scrypt +
|
||||
ChaCha20-Poly1305 — a vetted passphrase-AEAD, not hand-rolled), reusing the K-escrow pty mechanism
|
||||
(passphrase via the tty, data via files; `R`/tokens never logged). Same two-factor, zero-knowledge
|
||||
shape as the K-escrow. A **wrong R fails closed** (no bundle). `age` is a runtime dep for the
|
||||
identity path (analogous to proxmox-backup-client for K).
|
||||
- **`escrow.Create`** gains an optional `IdentityBundle` → also emits an `IdentityBlob` under the same
|
||||
R (additive; the K-escrow + 10C `Consume` paths are byte-unchanged). Self-verifies the identity
|
||||
round-trip before shipping.
|
||||
- **`--selftest=escrow-create -identity-bundle <file> -directive <file>`** — also wrap + upload the
|
||||
identity blob + the **non-secret** DR directive (pbs repo/ns, expected key fingerprint, tunnel id).
|
||||
- **`--selftest=identity-consume -blob <file> -keydest <file>`** (R via `FELHOM_RECOVERY_CODE`) —
|
||||
recover the identity bundle through the real code; tokens written 0600, never logged.
|
||||
|
||||
### Tests
|
||||
- identity bundle round-trips (wrap→unwrap byte-identical; blob is opaque ciphertext); wrong R fails
|
||||
closed + the blob stays retryable; input validation. K-escrow/10C tests byte-unchanged (additive).
|
||||
(age integration tests gated to a host with the `age` CLI.)
|
||||
|
||||
## v0.17.0 — slice 10C: escrow consumption (productionize the spike) (2026-06-10)
|
||||
|
||||
Turns the throwaway 10C spike harness into a real, tested **`Consume`** path: recover the PBS key
|
||||
|
||||
Reference in New Issue
Block a user