Skip to content

fix: handle recovery when API key slots are full #138

Description

@dennisonbertram

Problem

If a tenant has filled all 20 API key slots and loses access to all of them, they cannot:

  • Revoke keys — requires a valid API key to call DELETE /v1/auth/keys/{keyID}
  • RecoverPOST /v1/auth/recover creates a new key, which fails because the keyring is full (20/20)

This is a catch-22 that currently requires operator SQL intervention.

Proposed Solution

Modify the recovery endpoint (POST /v1/auth/recover) to handle the full keyring case:

  1. When keyring is full during recovery, auto-revoke the oldest expired key to make room
  2. If no expired keys exist, auto-revoke the oldest key (by created_at) and include a warning in the response
  3. Add a revoked_key_id field to the recovery response so the operator/tenant knows which key was displaced

Response when a key was auto-revoked:

{
  "api_key": "newkey.secret",
  "key_id": "new-key-id",
  "warning": "key slot was full; revoked oldest key",
  "revoked_key_id": "old-key-id"
}

Implementation Notes

  • Modify handleRecovery in internal/api/recovery.go
  • Add RevokeOldestExpired(tenantID) and RevokeOldest(tenantID) to the key store
  • Prefer revoking expired keys over active ones
  • Log at AUDIT level when auto-revoking

Acceptance Criteria

  • Recovery succeeds even when keyring is full (20/20)
  • Expired keys are revoked first, then oldest active key
  • Response includes revoked_key_id and warning when auto-revoke happens
  • AUDIT log entry for auto-revoked key
  • Unit tests for full-keyring recovery scenario
  • No regression when keyring has available slots

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions