feat(webui): redesign the admin dashboard around admin tasks

A sidebar replaces the flat tabs with seven pages, and one filter bar
sets the time range, comparison period and scope for all of them.

- Home: spend against budget, forecast, request rate, error rate,
  open breakers, top users and models, recent events and warnings.
- Spend: spend over time with comparison, budget burn-down, an
  attribution drill-down from group to user to model, pricing health
  and cost avoided by free models.
- Consumers: a directory with last seen and limit bars, an access
  matrix, and a detail page per user.
- Models: the catalog with billing prices, fleet latency and error
  rates, and provider health.
- Reliability: error, timeout, failover, 429 and 402 trends, events,
  and latency per provider.
- Config: the redacted config and a change helper that emits YAML or
  users.json snippets to paste into git.
- MCP & Agents: callers per target.

Page state lives in the URL hash, and old tab links map to the new
pages. The replaced views are removed. admin_assets_gen.go is
regenerated.

Claude-Session: https://claude.ai/code/session_01V5jYJNxpDFdJkyyExpADrv
This commit is contained in:
2026-09-23 16:41:01 +01:00
parent e8abb91dc8
commit ee49467e64
127 changed files with 11226 additions and 3414 deletions
+2 -2
View File
@@ -43,8 +43,8 @@ const props = defineProps<{
* default) keeps every existing call site's original UNCONTROLLED
* behavior unchanged — this component owns `internalSorting` itself and
* a caller has no way to read the current sort. Passed, a caller (e.g.
* UsageView.vue's Users export, which needs to export rows in the
* table's own current sort order — the plan's own "exports
* ConsumerDirectory.vue's Users export, which needs to export rows in
* the table's own current sort order — the plan's own "exports
* filtered+sorted rows" requirement) instead owns the ref: every header
* click emits `update:sorting` with the new state rather than mutating
* anything locally here.