controller v0.73.0: DR recipe — emit secret-free customer+apps half in hub report
DR recipe slice (controller half), grounded in SPIKE-dr-recipe-2026-06-16. The
controller emitter is the BOUNDARY enforcement point: v1 ships an explicit
allowlist {catalog_ref, enabled, storage_bindings} and reads NOTHING from
AppConfig.Env, so no ENC:/token/password can leak. storage_bindings parsed from
the compose (${HDD_PATH}/${USERDATA_PATH} volume binds -> {container_path,
drive, subpath}).
Load-bearing tests: TestBuildAppRecipe_NoSecrets (synthetic-secret app -> none
leak) + TestBuildAppRecipe_AllowlistIsLoadBearing (red-proof companion) +
TestAppStorageBindings + TestBuildDRRecipeAppHalf. Red-proofed live: forcing the
emitter to dump Env makes the boundary test fail. recipe_version=1.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,29 @@
|
||||
## Changelog
|
||||
|
||||
### v0.73.0 — DR recipe: emit the secret-free customer+apps half in the hub report (2026-06-16)
|
||||
|
||||
**DR recipe slice (controller half).** Additive `dr_recipe` section on the controller's hub report — the
|
||||
customer + apps half of the secret-free reconstruction recipe (`SPIKE-dr-recipe-2026-06-16.md`). The hub
|
||||
assembles it with the agent's storage/guest/PBS half into one customer recipe.
|
||||
|
||||
- `internal/report/dr_recipe.go` — `DRRecipeAppHalf{recipe_version, customer{id,display,domain}, apps[]}`
|
||||
built by the pure `BuildDRRecipeAppHalf(...)` over the DEPLOYED, non-protected stacks. Per app:
|
||||
`AppRecipe{catalog_ref (Meta.Slug, falls back to name), enabled, storage_bindings[]}`. Storage bindings
|
||||
are parsed from the compose (`appStorageBindings`) — each `${HDD_PATH}`/`${USERDATA_PATH}` volume bind
|
||||
becomes `{container_path, drive (basename of HDD_PATH), subpath}` (e.g. romm → felhom-flash:userdata/roms);
|
||||
named volumes are excluded. Wired into `BuildReport`.
|
||||
- **THE BOUNDARY (the emitter is the enforcement point).** v1 ships an explicit ALLOWLIST — only the three
|
||||
fields above — and the emitter reads **NOTHING** from `AppConfig.Env`, so no `ENC:` value / token /
|
||||
password can ride along. Allowlist, not denylist → a new field is excluded by default.
|
||||
- Tests (the load-bearing no-secrets boundary test + companion): `TestBuildAppRecipe_NoSecrets` feeds an
|
||||
app whose `Env` carries synthetic secrets (an `ENC:` value + a token-shaped value) and asserts the
|
||||
emitted recipe contains NONE of those values and NO credential-shaped key;
|
||||
`TestBuildAppRecipe_AllowlistIsLoadBearing` is the red-proof (a guard-removed shape leaks the token, the
|
||||
production emitter does not); `TestAppStorageBindings` (+ `_NoHDD`) pins the compose parse; and
|
||||
`TestBuildDRRecipeAppHalf` checks assemble-correctness (deployed/non-protected only) with a whole-half
|
||||
secret sweep. Red-proofed live: forcing the emitter to dump `Env` makes the boundary test fail.
|
||||
`recipe_version=1`, ignore-unknown on read.
|
||||
|
||||
### v0.72.0 — FileBrowser converges on boot-recreate (2026-06-16)
|
||||
|
||||
Follow-up to v0.71.0: a host-reboot test found `processGuestBootChange` recreated the drive-backed app
|
||||
|
||||
Reference in New Issue
Block a user