refactor: rename Metrics gear URL /history → /metrics + themed 404 - #97
Merged
Conversation
The Metrics gear was historically called "history" because the page
shows time-series data. That name leaked into the URL (/history), the
API endpoints (/api/{boxID}/history/*), the templ file
(history.templ), the handler functions (HistoryPage,
APIStatsHistoryHandler, …), and assorted comments / docs / README
entries. With nginx / Apache / Caddy / Traefik detection now landing
(issue #95) and "metric source" / "primary source" terminology in the
new code, the dual naming has become genuinely confusing.
This commit renames the metrics-gear identity end-to-end:
- Page route: /history → /metrics (plugin.go SidebarItem.Path,
base.templ path-prefix match + sidebar links, gears-page.js).
- API routes:
/api/{boxID}/history/stats → /api/{boxID}/metrics/stats
/api/{boxID}/history/metrics → /api/{boxID}/metrics/system
/api/{boxID}/history/backend/{name} → /api/{boxID}/metrics/backend/{name}
(Last one coexists with /metrics/backend/{name}/details — the
time-series endpoint vs the drill-down details endpoint added in #87.)
- Handler functions:
HistoryPage → MetricsPage
APIStatsHistoryHandler → APIMetricsStatsHandler
APIBackendHistoryHandler → APIMetricsBackendHandler
APISystemMetricsHistoryHandler → APIMetricsSystemHandler
- File: pages/history.templ → pages/metrics.templ
(templ component History() → Metrics())
- JS callers: history.templ + details.templ + chart_partials.templ
(8 fetch() URLs updated).
- Docs: metrics gear README routes table + architecture diagram +
development snippet; cmd/server/main.go route-group comment;
pages.go migration-history comment; permissions.go field comment;
docs/gears.md gear list.
Intentionally **kept** as legitimate "history" concepts (per design
discussion):
- DB tables stats_history, system_metrics_history, backend_history —
the rows ARE historical records. Renaming requires a migration with
no user-visible benefit; the names accurately describe what they
contain. The DB query methods that read them (GetStatsHistory,
GetBackendHistory, GetSystemMetricsHistory) keep their names for
the same reason.
- Snapshot interval / retention config: HistoryIntervalSeconds,
store_history, history_retention_days — these control how the
historical record is kept. Same reasoning.
- Local `history` variable names inside the renamed handler functions
— they reflect what the DB methods return.
- OS-update apt/zypper/dnf/pacman history — distinct concept.
/api/v1/system/updates/history on the agent, /os-updates/history on
the dashboard, parseAptHistoryLog, /var/log/apt/history.log, etc.
All untouched.
- HAProxy config change history — distinct concept.
/{boxID}/haproxy/config/history,
templates/pages/haproxy_config/change_history.templ, etc. Untouched.
Agent module: no changes. The agent's "history" references are all
OS-update package-manager history (apt/zypper/dnf/pacman/apk/yum),
which is the legitimate concept.
Tests + build green on both modules.
Wires chi's NotFound to a self-contained handler so a typo'd URL (or a bookmark to the now-renamed /history) lands on a small Gearbox-themed page instead of the browser's default 404. Particularly relevant after the /history → /metrics rename in this PR — anyone with a bookmark to the old URL will hit this. Security posture: the handler is deliberately static end-to-end. - No templ rendering, no auth middleware, no DB / agent lookups. - HTML is a Go const so there's no filesystem or template lookup at request time. - Inline CSS only (no <link> tags) so the response works even if the static-asset bundle didn't load. - No request data echoed into the response (test enforces this) — guards against the page becoming a reflection vector. - `Cache-Control: no-store` so a 404 doesn't outlive a deploy that later adds the missing route. Tests: - TestNotFoundHandlerStatusAndBody: 404 status, HTML body, Cache- Control, expected copy. - TestNotFoundHandlerDoesNotEchoRequestData: URL/header/cookie probes don't appear in the response body — handler is fully static. - TestNotFoundHandlerStableAcrossMethods: GET/POST/PUT/DELETE/PATCH all return the same 404 page. Visual: matches the dashboard's blue accent (#2563eb), uses system fonts (no external font loading), `prefers-color-scheme`-aware so it renders in dark mode without JS.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR renames the Metrics gear's URL surface from /history to /metrics end-to-end (page route, three API endpoints, handler functions, templ component, sidebar entries, JS callers, docs/comments) and adds a themed static 404 handler wired into chi's NotFound. DB tables, retention config, OS-update package-manager history, and HAProxy config-change history intentionally retain the "history" name. The 404 handler is deliberately self-contained (inline HTML const, no auth/DB/templ) so unmatched URLs cannot leak session state, and ships with three new tests.
Changes:
- Rename
/history→/metrics(page route, three API endpoints, Go identifiers, templ component, sidebar/JS/docs). - Add
NotFoundHandlerwith a themed inline-HTML 404 page wired viar.NotFound(...), plus tests asserting status, no request-data reflection, and stability across HTTP methods. - Update Metrics gear README, package doc comments, gears.md, and main.go route-group comments to reflect the rename.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| gearbox/cmd/server/main.go | Wires NotFoundHandler on root router; renames three API routes; updates route-group comment. |
| gearbox/internal/framework/handler/not_found.go | New static 404 handler with inline-HTML const. |
| gearbox/internal/framework/handler/not_found_test.go | Tests for status/headers/body, no-reflection, and method stability. |
| gearbox/internal/framework/handler/api_stats.go | Renames three handler funcs to APIMetrics{Stats,Backend,System}Handler with updated docs. |
| gearbox/internal/framework/handler/pages.go | Comment update for MetricsPage mapping. |
| gearbox/internal/framework/templates/pages/metrics.templ | Templ component renamed History→Metrics; updated fetch URLs and Base layout path. |
| gearbox/internal/framework/templates/pages/details.templ | Updates backend-history fetch to /metrics/backend/.... |
| gearbox/internal/framework/templates/layouts/base.templ | Sidebar links and current-path matcher use /metrics. |
| gearbox/internal/framework/models/permissions.go | Updates metrics:view permission comment. |
| gearbox/internal/gears/metrics/plugin.go | Updates package doc, gear display name/description, sidebar path, route comments. |
| gearbox/internal/gears/metrics/handlers.go | Renames HistoryPage→MetricsPage and updates log/render calls. |
| gearbox/internal/gears/metrics/chart_partials.templ | Updates 6 fetch URLs from /history/* to /metrics/{stats,system}. |
| gearbox/internal/gears/metrics/README.md | Updates routes table, file layout, dev snippet, and adds rename note. |
| gearbox/static/js/gears/gears-page.js | Updates two metrics → /history URL maps to /metrics. |
| docs/gears.md | Updates gear list entry for Metrics. |
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.
Summary
Two related changes that close out the "what does history mean in this codebase" question:
/historyto/metricsend-to-end (page route, API endpoints, handler functions, file name, templ component, sidebar, JS callers, docs).NotFound. Anyone with a bookmark to the old/historyURL will now land on a Gearbox-styled 404 instead of the browser's default — and the handler is intentionally static (no templ, no auth, no DB) so a typo'd URL can't be a side channel for fingerprinting session state.Why now
The Metrics gear was historically called "history" because the page shows time-series. That name leaked everywhere: the URL, the API endpoints, the templ file (
history.templ), the handler functions (HistoryPage,APIStatsHistoryHandler, …), and assorted comments. With #95's "metric source" / "primary source" terminology landing, the dual naming has become genuinely confusing — particularly because there are other legitimate "history" concepts in the codebase (OS-update apt/zypper history, HAProxy config change history) that should keep their names.Renaming the Metrics-gear identity isolates "history" to those genuinely-distinct concepts, so a future reader sees
historyand knows it means OS-update or config-change history, not the Metrics page.What's renamed
Routes:
/history→/metrics/api/{boxID}/history/stats→/api/{boxID}/metrics/stats/api/{boxID}/history/metrics→/api/{boxID}/metrics/system/api/{boxID}/history/backend/{name}→/api/{boxID}/metrics/backend/{name}(coexists with the existing/metrics/backend/{name}/detailsdrill-down from #87)Go identifiers:
HistoryPage→MetricsPageAPIStatsHistoryHandler→APIMetricsStatsHandlerAPIBackendHistoryHandler→APIMetricsBackendHandlerAPISystemMetricsHistoryHandler→APIMetricsSystemHandlerpages.History()templ component →pages.Metrics()Files:
templates/pages/history.templ→templates/pages/metrics.templDocs / comments / sidebar:
metrics/README.mdroutes table, architecture diagram, development snippetcmd/server/main.goroute-group commenthandler/pages.gomigration-history commentmodels/permissions.gofield commentdocs/gears.mdgear listtemplates/layouts/base.templsidebar links (regular + draggable) + current-path matchstatic/js/gears/gears-page.jsURL map (both copies)metrics.templ,details.templ,chart_partials.templIntentionally kept as "history"
These are legitimately distinct concepts; renaming would obscure their meaning:
stats_history,system_metrics_history,backend_history— the rows ARE historical records. Renaming requires a migration with no user-visible benefit; the names accurately describe what they contain. The DB read methods (GetStatsHistory, etc.) keep their names for the same reason.HistoryIntervalSeconds,store_history,history_retention_days— these control how the historical record is kept./api/v1/system/updates/history,parseAptHistoryLog,/var/log/apt/history.log,/os-updates/historyon the dashboard. Untouched./{boxID}/haproxy/config/history,change_history.templ,APIHAProxyConfigHistory. Untouched.Themed static 404
Wired via
r.NotFound(handler.NotFoundHandler)on the root chi router so it inherits only the global middleware (security headers, asset config) and not the auth / session / DB middleware on the protected route groups.Security posture (enforced by tests):
const— no filesystem or template lookup at request time.TestNotFoundHandlerDoesNotEchoRequestDataprobes for marker strings in the response body and fails if any leak.Cache-Control: no-storeso a 404 doesn't outlive a deploy that later adds the missing route.Visual: dashboard's blue accent (#2563eb), system fonts (no external font loading),
prefers-color-scheme-aware.Agent module
No changes. The agent's
historyreferences are all OS-update package-manager history (apt/zypper/dnf/pacman/apk/yum), which is the legitimate concept. Verified by grep — nothing left that ties to the Metrics gear's identity.Test plan
make test— full gearbox suite green.make teston gearbox-agent — 15 packages green (no changes; verifying nothing collateral).go vet ./...clean.NotFoundHandler— status/body, no-reflection, stable across HTTP methods./metricsloads charts onlight-hugger./history(the old URL) lands on the themed 404 with a working "Back to dashboard" link./lolnopelands on the themed 404.Follow-up
Separate branch in the next PR: fix the
scales.y.ticks.stepSize: 1 would result generating up to 8681 ticks. Limiting to 1000.Chart.js warning spam. Pre-existing issue — three places forcestepSize: 1whereprecision: 0would give the intended "integer ticks only" behaviour without making Chart.js generate thousands of tick marks when the data range is large.🤖 Generated with Claude Code