30380a59f4
Operator sets a minimum controller version (FLOOR), per-customer defaulting to a
global floor; the report ACK returns the effective floor + latest_version so the
controller auto-updates to the floor when below it (latest stays the opt-in button).
- store: min_controller_version column + hub_settings global floor + Effective/
Get/SetGlobal/SetMin resolution + config/env DEFAULT_MIN_CONTROLLER_VERSION
- handler: report ACK {min_controller_version, latest_version}; LatestVersionProvider
- web: global floor editor + per-customer override form + Floor column (English)
- tests: floor resolution + ACK + render; override-precedence red-proof verified
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FSZmmSFVzGwEzhYmxbkgBK
47 lines
3.0 KiB
Markdown
47 lines
3.0 KiB
Markdown
# 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).
|