Skip to content

feat(api-keys): show a simple "Last used" timestamp per API key (lighter alternative to #380) #492

@cristim

Description

@cristim

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

  • Migration adds last_used_at TIMESTAMPTZ NULL to api_keys (and the corresponding .down.sql drops it)
  • UserAPIKey / APIKeyInfo types gain a single LastUsedAt *time.Time field
  • ValidateUserAPIKey async-updates the column on successful validation (single UPDATE statement; no read-then-write); failures during the update log but don't impact the request path
  • Existing GET /api/api-keys returns the new field (no new endpoint)
  • Admin → API Keys frontend renders a "Last used" column with relative-time formatting and "—" for null
  • Tests cover: column appears in API response, async update fires on success but not failure, frontend renders null vs populated, time formatting

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions