Files
felhom-agent/REPORT.md
T

3.3 KiB

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.