Admin Portal#87
Merged
arnaugiralt merged 42 commits intomasterfrom Apr 30, 2026
Merged
Conversation
- Entry point with YAML config, --config flag, and env var overrides - SQLite store with migration framework (instances, users, audit_log, sessions) - HTTP server with security headers (CSP, X-Frame-Options, etc.) - SPA handler with embed.FS for single-binary distribution - Makefile targets: build-admin, run-admin, build-admin-dev
- Vue 3 + Vite + Pinia + Vue Router with Vite proxy to Go backend - Design system: CSS custom properties, BaseButton, BaseCard, BaseInput, StatusIndicator, BaseEmptyState - App shell with sidebar nav, Fleet Dashboard and Audit Log routes - WCAG AA contrast, keyboard focus styles, aria attributes - Vitest + jsdom configured for testing
- Lint (Go + ESLint), test (Go + Vitest), build (Go + Vite) - Path-scoped triggers on admin/** changes only
RetentionDays as int made it impossible to set retention_days: 0 (keep forever) in YAML — the zero value was indistinguishable from omission and silently became 90. Change to *int so nil means unset (gets default 90) while &0 means explicitly keep forever. Add regression test.
- Fix gofmt import ordering in main.go (errors before flag) - Add context.Context to store.Open and migrate for noctx compliance - Use ExecContext/QueryRowContext/BeginTx throughout store package - Extract parseDuration helper to reduce applyEnvOverrides complexity - Split migrate into ensureMigrationsTable/currentSchemaVersion/applyMigration - Add justifying comment to blank sqlite driver import - Extract default config constants to eliminate goconst violations
- CI: use --version instead of --help || true for binary verification - BaseInput: add aria-invalid and aria-describedby for screen readers
Add #nosec G304 annotation to admin config loader (path from trusted sources: CLI flag, env var, or hardcoded default). Explicitly discard db.Close() errors on cleanup paths in store.Open() to satisfy G104 (CWE-703).
Instance CRUD API (POST/GET/PUT/DELETE /api/instances) with SQLite store, background health poller with three-state machine (unknown → healthy → unreachable after 3 failures, instant recovery), test-connection endpoint, and Vue frontend with Pinia store, AddInstanceModal, InstanceCard/Table with density toggle, and staleness detection.
Replace minimal empty state with a guided welcome screen (portal description + 3-step onboarding flow). Replace window.confirm() with a ConfirmDialog component for instance removal. Add ghost button variant for the Remove action.
Validate addresses as strict host:port (rejects :9090, host:abc, host:0). Cap JSON request bodies at 1 MB. Fix poller failures map leak for deleted instances. Make Probe() accept *http.Client to avoid per-call allocation. Extract shared formatTime, isInstanceStale, STALE_THRESHOLD_MS to utils/instance.js with tests. Fix stale-status inconsistency between table and card views.
Extract component logic into pure functions (validation, formatting, filtering), composables (useInstanceForm, usePolling, useConfirmDialog), and a thin API client so all meaningful frontend logic is testable without vue-test-utils. 65 tests across 7 files.
Fix 12 lint issues (funlen, rangeValCopy, httpNoBody, gosec, govet shadow, revive var-naming, unparam) across Go sources. Add gosec G706 exclusion for admin module matching core. Switch Prettier to single quotes and reformat UI sources.
Parse Prometheus text format from proxy /metrics endpoints using expfmt, store snapshots in per-instance ring buffers (~1h retention at 10s intervals), compute per-second rates from counter deltas (handling resets), compute p50/p95/p99 from histogram buckets via linear interpolation, and expose results via REST API (GET /api/metrics/{id}, GET /api/metrics/fleet).
New admin/metrics package: parser, ring buffer, rate/percentile math, and Collector orchestrator. Poller extended to scrape /metrics on successful health probes. Fleet endpoint aggregates KPIs across instances with trend indicators vs 1h ago.
…l, and vendor charts - Add ECharts + vue-echarts with tree-shaken imports (line chart, grid, tooltip, legend, data zoom) - Add metrics formatting utilities (formatRps, formatLatency, formatErrorRate, formatCount, trendDirection) with 25 tests - Add metrics Pinia store for fleet and instance metrics with 6 tests - Add FleetKpiPanel with 4 KPI cards (RPS, error rate, connections, panics) and trend indicators - Add instance detail view at /instances/:id with breadcrumb, status header, and Overview/Traffic tabs - Overview tab: 5 KPI cards + P50/P95/P99 latency time-series chart - Traffic tab: interactive vendor table with checkboxes, color dots, totals row; 3 stacked charts (RPS, Latency, Error Rate) per selected vendor - Latency chart shows P50/P95/P99 for single vendor, P99-only for multiple (per design spec) - Auto-select top 3 vendors by RPS, prune stale selections when vendor list changes - Make instance cards and table rows clickable to navigate to detail view - Add P50/P95 fields to SeriesPoint in Go backend for overview latency chart - Escape HTML in ECharts tooltip formatters to prevent XSS via vendor IDs - Add tabpanel ARIA roles for accessibility
Add useAnimatedValue composable that transitions numeric values over 400ms using requestAnimationFrame with ease-out cubic easing. Applied to fleet and instance KPI cards so values animate smoothly instead of jumping on each 10s poll cycle.
Bcrypt password hashing, session cookies (24h TTL / 2h idle), CSRF double-submit cookie, IP-based login rate limiting, and CLI subcommands for user creation and password reset.
…gement Wire the Go auth backend into the Vue frontend: login page, password change settings, navigation guards, CSRF token injection, and 401 session-expiry interceptor.
- Avoid swallowing DeleteSession errors - Discarded CreateUser errors in tests - Rename Token to TokenHash struct field - Added comment about clientIP assumptions - Fix rate limiter unbounded memory by adding a Sweep method and adding a 5min goroutine in main.go
Admin portal auth
…anup Add audit logging to the admin portal: - Store layer: InsertAuditEntry, ListAuditEntries (paginated, filtered by user/action/instance/date range, FTS5 full-text search on detail), DeleteAuditEntriesBefore for retention cleanup - Migration v2: FTS5 virtual table with insert/delete/update triggers for automatic index sync - REST API: GET /api/audit with query params (user, action, instance_id, from, to, q, page, per_page) capped at 100 per page - Write-on-action: instance create/update/delete, login, logout, and password change all produce audit entries with contextual detail - Retention cleanup: background goroutine runs immediately on startup then daily, configurable via audit.retention_days (default 90, 0 to keep forever)
Filterable, paginated audit log table with debounced FTS5 search, action type dropdown, and date range pickers. Extracts logic into pure functions (utils/audit.js) and composable (useAuditLog.js). - Date filters use local-timezone boundaries, not UTC - Stale response guard discards out-of-order fetches - 25 utility + 11 composable tests (165 total passing)
Admin portal audit
feat(admin): improve UI accessibility, responsiveness, and polish
fix(admin): move SQLite pragmas to DSN for per-connection enforcement
Mock chaperone fleet, seed-user CLI, six test specs, data-testid attributes, and fix wrong-password 401→403 status code.
Admin portal E2Es
docs(admin): add deployment guide
arnaugiralt
approved these changes
Apr 29, 2026
Member
arnaugiralt
left a comment
There was a problem hiding this comment.
LGTM, congratulations, awesome job 🚀
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds an admin portal to monitor chaperone instances. The code has already been reviewed in many different steps.