agent v0.38.0: DR recipe — emit secret-free storage/guest/PBS half in host-report
DR recipe slice (agent half), grounded in SPIKE-dr-recipe-2026-06-16. Additive `dr_recipe` host-report section = the non-secret reconstruction scaffolding the operator must rebuild before PBS bytes can land. Built by pure BuildDRRecipeHostHalf from facts the report already collects (no new reads): guests[] sizing, drives[] (user-data by durable_id/role/mount/intent), pve_storage[] (storage.cfg), pbs coordinates. BOUNDARY (Phase-1 lesson): every field is an identifier/intent/size/coordinate — never a key/password/token/hash/ENC:. PBS key stays in escrow; restic password stays in escrow; the recipe names only the coordinates the restore targets. Tests: BuildDRRecipeHostHalf selection, NoPBS, NoSecrets (boundary mirror), dr_recipe key-set in the cross-repo golden contract test. recipe_version=1, ignore-unknown on read. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,32 @@
|
||||
All notable changes to **felhom-agent** are recorded here. Update on every code
|
||||
change that gets pushed.
|
||||
|
||||
## v0.38.0 — DR recipe: emit the secret-free storage/guest/PBS half in the host-report (2026-06-16)
|
||||
|
||||
**DR recipe slice (agent half).** Additive `dr_recipe` section on the host-report — the agent half of the
|
||||
secret-free reconstruction recipe (`SPIKE-dr-recipe-2026-06-16.md`) that complements escrow (keys) +
|
||||
PBS/restic (bytes): the non-secret SCAFFOLDING an operator must rebuild before the PBS bytes can land.
|
||||
The hub assembles it with the controller's app half into one customer recipe.
|
||||
|
||||
- `internal/hub/dr_recipe.go` — `DRRecipeHostHalf{recipe_version, guests[], pbs, drives[], pve_storage[]}`
|
||||
built by the pure `BuildDRRecipeHostHalf(guests, targets, pbs)` from facts the report ALREADY collects
|
||||
(no new privileged reads): `guests[]` = each guest's sizing (`GuestSpec`, skip status-unknown);
|
||||
`drives[]` = the user-data external drives (usb/local-dir with a `uuid:` durable-id + mount path) with
|
||||
`{durable_id, role, mount_path, intent, total_bytes}`; `pve_storage[]` = every storage target
|
||||
`{name, type, content}` (the `storage.cfg` scaffolding); `pbs` = the latest snapshot's coordinates
|
||||
`{repo_id (the pbs storage id), namespace, latest_snapshot_id}`. Wired into `Collect()` after the facts
|
||||
are gathered; `HostReport.DRRecipe` (always set, never null).
|
||||
- **BOUNDARY (the Phase-1 lesson):** every field is an identifier / intent / size / coordinate — NEVER a
|
||||
key, password, token, hash, or `ENC:` value. The PBS encryption key stays in escrow; the access token in
|
||||
identity-escrow; the restic password in escrow — the recipe names only the `repo_id`/`namespace`/
|
||||
`durable_id`/`restic_repo_coord` the restore TARGETS. `recipe_version=1`; read is ignore-unknown
|
||||
(forward-compat). The wire shape is pinned in the cross-repo golden (`host-report.golden.json` here +
|
||||
the hub's copy — keep them byte-identical; manual checksum-diff on any change).
|
||||
- Tests: `TestBuildDRRecipeHostHalf` (drives = only user-data; pve_storage = all; pbs = latest; guests
|
||||
skip nil-spec), `..._NoPBS` (omitted, non-nil slices), `TestDRRecipeHostHalf_NoSecrets` (the lighter
|
||||
boundary mirror — serialized half carries NO credential-shaped key; the load-bearing version is on the
|
||||
controller emitter), and the `dr_recipe` key-set added to `TestHostReport_ContractMatchesGolden`.
|
||||
|
||||
## v0.37.0 — host-reboot remount re-resolves enrolled drives by filesystem UUID (2026-06-16)
|
||||
|
||||
**TASK A — close out the reboot story (agent half).** On a host reboot the kernel can re-enumerate block
|
||||
|
||||
Reference in New Issue
Block a user