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:
2026-06-16 18:38:59 +02:00
parent 0d159d7e34
commit f3146ac7bf
7 changed files with 441 additions and 45 deletions
+5
View File
@@ -161,6 +161,11 @@ func BuildReport(
// "Inaktív" hub-side.
r.GeoRestriction = buildGeoRestrictionReport(geoRestriction)
// DR recipe app-half — customer identity + per-app {catalog_ref, enabled, storage_bindings}.
// Allowlist-only (the boundary): NO env/secret fields. The hub assembles it with the agent half.
r.DRRecipe = BuildDRRecipeAppHalf(cfg.Customer.ID, cfg.Customer.Name, cfg.Customer.Domain,
stackMgr.GetStacks(), readComposeFile)
if debug && logger != nil {
logger.Printf("[DEBUG] [report] BuildReport: complete — containers=%d, health=%s, deployed=%d, available=%d, app_telemetry=%d",
r.Containers.Total, r.Health.Status, len(r.Stacks.Deployed), len(r.Stacks.Available), len(r.AppTelemetry))