docs+manifest: hub v0.49.0 — Edit tab merge train (CHANGELOG, REUSE rows, CONTEXT, GitOps bump)

Version note: the task spec targeted 0.48.0 but that tag had already shipped
(app_start_failed); published tags are never re-pointed → this train is 0.49.0.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TZc5w5jDhFLv6qDC32KN5v
This commit is contained in:
2026-07-12 17:39:09 +02:00
parent 1d94b1a9e9
commit b1ab0ea0e5
4 changed files with 58 additions and 1 deletions
+15
View File
@@ -3,6 +3,21 @@
> Created with the REUSE.md rollout (2026-07-03). Authoritative history: `hub/CHANGELOG.md` (hub),
> `website/CHANGELOG.md`, `scripts/CHANGELOG.md`; end-of-task detail in `REPORT.md`.
- **2026-07-12 — HUB v0.49.0 SHIPPED: Edit tab merge (edit-a) + scoped auto-refresh + riders**
(CHANGELOG v0.49.0; commits `e740147``2e03de1``1d94b1a` + docs/manifest). The standalone
customer edit page merged into the customer page's **Edit** tab (renamed from Settings): shared
`config_form_body` sub-template + `configFormData` builder (REUSE.md rows added), Block/Delete
relocated to a danger-zone card, header cleaned, `GET /configs/{id}/edit` → 302 `#tab=edit`,
post-action redirects anchored to their tab, `settings→edit` legacy-hash alias. Update handler
gained server-side required-field validation (error path preserves SUBMITTED values —
red-proofed). The 60s auto-refresh is now scoped: fires only on live tabs
(`data-live-tabs="overview,applications,events,host"`) and never while a form is dirty; muted
`(paused)` hint. Riders: `/style.css?v={{hubVersion}}` cache-bust on every template (closes the
v0.47.0 max-age=3600 gotcha) + the CLAUDE.md `git add -A` ban codified. **NOTE: the task spec
said v0.48.0, but v0.48.0 (app_start_failed) had already shipped — published tags are never
re-pointed, so this train is v0.49.0.** Out of scope (observed, not done): type-to-confirm for
customer delete (still `confirm()`, relocated as-is); the workspace-root `E:\git\CLAUDE.md` and
other repos' CLAUDE.md files still carry `git add -A` snippets — flag for their own sessions.
- **2026-07-12 — Day-0 VM DRILL COMPLETE (auto-confirm FIRST LIVE FIRING): full arc proven on a
fresh nested-PVE box** — appliance Day-0 → floor-at-first-report → ceremony → **auto-confirm
pending→escrowed in ~7.5 min, zero clicks** → offsite backup + restore round-trip. Two HIGH gaps:
+2
View File
@@ -62,6 +62,8 @@
| `(*Server).hostDetailData` | hub/internal/web/hosts.go (~L282) | `(host *store.Host, r) map[string]interface{}` | The ONE view-model builder for the shared `host_detail_body` sub-template (standalone `/hosts/{id}` + customer Host tab) | Booleans/counts only for DR/escrow; carries `Deletable` (= status != "ok") which gates the danger-zone card. Never add a secret field. |
| `host_detail_body` sub-template | hub/internal/web/templates/host_detail_body.html | `{{template "host_detail_body" .}}` | Rendering a host's detail sections on ANY surface | One namespace across ParseFS (icons.html pattern). Renders per-host — id-suffix any new element ids with `{{.HostID}}` (the customer page renders N instances). |
| `(*Store).ListHostsByCustomer` | hub/internal/store/store.go (~L1620) | `(customerID) ([]Host, error)` | A customer's hosts, host_id order | A LIST by design (HA-cluster roadmap) — don't collapse to GetHostByCustomer. |
| `(*Server).configFormData` (v0.49.0) | hub/internal/web/configs.go (~L430) | `(r, isNew, cfg, overrides, errMsg) configFormView` | The ONE view-model builder for the customer config form (standalone chrome + the customer page Edit tab) | `overrides=nil` → parses the STORED cfg.ConfigJSON; pass the SUBMITTED map on the update validation-error re-render or typed values reset (red-proofed). |
| `config_form_body` sub-template (v0.49.0) | hub/internal/web/templates/config_form_body.html | `{{template "config_form_body" <configFormView>}}` | Rendering the config form on ANY surface (config_form.html chrome + customer Edit tab) | The floor/geo/danger cards on the Edit tab are SIBLINGS after `</form>` — never nest a form inside it (breaks the offsite/PBS formaction sub-buttons). Includes the F5 in-flight `<script>`. |
| `(*Store).CountHostArtifacts` / `DeleteHost` | hub/internal/store/store.go (~L1640/~L1690) | `(hostID) (HostArtifacts, error)` / `(hostID, deleteEscrow bool) error` | Host-delete impact preview + the ONE-transaction cascade | ONLINE gate lives in the handler, escrow gate in the store (`ErrHostEscrowPresent`, tx never starts). log_bundles die by `scope_id == host_id` ONLY (customer-scoped bundles survive). The wg_peers delete is INSIDE the tx — never split it out. |
| `(*Store).ListWGEndpoints` / `DeleteWGEndpoint` | hub/internal/store/wg.go (~L64/~L86) | `() ([]WGEndpoint, error)` / `(endpointID) error` | The /offsite endpoint-management surface | `GetWGEndpoint` (lowest id, LIMIT 1) stays THE allocation/sync endpoint — do not switch allocator/reconciler/desired-state to the list without the `wg_peers.endpoint_id` migration arc. Peers-in-subnet guards live in web/offsite.go. |
+40
View File
@@ -1,5 +1,45 @@
# Felhom Hub — Changelog
## v0.49.0 — Edit tab merge (edit-a), scoped auto-refresh, style.css cache-bust (2026-07-12)
> The task spec targeted "v0.48.0", but v0.48.0 (app_start_failed, below) had already shipped +
> deployed by the time this train ran — a published tag is never re-pointed, so this is v0.49.0.
> Baseline `3e949bc`; commits `e740147``2e03de1``1d94b1a` → docs/manifest.
- **Edit tab merge (edit-a)** (`templates/customer_unified.html`, `templates/config_form.html`,
new `templates/config_form_body.html`, `web/configs.go`, `web/pbsdr.go`): the standalone
customer edit page merged into the customer page's Settings tab, renamed **Edit**. The form
body is a shared `{{define "config_form_body"}}` sub-template (the `host_detail_body`
pattern) built by the one `configFormData` view-model builder; the standalone chrome keeps
rendering it for the create flow (`/configs/new`) and the validation-error re-render. The
Edit tab renders: config form, Controller Update card, Geo card, and a **Danger zone** card
holding the Block/Unblock/Delete forms relocated verbatim from the Customer Info header
(endpoints + `confirm()` unchanged) — all SIBLINGS after `</form>` (nested forms are invalid
HTML and would break the offsite/PBS `formaction` sub-buttons). The header keeps only the
config-less Create Config action. `GET /configs/{id}/edit` → 302 `/customers/{id}#tab=edit`;
tabs JS gains the `settings``edit` legacy-hash alias.
- **Server-side required fields on update** (`web/configs.go` `handleConfigUpdate`): the twin
of the form's `required` attributes (Display Name + Domain), checked BEFORE provisioning; the
error path re-renders the standalone page with the SUBMITTED overrides so typed values are
never lost (red-proofed: nil overrides → values reset → test fails).
- **Redirect anchors**: update/block/unblock/offsite-reissue/offsite-freeze/pbsdr-reissue →
`?flash=…#tab=edit`; regen-password → `#tab=setup` (its card lives there); delete unchanged
(`/configs?flash=deleted`).
- **Scoped auto-refresh** (`templates/customer_unified.html`): the 60s reload fires only while
a live tab (`data-live-tabs="overview,applications,events,host"` on the nav) is active AND no
form is dirty (delegated document-level input/change listener, never reset — a reload clears
it). Skipped ticks reschedule; a muted `(paused)` hint shows next to the toggle on non-live
tabs / dirty forms. Toggle, `hub_auto_refresh` localStorage key, cadence, default-on: unchanged.
- **style.css cache-bust** (all `templates/*.html`): every stylesheet link is now
`/style.css?v={{hubVersion}}` — closes the v0.47.0 gotcha (`max-age=3600` served stale
styling for up to an hour after each deploy). Red-proofed (bare link fails the render test).
- **Repo staging rule** (`CLAUDE.md`): never `git add -A` in this repo (the v0.47.0 `146d165`
sweep incident) — explicit paths, pull-rebase, one writing session per clone.
- Tests: +11 (Group A panel surface / sibling-form / header-count, Group B redirect + create +
typed-values-preservation table, Group C refresh structural pins, Group D cache-bust sweep).
Amended pins: `customer_tabs_test.go` (settings→edit), `pbsdr_test.go` (postUpdate supplies
the now-required fields; FormRendersState asserts the embedded Edit-tab render).
## v0.48.0 — accept the app_start_failed event (controller fix-3, CAMPAIGN-3) (2026-07-12)
- `app_start_failed` added to `allowedEventTypes` (`internal/api/handler.go`) + `customerMessages`
+1 -1
View File
@@ -126,7 +126,7 @@ spec:
spec:
containers:
- name: hub
image: gitea.dooplex.hu/admin/felhom-hub:0.48.0
image: gitea.dooplex.hu/admin/felhom-hub:0.49.0
ports:
- containerPort: 8080
name: http