# 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); the scripts history lives in [scripts/CHANGELOG.md](scripts/CHANGELOG.md). ## Hub v0.54.0 — operator login password changeable from the UI — 2026-07-13 ### What & why The hub login password could previously be changed **only** by editing `auth.password_hash` in the `hub-config` ConfigMap and redeploying — no in-app path existed (operator hit this wall). Added a **Configuration → Login password** card that changes the password at runtime, persisted in the DB, with the ConfigMap kept as the break-glass reset path. ### Design (matches the controller-version-floor precedence pattern) - **Store** (`internal/store/store.go`): new `hub_settings` key `operator_password_hash` with `GetOperatorPasswordHash()` / `SetOperatorPasswordHash()` (thin wrappers over the existing `getSetting`/`setSetting`). No schema change. - **Server** (`internal/web/server.go`): the static `Server.passwordHash` field is renamed `configPasswordHash` (the hub.yaml SEED). New `effectivePasswordHash()` = **DB override wins, else config seed** — and it is now the single source for every auth check (CSRF gate, `RequireAuth` session + Basic-Auth paths, `handleLogin`). - **Handler** `POST /configuration/password` (`handleChangePassword`): requires the current password (verified against the effective hash), new password 8–72 bytes, matching confirmation, rejects a no-op. On success bcrypts (cost 10) and persists the override. Existing sessions stay valid; CSRF enforced by the central `ServeHTTP` gate; no secret logged. - **UI** (`templates/configuration.html`): current/new/confirm fields, inline client-side mismatch pre-check, six flash outcomes. ### Recovery posture (operator's explicit choices) - Requires the **current** password to change it (blocks a walk-up attacker on an open session). - ConfigMap `auth.password_hash` remains the **break-glass fallback** — blank the DB row (or edit the manifest + redeploy) to reset a forgotten password. ### Tests & red-proofs (`internal/web/change_password_test.go`) - `TestEffectivePasswordHash_DBOverrideWins` — override wins; clearing falls back to the seed. - `TestChangePassword_HappyPath` — end-to-end through `handleLogin` (new works, old dead). - `TestChangePassword_WrongCurrentRejected` — security anchor: no override written. - `TestChangePassword_ValidationRejections` — mismatch / too-short / no-op refused, no override. - `TestConfigurationPage_RendersPasswordCard` — form renders through the production template. - Red-proofs verified: dropping the current-password check → WrongCurrentRejected fails; breaking the override precedence → precedence + happy-path login assertions fail. ### Gates - `go build ./... && go vet ./... && go test ./...` (hub): green. - `python scripts/hub_confirm_gate.py`: green (no native confirm/prompt in templates). ### Docs - `hub/CHANGELOG.md` (v0.54.0), `hub/README.md` (Authentication + Configuration sections), `REUSE.md` (`effectivePasswordHash`, `Get/SetOperatorPasswordHash` rows). ### Deploy Hub image built + pushed as `v0.54.0`; `manifests/hub.yaml` tag bumped; ArgoCD synced; verified live on `hub.felhom.eu`.