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:
@@ -42,7 +42,7 @@ func TestHostReport_ContractMatchesGolden(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Name: "usb-backup", Type: StorageTypeUSB, DurableID: "uuid:x",
|
||||
State: StorageStateAttached, Reachable: true,
|
||||
State: StorageStateAttached, Reachable: true, MountPath: "/mnt/usb-backup", TotalBytes: 2000000000000,
|
||||
Smart: SmartSummary{Health: SmartUnknown},
|
||||
},
|
||||
},
|
||||
@@ -73,6 +73,8 @@ func TestHostReport_ContractMatchesGolden(t *testing.T) {
|
||||
AuditTail: []AuditEntry{},
|
||||
Cloudflared: Cloudflared{Status: "active"},
|
||||
}
|
||||
// dr_recipe host-half: built from the same guest/storage/pbs facts (the production path).
|
||||
report.DRRecipe = BuildDRRecipeHostHalf(report.Guests, report.StorageTargets, report.PBSSnapshots)
|
||||
b, _ := json.Marshal(report)
|
||||
var got map[string]any
|
||||
json.Unmarshal(b, &got)
|
||||
@@ -95,6 +97,15 @@ func TestHostReport_ContractMatchesGolden(t *testing.T) {
|
||||
assertSameKeys(t, "restore_tests[0]", firstElem(golden["restore_tests"]), firstElem(got["restore_tests"]))
|
||||
// slice-6-Phase-B addition — pbs_snapshots[0] key set.
|
||||
assertSameKeys(t, "pbs_snapshots[0]", firstElem(golden["pbs_snapshots"]), firstElem(got["pbs_snapshots"]))
|
||||
|
||||
// DR-recipe host-half — the agent's secret-free reconstruction-scaffolding section. Assert the
|
||||
// dr_recipe key set + each sub-array's element key set (the cross-repo wire pinned in the golden).
|
||||
grec, srec := golden["dr_recipe"], got["dr_recipe"]
|
||||
assertSameKeys(t, "dr_recipe", grec, srec)
|
||||
assertSameKeys(t, "dr_recipe.pbs", field(grec, "pbs"), field(srec, "pbs"))
|
||||
assertSameKeys(t, "dr_recipe.guests[0]", firstElem(field(grec, "guests")), firstElem(field(srec, "guests")))
|
||||
assertSameKeys(t, "dr_recipe.drives[0]", firstElem(field(grec, "drives")), firstElem(field(srec, "drives")))
|
||||
assertSameKeys(t, "dr_recipe.pve_storage[0]", firstElem(field(grec, "pve_storage")), firstElem(field(srec, "pve_storage")))
|
||||
}
|
||||
|
||||
// field extracts a nested object value from a decoded JSON map (nil if absent/not a map).
|
||||
|
||||
Reference in New Issue
Block a user