0.4.0

OAP becomes the runtime source of truth for UI templates, the 5-theme system lands, and the app supports being served behind a gateway prefix.

Templates synced to OAP

  • Five reserved template families now live on OAP’s UI-template REST surface (/ui-management/templates* on the admin port): overview dashboards, per-layer dashboards, alert page setup, theme selection, time-defaults. Bundled JSON ships as the seed + read-only fallback.
  • One-shot seed on BFF boot pushes any missing bundled template to OAP; runtime sync is read-only with a 30-second single-flight cache.
  • New admin endpoints: GET /api/admin/templates/sync-status, POST /api/admin/templates/save, POST /api/admin/templates/resync, POST /api/admin/templates/:name/push-bundled.
  • When the admin port is unreachable, every admin page goes read-only with a red banner; Save / Create / Delete are disabled; render falls back to bundled.
  • Diverged rows surface a “Show diff & reset” Monaco modal with a destructive-confirm (type the template key to arm reset).

Themes

  • Five bundled themes — Horizon (default), Meridian, Obsidian, Daybreak, Aurora — each shipping a complete token set (bg, fg, accent, info/ok/warn/err, font, radius, density).
  • New /admin/global-defaults admin page replaces the old “Setup” link. Theme picker uses preview cards lifted from the design (hero strip, mini-app mockup with Primary/Tonal/Ghost buttons, KPI tiles, sparkline, density/font/radius badges).
  • Per-user theme override via a labelled topbar chip — three-tier resolution localStorage user → OAP org default → bundled, written to <html data-theme> / <html data-appearance> synchronously on boot so the pre-auth login page already respects the local override.
  • Sidebar SkyWalking logo swaps to the official brand blue (#1368B3) on light-appearance themes.
  • Widget series colors (Zipkin trace palette, AlarmSnapshotChart, AlarmsTimeline) track the active theme’s --sw-accent via a shared readAccent() util.
  • Sign-in button gradient derives both stops from the theme accent.

Time defaults

  • /admin/global-defaults also owns the global picker’s default window (60 minutes shipped). OAP step precision is derived from window size — ≤ 4 h MINUTE, 6 h–14 d HOUR, ≥ 30 d DAY — and surfaced inline on the page.
  • Per-user override in the topbar time picker: “Save as my default” / “Reset to org default”.

Reliability + diagnostics

  • Topology cluster boundary now grows to encompass dragged nodes; the chip moved inside the cluster header so it stays visible at any drag position.
  • Alarms page gains an Other KPI tile that surfaces the residual count between Active and the sum of pinned-layer chips — Active = General + Mesh + Other reconciles even when alarms land in unmapped layers.
  • Overview “Active alarms” widget now reads the admin’s configured defaultWindowMs from /admin/alert-page-setup; all three alarm surfaces (overview widget, alarms page, topbar badge) share one window.
  • Every backend call failure (network throw or non-2xx) writes a pushEvent('api', 'err', …) into the debug event log with the BFF’s code / message envelope inlined when present.
  • Dashboards with more than 40 widgets (e.g. the General/instance page, 56 widgets) now succeed: the UI splits oversize requests into ≤40-widget chunks fired in parallel, then merges results.

Deployment

  • Gateway-prefix support: BffClient.request() prepends import.meta.env.BASE_URL to every API path. Build with vite build --base=/horizon/ and a gateway that strips the prefix and the SPA + every API call resolves cleanly under the sub-path.
  • Cluster Status route corrected from /admin/cluster/operate/cluster (the prior default 404’d because no route by that name existed).

Cleanup

  • Documentation rewritten as an orientation map; the left-side menu is the canonical navigation now. All SWIP-* references removed from user-visible text and docs.
  • “Coming in Phase 6 / 7” placeholder strip on Cluster Status removed.
  • Dead code dropped — LandingView.vue, LayerTabPlaceholder.vue, the orphaned disk-write template routes (POST /api/admin/overview-templates/:id + POST /api/admin/layer-templates/:key), and stale Phase X markers across BFF + UI + docs.
  • The OAP UTC-offset chip is gone from the topbar; the health dot stays.