Summary
Follow-up from #380 (closed without merging).
PR #380 added a heavyweight usage-stats system to API keys: a lifetime counter + a rolling-24h counter + a 3-tile summary card + a "Most active (24h)" top-3 list + per-row Requests (24h) and Requests (total) columns + a dedicated GET /api/api-keys/usage-stats endpoint + a migration for two counters and a window-start timestamp.
Per @cristim on the PR (closing comment, 2026-05-19):
I don't think these stats are valuable, we should at most update a "Last used" timestamp of the API keys, not keeping such detailed stats.
This issue tracks the lighter alternative: just a single last_used_at TIMESTAMPTZ column, updated on each authenticated API-key use, surfaced as one column in the Admin → API Keys table.
What this issue is
- One new column on
api_keys: last_used_at TIMESTAMPTZ NULL
- On every successful API-key authentication, async update
last_used_at = NOW() for that key — no counters, no rolling window, no separate timestamp tracking
- One new column in the Admin → API Keys UI: "Last used" — render as a relative time (e.g. "2 hours ago", "—" when null)
- Sort the table by
last_used_at DESC NULLS LAST by default? Optional; can stay as-is
What this issue is NOT
Acceptance criteria
Implementation notes
The PR #380 branch (feat/admin-apikeys-usage-stats) is closed but the worktree exists at ~/.worktrees/CUDly/apikeys-usage and could be partially salvaged — keep the migration shape, the RecordAPIKeyUsage async pattern, and the ValidateUserAPIKey async-trigger; delete the counter logic, the stats endpoint, the summary card, and the top-3 list.
Cross-references
Summary
Follow-up from #380 (closed without merging).
PR #380 added a heavyweight usage-stats system to API keys: a lifetime counter + a rolling-24h counter + a 3-tile summary card + a "Most active (24h)" top-3 list + per-row Requests (24h) and Requests (total) columns + a dedicated
GET /api/api-keys/usage-statsendpoint + a migration for two counters and a window-start timestamp.Per @cristim on the PR (closing comment, 2026-05-19):
This issue tracks the lighter alternative: just a single
last_used_at TIMESTAMPTZcolumn, updated on each authenticated API-key use, surfaced as one column in the Admin → API Keys table.What this issue is
api_keys:last_used_at TIMESTAMPTZ NULLlast_used_at = NOW()for that key — no counters, no rolling window, no separate timestamp trackinglast_used_at DESC NULLS LASTby default? Optional; can stay as-isWhat this issue is NOT
/api/api-keys/usage-statsendpoint — the timestamp comes back as part of the existingGET /api/api-keysresponseAcceptance criteria
last_used_at TIMESTAMPTZ NULLtoapi_keys(and the corresponding.down.sqldrops it)UserAPIKey/APIKeyInfotypes gain a singleLastUsedAt *time.TimefieldValidateUserAPIKeyasync-updates the column on successful validation (singleUPDATEstatement; no read-then-write); failures during the update log but don't impact the request pathGET /api/api-keysreturns the new field (no new endpoint)Implementation notes
The PR #380 branch (
feat/admin-apikeys-usage-stats) is closed but the worktree exists at~/.worktrees/CUDly/apikeys-usageand could be partially salvaged — keep the migration shape, theRecordAPIKeyUsageasync pattern, and theValidateUserAPIKeyasync-trigger; delete the counter logic, the stats endpoint, the summary card, and the top-3 list.Cross-references