# REPORT — agent v0.77.0: fork-4 escrow the offsite restic repo password under R **Date:** 2026-07-09 · **Class:** implementation (agent). **Baseline:** `main` @ `7f07393` (v0.76.0) → `0c22b9b` (v0.77.0). Pairs with controller v0.105.0. Design validated by the custody spike (`felhom.eu/documentation/audits/SPIKE-restic-password-custody-2026-07-09.md`, `febdc56`). ## What shipped Makes the restic-offsite repo password recoverable at DR by riding the existing customer-recovery-code (R) zero-knowledge escrow (age-under-R, in `IdentityBundle`). Additive; the PBS-K escrow path is untouched. - `internal/escrow/identity.go`: `IdentityBundle.ResticRepoPassword` (rides `WrapIdentityBundle`/ `UnwrapIdentityBundle`, self-verified by `escrow.Create`); `AttachResticPassword` (mirrors `AttachWGKey`); `StagedResticPasswordPath` + `WipeStagedResticPassword`. - `internal/localapi`: `POST /escrow/stage-secret` (`withGuest` + `scopedFromBody`) stages the controller-pushed password 0600 (atomic tmp+rename), **never logged** (field name only), overwritten on re-push. Stage path injectable via `Options.EscrowStagePath` (default `StagedResticPasswordPath`). - `cmd/felhom-agent/main.go` (`runSelftestEscrowCreate`): auto-injects the staged password into the bundle (mirrors the WG-key auto-inject) and wipes the staging file after a successful `escrow.Create`. ## Files changed (commit `0c22b9b`) `internal/escrow/identity.go`, `internal/escrow/identity_test.go`, `internal/localapi/server.go`, `internal/localapi/escrow_stage.go` (new), `internal/localapi/escrow_stage_test.go` (new), `cmd/felhom-agent/main.go`, `CHANGELOG.md`, `CONTEXT.md`. ## Tests Green gate `go build ./... && go vet ./... && go test ./...` on the build host (age present) — **all green**. New tests: - `TestIdentity_RoundTrip_CarriesResticPassword` — the bundle carries `ResticRepoPassword` byte-exact, the blob does not leak the plaintext, and a wrong R fails closed (no bundle). - `TestAttachResticPassword` — missing staged file → clean no-attach; present → trimmed value attached; empty → error. - `TestStageEscrowSecret_StagesScopesAndHidesValue` — the pushed secret is staged 0600, the ack is `{ok,data.staged:true}` (no value echoed), a cross-guest push is 403 and does not overwrite the staged file. - `TestStageEscrowSecret_NoSecretInLog` — the staged value never appears in a captured log buffer. Note: `TestGenerateRecoveryCode_EntropyAndFormat` is the documented pre-existing flake (a hyphenated wordlist word splits to 11) — re-run passes; unrelated to this change. ## Deploy verification Built `felhom-agent 0.77.0` (`go build -ldflags -X main.version=0.77.0`), installed on felhom-pve (prior binary backed up to `felhom-agent.bak-0.76.0`), `systemctl restart felhom-agent` → `--version` = 0.77.0, `systemctl is-active` = active, **capabilities self-check ok=56 total=56 degraded=0**, local-api listening on 192.168.0.162:8443, no errors/panics. ## NOT yet live-validated The supervised escrow ceremony (enable → stage → `--selftest=escrow-create` with a real R → confirm → gated run) is the **operator-run** follow-up — NOT run here. The stage endpoint is deployed and unit-proven. No agent publish (`publish-agent.sh`) / Day-0 manifest bump was done — that is a separate operator step.