{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://auth.proudbase.com/schemas/events/signing_key.rotated.v1.json",
  "title": "signing_key.rotated (v1)",
  "description": "The realm's token signing key was rotated. Emitted when a token signing key rotation starts. Planned rotation (administration API or the scheduled worker) creates a new key in the \"pending\" state that is published in JWKS ahead of use and activated later by the worker without a further event. Emergency rotation activates the new key immediately and marks the previous active key compromised: it is removed from JWKS and its tokens are rejected, so relying parties should refresh JWKS and drop any cached trust in previous_kid. org_id is never set.",
  "type": "object",
  "allOf": [
    {
      "$ref": "envelope.v1.json"
    }
  ],
  "properties": {
    "event_type": {
      "const": "signing_key.rotated"
    },
    "event_version": {
      "const": 1
    },
    "data": {
      "type": "object",
      "description": "Event data. Both payload forms carry every listed member (new_kid, previous_kid and previous_key_compromised are kept in the minimal form).",
      "required": [
        "mode",
        "new_kid",
        "previous_key_compromised"
      ],
      "properties": {
        "mode": {
          "type": "string",
          "enum": [
            "planned",
            "emergency"
          ],
          "description": "Rotation mode."
        },
        "new_kid": {
          "type": "string",
          "minLength": 1,
          "description": "Key ID (JWK \"kid\") of the new key, formatted \"<algorithm in lower case>-<YYYYMMDD>-<16 hex digits>\"."
        },
        "previous_kid": {
          "type": "string",
          "description": "Key ID of the key that was active when the rotation started; empty string when there was none."
        },
        "previous_key_compromised": {
          "type": "boolean",
          "description": "true for emergency rotations (the previous key is compromised and no longer trusted), false for planned rotations."
        }
      },
      "additionalProperties": false,
      "if": {
        "properties": {
          "mode": {
            "const": "emergency"
          }
        },
        "required": [
          "mode"
        ]
      },
      "then": {
        "properties": {
          "previous_key_compromised": {
            "const": true
          }
        }
      },
      "else": {
        "properties": {
          "previous_key_compromised": {
            "const": false
          }
        }
      },
      "dependentRequired": {
        "new_kid": [
          "previous_kid",
          "previous_key_compromised"
        ],
        "previous_kid": [
          "new_kid",
          "previous_key_compromised"
        ],
        "previous_key_compromised": [
          "new_kid",
          "previous_kid"
        ]
      }
    },
    "org_id": {
      "description": "Never set for this event type by the current server."
    }
  },
  "x-event-type": "signing_key.rotated",
  "x-subscribable": true,
  "x-emitted-by": [
    "internal/token/keys.go: (*KeyManager).Rotate"
  ],
  "x-org-scoped": "never",
  "examples": [
    {
      "event_id": "obx_01jbbggdkrchwdkzxbeesha1cr",
      "event_type": "signing_key.rotated",
      "event_version": 1,
      "occurred_at": "2026-10-10T12:10:00.123456789Z",
      "realm_id": "rlm_01jbxe2ktygrnsjxt1j8etsahj",
      "data": {
        "mode": "emergency",
        "new_kid": "es256-20261010-3f9a1c0d7e2b4a65",
        "previous_kid": "es256-20260712-9b1e7d3c2a4f6e80",
        "previous_key_compromised": true
      }
    }
  ]
}
