# felhom.eu — task reports > **Overwrite** this file with a summary of the most recent task only (uniform with the other repos; not cumulative). The cumulative hub history lives in [hub/CHANGELOG.md](hub/CHANGELOG.md). ## hub v0.15.0 — Phase 2 managed updates: per-customer controller-version floor (2026-06-27) **Why.** Phase 1 gave enthusiasts an opt-in "update to latest" button. Phase 2 adds the managed default: the operator sets a per-customer **minimum controller version** (defaulting to a global floor), and any box below it **auto-updates** on its next report — so the household that never clicks stays current and patched. Floor = the operator's enforced minimum and the auto-target; latest stays the customer's manual opt-in. ### Files changed - `internal/store/store.go` — `customer_configs.min_controller_version` column; `hub_settings` KV table; `defaultMinControllerVersion` + `SetDefaultMinControllerVersion`; `Get/SetGlobalMinControllerVersion`, `SetMinControllerVersion`, `EffectiveMinControllerVersion`. - `internal/api/handler.go` — `LatestVersionProvider` interface + `SetLatestVersionProvider`; report ACK returns `{min_controller_version, latest_version}` (both omitted when empty). - `internal/web/configs.go`, `server.go`, `templates/configs.html`, `templates/customer_unified.html` — operator UI: global floor editor + per-customer override form + Floor column / below-floor markers; routes `POST /configs/global-floor`, `POST /customers/{id}/floor`. - `cmd/hub/main.go` — `Config.ControllerUpdates.DefaultMinVersion` (yaml `default_min_version`, env `DEFAULT_MIN_CONTROLLER_VERSION`); seeds the store default; wires the version checker as latest provider. ### Design - Effective floor = per-customer override if non-empty, else global (hub_settings → config/env default), else "" (Phase 2 inert for that customer). - Rides the **existing report cycle** — no new floor-polling endpoint. The actual swap is the controller's Phase 1 flow (in-guest pull → agent `POST /controller/swap` → rollback); the hub only advertises the floor. **No agent change.** ### Tests (`go test ./...` green) - `internal/store/floor_test.go` — empty-when-unset; global-default fallback; DB-overrides-default; **override-beats-global (companion red-proof)**; set-and-preserve-across-save. - `internal/api/floor_ack_test.go` — ACK carries effective floor (override beats global) + latest; omits both when unset. - `internal/web/render_test.go` — template render smoke (catches `template.Must` panics + floor fields). - **Companion red-proof (verified):** making `EffectiveMinControllerVersion` ignore the override → `TestEffectiveFloor_OverrideBeatsGlobal` AND `TestReportACK_FloorAndLatest` FAIL → restored → green. ### Green gate `go build ./... && go vet ./... && go test ./...` → all pass. ### Deploy Built + pushed `gitea.dooplex.hu/admin/felhom-hub:0.15.0`, manifest bumped + synced (see hub/CHANGELOG and the live-test summary in felhom-controller/REPORT.md for the end-to-end floor auto-update result).