Commit Graph

15 Commits

Author SHA1 Message Date
admin 36c72138f1 hub: dead-host roll-up honesty - customer status folds worst expected host
Customer status (dashboard row, /configs list, detail header + strip) is
now worst(controllerDerived, hostStatusOf(each expected host)) via the ONE
staleness definition (Server.hostStatus, hosts.go - shared with the
HostStalenessChecker; no second threshold). Any host down/stale caps the
customer at WARN with a cause chip naming the host ("host down: <id>");
pending (never-reported) hosts worsen only once the customer has reported
(onboarding exclusion). The three previously-inlined controller-status
chains collapse into controllerStatus() (rollup.go). Display + derivation
only - checker alerting untouched.

Live shape pinned (drill-1 / Peti cluster): host down 23h + controller
report minutes old rendered a GREEN row - TestRollup_DeadHostMasking now
fails that exact outcome. Red-proof: short-circuiting foldHostStatus to
controller-only flips C + two D subtests red ("dashboard row is GREEN
over a 23h-dead host").
2026-07-13 14:52:04 +02:00
admin 1d94b1a9e9 hub: scoped auto-refresh + style.css cache-bust + staging rule (v0.48.0 parts 3-4)
- Auto-refresh: the 60s reload fires only while a live tab is active
  (nav data-live-tabs="overview,applications,events,host") AND no form is
  dirty (delegated 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, localStorage key, 60s cadence, and
  default-on behavior unchanged. The refresh script resolves the legacy
  settings→edit hash alias like the tabs script.
- Rider 4a: every template's stylesheet link is /style.css?v={{hubVersion}}
  (the v0.47.0 gotcha: max-age=3600 served stale styling for up to an hour
  after a deploy). Red-proof run: a reverted bare link fails the test.
- Rider 4b: CLAUDE.md standing rule — never git add -A in this repo
  (the 146d165 sweep incident); explicit paths + pull-rebase + one writing
  session per clone.
- Tests: Group C structural pins (attribute read, dirty listeners, alias x2,
  hint element, cadence/key survivors) + Group D cache-bust over six pages.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TZc5w5jDhFLv6qDC32KN5v
2026-07-12 17:37:04 +02:00
admin 13203c2452 hub: S2 /offsite registry page (read-only) + nav + WGPeer.CreatedAt
Endpoint card + peers table (truncated pubkeys with full-value title attr,
bound peers link to /hosts/<id>); Offsite nav link in all 9 page templates;
render tests for endpoint/peers, empty, and not-configured states.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
2026-07-04 00:48:03 +02:00
admin c136308aad D4 Part 2: hub style.css v2 + template sweep
- style.css: slate tokens -> the canonical navy block + @font-face
  (self-hosted, latin-ext for Hungarian customer names); single 2px
  radius; hairline table rows (--line-soft dividers, density kept);
  status classes re-expressed per the design-system addendum:
  .status-badge = outline tag + CSS ::before dot keyed by the raw
  status the templates emit (ok=blue, warn/blocked/stale=amber,
  down/fail=red, pending/disabled=quiet neutral); .status-dot =
  class-based 8px dot; severity badges stay filled amber/red
  (exceptions stay loud); config badges = filled informational chips
  in v2 colors; row tint only for warn/down (warn-dim/crit-dim).
- Two-tone brand heading on all 8 'Felhom Hub' pages
  (<h1>Felhom <span>Hub</span></h1>, span = blue-bright).
- app_detail chart retinted: avg #2EA8F5 (primary data), peak #8E7CE8
  (secondary DATA series — not status red), catalog-limit line #E0A93E
  (threshold marker); legend/tick/grid -> v2 literals.
- customer_unified: JS status-message colors (success -> blue-bright,
  error -> crit), all inline slate hexes -> tokens.
- Login page inline HTML retinted (#0088cc -> #0083D8).
- Grep gate: every slate hex (#0f172a #1e293b #334155 #60a5fa #4ade80
  #facc15 #f87171 #94a3b8 #64748b #475569 #e2e8f0) at ZERO across
  hub/internal/web (non-test); statusIcon 0; inline statusColor
  style 0. go build/vet/test green; api/ + store/ untouched.
2026-07-02 22:38:37 +02:00
admin bc8d54df6a D4 Part 1: hub fonts + sprite + statusColor semantic remap
- static/fonts/: the 4 vendored woff2 (byte-copied from
  felhom-controller), embedded (embed.go) and served at /static/fonts/
  (font/woff2, immutable) mirroring the chart.min.js pattern. No CDN
  before, none now.
- templates/icons.html: 12-symbol Lucide sprite partial (icon_sprite),
  included at the top of <body> on all 9 pages ({{template}} — the hub
  has no shared layout; per-page include is the minimal shared block).
- statusColor now returns v2 semantic tokens (nominal/warn/crit/
  neutral) consumed as class suffixes: ok->nominal, warn+stale->warn,
  down+fail->crit, pending+disabled->neutral (a not-yet-provisioned or
  deliberately paused customer is a normal fleet state), blocked->warn
  (intentional operator cut-off, attention-worthy not an outage),
  unknown->neutral. The inline style="color: {{statusColor}}" pattern
  is dead: dashboard + customer_unified render a class-based
  .status-dot-<token>; statusIcon (constant "●") retired from funcmap
  and templates.
- Tests (new; the hub web package had no funcmap/template tests):
  TestStatusColorTruthTable over the full enumerated status set —
  red-proven vs the old implementation (ok returned "#4ade80") — and
  TestTemplatesParseWithFuncmap.
2026-07-02 22:34:40 +02:00
admin 562c0dfeb6 hub v0.28.0 + host-install v1.2.0: settings→Configuration, online install, vmid auto-detect
Part A (hub): move the global-floor + Day-0-artifacts cards from the Customers
page to the Configuration tab; routes → /configuration/{global-floor,artifacts};
redirects + flashes to /configuration. Customers page back to list + Add.

Part B: online setup command on the customer page (download-then-run, passphrase
at prompt, not templated); serve /scripts/ from the website (sparse-checkout +
nginx location) so felhom.eu/scripts/felhom-host-install.sh resolves; script
passphrase prompt reads < /dev/tty (works for pipe-to-bash too).

Part C (script): --vmid auto-detect — default 9201 in use + no --force → pick the
next free id from pct+qm and confirm; explicit --vmid stays die-unless-force.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 06:43:29 +02:00
admin 2289fc907c hub v0.27.0: Hosts page — read-only fleet view (audit F-M1)
New Hosts nav section: a fleet list (/hosts) + per-host detail (/hosts/{id}),
read-only (GET only, no host actions). Surfaces identity, agent version,
online/stale status (reusing the HostStalenessChecker threshold), guests,
vitals, storage targets with SMART/thin-pool, and DR/escrow presence.

- store: new ListGuestsForHost reader (reality cols only; omits api_key/
  desired_spec_json) + scanGuest helper.
- web: handleHostsList + handleHostDetail (hosts.go); hosts.html +
  host_detail.html; Hosts nav link on every page; timeAgoPtr helper; routes.
- tests: store getter, both handlers, no-secret (api_key) assertion, 404,
  no-report empty state, status-band mapping.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 06:10:02 +02:00
admin 39ef64e128 hub v0.16.0 + host-install v1.1.0: Day-0 artifact manifest + self-install the agent (BUNDLE slice)
Hub (v0.16.0):
- store: ArtifactManifest{agent,golden version+sha256} in hub_settings; Get/SetArtifactManifest.
- handler: GET /api/v1/artifacts/{id} (passphrase auth, mirrors config-retrieve). Unset => 200 empty.
- web: operator UI "Day-0 artifacts" card (POST /configs/artifacts), semver + 64-hex validation.
- artifact_test.go: returned-verbatim / unset-empty / 401 / 404 / store round-trip.

host-install (v1.1.0):
- new step 5/8 agent-install: manifest + git token (config-retrieve) -> fetch binary from Gitea ->
  verify sha256 vs hub manifest (abort on mismatch) -> install non-root felhom-agent user + binary +
  sudoers (visudo -cf) + canonical unit. Idempotent.
- new step 7/8 golden: local fallback else fetch+verify+import from Gitea (--force-gitea-golden).
- agent now runs non-root (privileged.mode sudo), config chowned to the service user.
- README prerequisites trimmed to: install PVE + create customer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 08:38:26 +02:00
admin 30380a59f4 hub v0.15.0: Phase 2 managed updates — per-customer controller-version floor
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
2026-06-27 11:59:30 +02:00
admin 1e354cbd41 feat(hub): Configuration page, asset seedOrUpdate, English UI
- Add Configuration page with "Refresh Assets" button
- Replace seedIfEmpty with seedOrUpdate (SHA-256 compare on startup)
- Translate all Hungarian text on Apps pages to English
- Add Configuration tab to all template navigation
- Expand isAssetFile to match favicon patterns
- Add felhom-logo.svg to website assets for the pipeline

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:34:43 +01:00
admin a757bee07a feat(hub): app telemetry analytics dashboard (v0.4.0)
- store/telemetry.go: new app_telemetry + app_log_issues tables with
  SaveAppTelemetry, GetFleetAppSummary (with P95), GetAppTelemetryHistory,
  GetAppCustomerBreakdown, GetCustomerAppSummary, GetAppIssues, prune methods
- api/handler.go: parse and save optional app_telemetry from report body,
  backward-compatible with old controllers
- cmd/hub/main.go: prune app_telemetry (90d) and stale issues (30d)
- web/apps.go: handleApps + handleAppDetail + chart data aggregation helpers
- web/server.go: routes for /apps, /apps/{name}, /static/chart.min.js;
  added memoryColor/accuracyClass/gt template functions
- web/embed.go: embed static/chart.min.js
- web/configs.go: add app telemetry section to handleCustomerUnified
- templates/apps.html: fleet-wide app list with summary cards and sortable table
- templates/app_detail.html: per-app page with Chart.js memory trend,
  customer breakdown, and known issues table
- templates/customer_unified.html: new Alkalmazás telemetria card
- templates/style.css: badge, summary-card, chart, period-selector,
  accuracy-dot, mem-color, data-table styles
- All templates: added Alkalmazások nav link

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 10:46:50 +01:00
admin 6bcbaa1574 hub v0.3.2: Show Hub version in page footers
Add hubVersion template function via closure in web.New(). Version is
passed from main.go (set via ldflags at build time) and displayed in
the footer of all 6 page templates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 19:39:52 +01:00
admin 42e0617a6c hub: unified customer page, blocked status, dashboard merge
- Replace separate config detail and report detail pages with unified
  /customers/{id} page showing both config info and live report data
- Add "blocked" status for customers (hidden from dashboard, notifications
  suppressed, still accepts reports)
- Dashboard now shows config-only customers as "PENDING" status
- Customers list: all rows link to /customers/{id}, show BLOCKED badge
- New actions: block/unblock, push config to controller, auto-create
  config from report data
- /configs/{id} now redirects to /customers/{id}
- Add config-badge CSS classes for MANAGED/MANUAL/BLOCKED badges

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:57:39 +01:00
admin cb425d8086 feat: merge report-only customers into Customers page, rename tab
- Customers page now shows ALL customers: both pre-configured (managed)
  and report-only (manual) — merged from customer_configs + reports tables
- Renamed "Configurations" → "Customers" in navigation tabs
- Renamed "+ New Configuration" → "+ Add Customer"
- Status column with ok/warn/down badges, version column, managed/manual badge

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:27:05 +01:00
admin 4c8bf63ce3 feat: customer config management — CRUD, API retrieval, per-customer auth (v0.2.0)
New "Configurations" section lets operators pre-configure customer settings
in the Hub, then docker-setup.sh can download a ready-made controller.yaml
using just a customer ID and retrieval password.

- Store: customer_configs table with CRUD + per-customer API key lookup
- API: GET /api/v1/config/{id} with X-Retrieval-Password auth
- Auth: per-customer API keys alongside existing global key (backward compatible)
- Web UI: /configs list, create, edit, delete, YAML preview, copy-to-clipboard
- YAML gen: deep-merge controller.yaml.example template with customer overrides
- Template fetcher: background goroutine refreshing template from Gitea repo
- Navigation: Dashboard / Configurations tabs on all pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:36:32 +01:00