slice 7 escrow: agent contract test + CHANGELOG/REPORT/CLAUDE (v0.9.0)
Agent half of slice-7 close-out finalized: cross-repo wire-contract test (escrowUploadRequest mirrors the hub), v0.9.0 CHANGELOG entry + REPORT + CLAUDE version line. No secrets. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,40 @@
|
||||
All notable changes to **felhom-agent** are recorded here. Update on every code
|
||||
change that gets pushed.
|
||||
|
||||
## v0.9.0 — slice 7 close-out: PBS recovery-code escrow creation (2026-06-10)
|
||||
|
||||
The first code that touches the PBS client encryption key `K` and introduces the customer recovery
|
||||
code `R`. Default posture is **zero-knowledge**: Felhom holds an opaque `R`-wrapped blob (cannot
|
||||
open it), the customer holds `R`. Grounded by `felhom.eu/documentation/tests/slice7-escrow-spike-findings.md`
|
||||
(round-trip proven on a throwaway: the `R`-recovered key restores a real encrypted snapshot). Hub
|
||||
opaque storage is the `felhom.eu` half (hub v0.8.0); consumption/serving is slice 10.
|
||||
|
||||
### Secret discipline (overriding)
|
||||
`R` is `crypto/rand`, ≥128 bits, surfaced **exactly once** and **never** logged/persisted/committed;
|
||||
the wrap pty's echo is discarded so `R` can't leak. `K` is read by location, **never modified** (the
|
||||
live key file is byte-unchanged — Wrap operates on a copy), never logged.
|
||||
|
||||
### Added
|
||||
- **`internal/escrow`** — `Create` generates `R` (10 EFF-wordlist words ≈ 129 bits), wraps `K` under
|
||||
`R` via the **PBS-native** `proxmox-backup-client key change-passphrase --kdf scrypt`, and
|
||||
**self-verifies** the blob recovers `K` (fingerprint match) before shipping. The wrap is driven
|
||||
over a **stdlib pty** (`x/sys/unix`; spike F-A1 — the command is TTY-only) with **output discarded**
|
||||
(F-A2 — the pty echoes the passphrase). Opt-in outputs: **(b)** `R`-wrapped offline copy (two-factor,
|
||||
no extra trust) and **(a)** raw paperkey (single-factor, unrevocable — loud caveat).
|
||||
- **`--selftest=escrow-create`** (`-storage`, `-paperkey`, `-offline`, `-upload`): surfaces `R` once
|
||||
to stdout (never the logger), prints the opaque blob's size/fingerprint/posture, and with
|
||||
`-upload` PUTs the blob to the hub (`/api/v1/hosts/{host_id}/escrow`, per-host key).
|
||||
- Config: `escrow` section (`posture` default `zero_knowledge`, `pbs_storage_id`); `PBSEncKeyPath`
|
||||
helper (the `<id>.enc` key K).
|
||||
- Runtime dependency on the `proxmox-backup-client` CLI (the PBS key+passphrase KDF).
|
||||
|
||||
### Tests
|
||||
- `R` entropy ≥128 / 10-word format / uniqueness; integration round-trip (wrap→unwrap fingerprint
|
||||
match, **wrong-`R` fails**, **live `K` byte-unchanged**, blob ≠ plaintext key) guarded to
|
||||
linux+`proxmox-backup-client`; the agent→hub wire-contract key-set (mirrors the hub's).
|
||||
- **Live-validated** (demo): `escrow-create` → `R` (10 words) surfaced once, blob 383 B opaque,
|
||||
self-verify ok, **live `K` sha256 unchanged**, exact `R` absent from stderr/journal.
|
||||
|
||||
## v0.8.0 — slice 7 Phase 1: unified bring-up reconcile job (provision + guest-loss DR) (2026-06-09)
|
||||
|
||||
The shared FRONT HALF of provision and guest-loss DR, as a journaled reconcile job mirroring the
|
||||
|
||||
Reference in New Issue
Block a user