# Felhom Hub — Changelog ## v0.28.0 — global settings → Configuration tab + online setup command (2026-07-01) Three operator-requested improvements (companion: host-install script v1.2.0). - **Global settings moved from the Customers page to the Configuration tab** (`web/configuration.html`, `configs.html`, `server.go`, `configs.go`). The two **global** cards — "Managed updates — global floor" and "Day-0 artifacts — agent & golden" — were on the Customers list; they now render + save on Configuration (where they belong). `handleConfiguration` supplies `GlobalFloor` + `Artifacts` + `CSRFField`; the save handlers (`handleSetGlobalFloor`/`handleSetArtifacts`) now redirect to `/configuration?flash=…` and are mounted at `/configuration/global-floor` + `/configuration/artifacts`; their flash banners moved too. The Customers page is back to just the list + "Add Customer" (its per-customer effective-floor column is unchanged). - **Online setup command added** to a customer's Setup Command block (`customer_unified.html`). New **"Option 1: Online install (recommended)"** — download-then-run: `curl -fsSL https://felhom.eu/scripts/felhom-host-install.sh -o … && sudo bash … --customer-id ` — with a copy button and the customer id filled. The passphrase is **not** templated in (entered at the prompt). The former local-file command becomes Option 2, the debug curl Option 3. Download-then-run (not `curl | sudo bash`) stays the recommended form — inspect before running. - **Website now serves `/scripts/`** (`manifests/webpage.yaml`). The host-install script lives at the repo's `/scripts` (outside the website doc-root); added `/scripts/` to the git-sync sparse-checkout and an nginx `location /scripts/` (root `.../current`, `text/plain`) so `https://felhom.eu/scripts/felhom-host-install.sh` resolves — single source of truth, no duplicated copy. - **Remaining audit follow-ups unchanged:** controller-side geo intent sync; a read-only reported-vs-desired "Show Diff"; the cosmetic `controllerURL` cleanup in `configs.go`. ## v0.27.0 — Hosts page: read-only fleet view (audit F-M1) (2026-07-01) Resolves audit finding **F-M1**: the agent enrolls as a *host* and the hub stores rich host state (identity, agent version, guests, storage targets with SMART, DR/escrow, staleness) and alerts on it — but the whole host domain was **invisible in the GUI** (email-only). Adds a **Hosts** nav section — a fleet list + a per-host detail page. **Read-only** (GET only, no host actions/mutation routes): this surfaces state the way the pull/desired-state model demands; it does not reintroduce inbound control (retired in v0.26.0). - **New store reader `ListGuestsForHost(hostID)` (`internal/store/store.go`).** `SELECT … FROM guests WHERE host_id = ? ORDER BY vmid`, via a new `scanGuest` helper over `guestRealitySelectCols` — the reality columns only. It deliberately **omits the secret/inert columns** (`api_key`, `desired_spec_json`), so the read-only view can never surface them. Returns `[]` (never nil-error) on no guests. (There was previously no guests *reader* — only `UpsertGuestFromReport`.) - **New handlers (`internal/web/hosts.go`).** - `handleHostsList` — `ListHosts` + a per-host status badge from `hostStatus()` (which reuses `s.staleThreshold` — the **same** thresholds as the `HostStalenessChecker`: stale after the threshold, down at 2× — so the badge agrees with the alerting) + per-host guest counts (`ListGuestsForHost`) + vitals parsed from `GetLatestHostReportJSON` + worst storage fill grouped from `GetHostStorageTargets`. - `handleHostDetail` — `GetHost` (404 if absent) + `ListGuestsForHost` + rich storage targets (role, state, fill %, thin-pool, SMART health/temp/wear parsed from the latest report body) + vitals + `GetHostDRBundle`/`GetHostEscrow` **presence booleans only** (never the opaque blobs). Nil/missing (no report, no guests, no storage, no DR) render empty states — never a panic. - **New templates `hosts.html` + `host_detail.html`** (existing dark operator-console styling reused — `data-table`, `status-badge-*`, `info-grid`, `empty-state`; no restyle). A no-report host shows a STALE/NO-REPORT badge and "waiting for first report". - **Nav:** added the `Hosts` link (between Apps and Configuration) to every page's `