Skip to content

feat(api): emit Deprecation/Sunset headers on legacy endpoints#40

Merged
revtex merged 1 commit intodevfrom
feat/native-api-n3-deprecation
Apr 27, 2026
Merged

feat(api): emit Deprecation/Sunset headers on legacy endpoints#40
revtex merged 1 commit intodevfrom
feat/native-api-n3-deprecation

Conversation

@revtex
Copy link
Copy Markdown
Owner

@revtex revtex commented Apr 27, 2026

Adds RFC 8594 deprecation headers, structured per-request warn logs, and an admin dashboard banner listing API keys that still hit the legacy surface. Purely additive — no legacy behaviour changes.

Backend

  • `middleware.Deprecated(successor, sunset)` attaches `Deprecation: true`, `Sunset`, `Link: ; rel="successor-version"`, and `Cache-Control: no-store` to every legacy `/api/*` and legacy WebSocket route.
  • Per-request `slog.Warn("legacy endpoint hit", method, path, apiKeyIdent)` — `apiKeyIdent` is the truncated identifier (set by `APIKeyAuth` alongside `apiKeyID`), never the raw key.
  • New `GET /api/v1/admin/legacy-usage` endpoint returning a 24-hour aggregate of `{method, path, apiKeyIdent, count, lastSeen}` rows, backed by an in-memory ring buffer (no schema change).

Frontend

  • `LegacyUsageBanner` on the admin dashboard reads `/api/v1/admin/legacy-usage`, polls every 60s, and is dismissable per session via `sessionStorage`. Expandable details table with method, path, API key, count, and last-seen relative time.

Tests

Compatibility

No legacy route behaviour changed. Existing clients see the new response headers and ignore them; functional responses are byte-identical.

Adds RFC 8594 deprecation headers, structured per-request warn logs, and
an admin dashboard banner listing API keys that still hit the legacy
surface. No legacy behaviour changed beyond the additive headers.

Backend:
- middleware.Deprecated(successor, sunset) attaches Deprecation: true,
  Sunset, Link rel=successor-version, and Cache-Control: no-store to
  every legacy /api/* and legacy WS route.
- Per-request slog.Warn("legacy endpoint hit", method, path,
  apiKeyIdent) — apiKeyIdent is the truncated identifier (set by
  APIKeyAuth alongside apiKeyID), never the raw key.
- New /api/v1/admin/legacy-usage endpoint returning a 24h aggregate
  ({method, path, apiKeyIdent, count, lastSeen}) backed by an in-memory
  ring buffer; no schema change.

Frontend:
- LegacyUsageBanner reads /api/v1/admin/legacy-usage on the admin
  dashboard, polls every 60s, dismissable per session via
  sessionStorage. Expandable details table with method, path, API key,
  count, last-seen relative time.

Tests: middleware/deprecation_test.go covers header emission and the
ring buffer; legacyusage/handler_test.go covers the aggregate endpoint;
LegacyUsageBanner.test.tsx covers loading, empty, populated, and
dismissed states.
@revtex revtex merged commit 468e397 into dev Apr 27, 2026
7 checks passed
@revtex revtex deleted the feat/native-api-n3-deprecation branch April 27, 2026 00:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant