mirror of
https://github.com/lukaszraczylo/traefik-llmgateway.git
synced 2026-10-14 05:18:54 +00:00
Review fix round (4 Important + 2 folded): 1. Version display: OverviewView.vue was missing the muted version line the old vanilla-JS page rendered (types/api.ts already declared overview.version) - added. 2. CSP invariant now guarded twice: webui/generate.mjs's new assertNoInlineAssets fails the build if dist/index.html contains an inline <script> (no src= attribute) or any <style> tag - the exact condition the tightened admin CSP (script-src/style-src 'self', no 'unsafe-inline') depends on. admin_test.go's new TestAdminIndexHTML_NoInlineAssets re-asserts the identical invariant server-side, against the decoded adminIndexHTML admin.go actually serves, so a regression is caught even if admin_assets_gen.go were regenerated with a modified copy of generate.mjs. 3. webui/components.json's iconLibrary:"lucide"/font:"inter" fields cannot be fixed in place - checked shadcn-vue's own schema (PRESET_ICON_LIBRARIES/PRESET_FONTS in the installed package): no "none"/fontawesome/system choice exists for either, and JSON (unlike the tsconfig.*.json files touched in the previous commit) has no comment syntax to warn inline. Documented instead: webui/README.md gained a loud warning section naming the exact regression (already hit twice this branch - a re-added Google Fonts import, a re-added lucide icon import) and the two-step fix to apply after any future shadcn-vue add/init call. 4. Real-CSP verification: the browser pass earlier in this branch ran under vite preview, which sends no CSP header at all. New integration/integration_test.go: TestAdminAssetCSP fetches GET /admin against the real Traefik+Yaegi pipeline, extracts the asset URL from its <script src="..."> tag, fetches that asset, and asserts both responses carry the exact adminCSP string byte-for-byte. admin.go's serveAdminAsset now also sets Content-Security-Policy (previously JSON/page routes only) so this holds for a direct navigation to an asset URL, not just as a same-origin sub-resource of GET /admin; admin_test.go's TestAdminAsset_Serving updated to match. 5. (folded) UsageChart.vue stacked the "tokens" tab's two series (tokin/tokout - two separate HTTP requests, not one atomic call) by positional index. A window rollover landing between the two requests could leave one series one bucket ahead, mis-stacking that refresh. Now aligns both series by their bucket key (a sorted union of every active series' buckets - the fixed-width, zero-padded bucket strings sort chronologically by construction), with a missing bucket in one series reading as 0 rather than shifting the whole series. 6. (folded) AuthGate.vue now triggers an immediate dashboard.refresh() on successful key submit, instead of waiting up to 5s for the next poll tick - the dashboard no longer sits blank right after auth. Rebuilt via make admin-ui; admin_assets_gen.go regenerated.
71 lines
3.5 KiB
Markdown
71 lines
3.5 KiB
Markdown
# Admin panel (webui)
|
|
|
|
Source for the traefik-llmgateway read-only admin dashboard: Vue 3 +
|
|
TypeScript + Pinia + Tailwind v4 + shadcn-vue + Chart.js, built with Vite.
|
|
|
|
See the repo root [README.md's Admin section](../README.md#admin) for what
|
|
the dashboard shows and how its API/auth works, and the
|
|
[Development section](../README.md#development) for `make admin-ui` — the
|
|
only way this directory's output (`../admin_assets_gen.go`) is meant to be
|
|
regenerated. Nothing here runs at request time: the plugin serves the
|
|
built, baked-in output, never `webui/` itself.
|
|
|
|
## Warning: `shadcn-vue add`/`init` regressions
|
|
|
|
`components.json`'s `iconLibrary` and `font` fields are locked to
|
|
`"lucide"` and `"inter"` — **not this project's real choices** (this
|
|
project uses FontAwesome only, per `vue-web-development` house skill, and
|
|
no external font at all). The shadcn-vue CLI's schema does not accept
|
|
`"none"`/`"fontawesome"`/`"system"` for either field (checked directly:
|
|
`node_modules/shadcn-vue/dist/preset-*.js`'s `PRESET_ICON_LIBRARIES` and
|
|
`PRESET_FONTS` arrays — five fixed choices each, no escape hatch), and
|
|
JSON supports no comment syntax to warn inline (the repo's own
|
|
pre-commit JSON validator rejects JSONC comments — see `tsconfig.*.json`
|
|
history). This warning is the only place the trap could be recorded.
|
|
|
|
Both `npx shadcn-vue init` and `npx shadcn-vue add <component>` read
|
|
these fields and **silently rewrite `src/assets/main.css`** — hit twice
|
|
in this project's own history: `init` first, then a follow-up `add`
|
|
call, both re-added a `@import url('https://fonts.googleapis.com/...')`
|
|
line and switched the dark-mode `@custom-variant` back to a `.dark`-class
|
|
toggle. If you ever run either command again:
|
|
|
|
1. **Diff `src/assets/main.css` before committing.** Remove any
|
|
re-added `@import url('https://fonts.googleapis...')` line (external
|
|
font, blocked by the admin CSP's `style-src 'self'` anyway) and
|
|
restore the `@custom-variant dark` removal (see the file's own header
|
|
comment for why: `prefers-color-scheme`, not a class toggle).
|
|
2. **Check the new component for a `lucide-vue-next`/`@lucide/vue`
|
|
import** and swap it for the FontAwesome equivalent (see
|
|
`src/components/ui/select/Select*.vue` for the pattern already
|
|
applied there).
|
|
|
|
## Local development
|
|
|
|
```sh
|
|
npm ci
|
|
npm run dev # Vite dev server — /admin/api/* calls need a real
|
|
# gateway to fetch from; point one at the same origin or
|
|
# accept the "refresh failed" state while iterating on
|
|
# layout/styling alone.
|
|
npm run build # what `make admin-ui` runs, plus webui/generate.mjs
|
|
```
|
|
|
|
## Structure
|
|
|
|
- `src/stores/` — Pinia: `auth` (the sessionStorage key gate), `dashboard`
|
|
(Overview/Usage, 5s poll), `history` (Charts, fetch-on-selection + 30s
|
|
refresh).
|
|
- `src/components/` — `AuthGate`, `OverviewView`, `UsageView`,
|
|
`ChartsView`/`UsageChart`, `UsageTable`; `ui/` holds the shadcn-vue
|
|
primitives this panel actually uses (Card, Table, Tabs, Button, Input,
|
|
Alert, Select, Badge) — nothing installed and unused.
|
|
- `src/lib/` — `api.ts` (the `/admin/api/*` fetch wrapper), `format.ts`,
|
|
`key-storage.ts`, `chart-setup.ts`.
|
|
- `src/types/api.ts` — TypeScript mirrors of admin.go's JSON response
|
|
shapes (`adminOverviewResponse`, `adminUsageResponse`,
|
|
`usageHistoryResponse`).
|
|
- `generate.mjs` — reads `dist/` after `vite build` and writes
|
|
`../admin_assets_gen.go`; see its own header comment for why every
|
|
asset is base64-encoded rather than embedded as a raw string literal.
|