{
  "openapi": "3.1.0",
  "info": {
    "title": "Ezkey Admin API",
    "description": "Administration API for Ezkey - Open Source Cryptographic MFA Platform\n\nThis API enables administrative management of Ezkey's main entities:\n- **Integrations**: Applications or systems protected by MFA\n- **Enrollments**: Associations between users, devices and integrations\n- **Auth Attempts**: MFA authentication attempts\n- **Admin Management**: Administrator authentication,\n                        enrollment recovery, and admin operations\n\nEzkey is intentionally distinct from FIDO2/WebAuthn and follows its own\ncryptographic MFA model. The API uses REST conventions and DTOs for all\nrequests and responses.\n",
    "contact": {
      "name": "Ezkey Team",
      "url": "https://ezkey.org",
      "email": "info@ezkey.org"
    },
    "license": {
      "name": "MIT License",
      "url": "https://opensource.org/licenses/MIT"
    },
    "version": "1.0.0"
  },
  "servers": [
    {
      "url": "http://localhost:9080",
      "description": "Development server Admin API"
    },
    {
      "url": "https://admin-api.ezkey.org",
      "description": "Production server Admin API"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Public",
      "description": "Unauthenticated instance metadata, evaluator preview signup, and related public endpoints"
    },
    {
      "name": "Admin Authentication",
      "description": "Administrator authentication and session management for passwordless login and recovery"
    },
    {
      "name": "Tenants",
      "description": "Tenant management API"
    },
    {
      "name": "Integrations",
      "description": "Integration management API"
    },
    {
      "name": "Enrollments",
      "description": "Enrollment management API"
    },
    {
      "name": "API Keys",
      "description": "API key management for machine-to-machine (Integration API) authentication"
    },
    {
      "name": "Auth Attempts",
      "description": "Authentication attempt management API"
    },
    {
      "name": "Admin Enrollment Management",
      "description": "Administrator enrollment management and device recovery after loss"
    },
    {
      "name": "Administrator Provisioning",
      "description": "Administrator provisioning API"
    },
    {
      "name": "Audit Logs",
      "description": "Audit log query and reporting API for security monitoring and compliance"
    },
    {
      "name": "Encryption Keys",
      "description": "Encryption key lifecycle management and rotation operations"
    },
    {
      "name": "Alerts",
      "description": "Operator-facing alert subsystem (Global Admin only). Surfaces internal Ezkey signals such as undeclared audit chain gaps; resolved automatically by the matching producer workflow."
    },
    {
      "name": "Dashboard",
      "description": "Dashboard overview and aggregated stats for Admin UI"
    }
  ],
  "paths": {
    "/api/v1/tenants/{id}": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "Get tenant by ID",
        "description": "Gets a tenant by ID. GlobalAdmins can access any tenant. TenantAdmins can only access their own tenant.",
        "operationId": "getTenant",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Tenant found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Tenant not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": [
          "Tenants"
        ],
        "summary": "Update a tenant",
        "description": "Updates a tenant (partial update). GlobalAdmin only.",
        "operationId": "updateTenant",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Tenant updated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Tenant not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tenants": {
      "get": {
        "tags": [
          "Tenants"
        ],
        "summary": "List tenants",
        "description": "Lists tenants with pagination and optional filters. GlobalAdmin only. Use page, size, sort for pagination. Optional tenantName (partial match) and active (boolean) for filtering. Sortable: tenantId, tenantName, active, createdAt.",
        "operationId": "listTenants",
        "parameters": [
          {
            "name": "tenantName",
            "in": "query",
            "description": "Filter by tenant name (partial match, case-insensitive)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Filter by active flag (true/false; omit for all)",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of tenants (content + page)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelTenantResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelTenantResponseDto"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Tenants"
        ],
        "summary": "Create a new tenant",
        "description": "Creates a new tenant. GlobalAdmin only.",
        "operationId": "createTenant",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Tenant created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request or tenant name already exists",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not a global administrator",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/TenantResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tenants/{id}/deactivate": {
      "post": {
        "tags": [
          "Tenants"
        ],
        "summary": "Deactivate a tenant",
        "description": "Deactivates a tenant and revokes all active admin tokens for that tenant. GlobalAdmin only. The system tenant cannot be deactivated.",
        "operationId": "deactivateTenant",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantDeactivateRequestDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Success (no content). An audit entry is recorded only when the tenant was active and is now deactivated; idempotent calls when already inactive do not add an audit event."
          },
          "400": {
            "description": "Bad request - cannot deactivate the system tenant (RFC 9457 ProblemDetail)"
          },
          "404": {
            "description": "Tenant not found"
          },
          "403": {
            "description": "Forbidden - not a global administrator"
          }
        }
      }
    },
    "/api/v1/tenants/{id}/activate": {
      "post": {
        "tags": [
          "Tenants"
        ],
        "summary": "Activate a tenant",
        "description": "Activates a previously deactivated tenant. GlobalAdmin only. Idempotent if already active.",
        "operationId": "activateTenant",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Tenant ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantActivateRequestDto"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Success (no content). An audit entry is recorded only when the tenant was inactive and is now activated; idempotent calls when already active do not add an audit event."
          },
          "404": {
            "description": "Tenant not found"
          },
          "403": {
            "description": "Forbidden - not a global administrator"
          }
        }
      }
    },
    "/api/v1/public/evaluator-signup": {
      "post": {
        "tags": [
          "Public"
        ],
        "summary": "Anonymous evaluator self-registration",
        "description": "Creates an empty preview tenant and a pending Tenant Admin with a one-time activation code. Available only on installations with evaluator self-registration enabled.",
        "operationId": "evaluatorSignup",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EvaluatorSelfRegistrationRequestDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Preview tenant and activation code created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EvaluatorSelfRegistrationResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Feature disabled on this installation",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EvaluatorSelfRegistrationResponseDto"
                }
              }
            }
          },
          "429": {
            "description": "Preview capacity or client limit reached",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EvaluatorSelfRegistrationResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "summary": "Search integrations",
        "description": "Retrieves integrations with optional filters and pagination for administration and compliance reporting. Supports dynamic sorting via ?sort=field,direction (e.g., ?sort=id,asc). Default sort is by creation date descending (newest first). Retired integrations are excluded by default unless explicitly requested. Optional tenantId filter: GlobalAdmin only; TenantAdmin scope is always their tenant.",
        "operationId": "search",
        "parameters": [
          {
            "name": "integrationName",
            "in": "query",
            "description": "Filter by integration name (partial match, case-insensitive)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Compatibility filter by active flag",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "lifecycleStatus",
            "in": "query",
            "description": "Exact lifecycle filter (ACTIVE, RETIRED)",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ACTIVE",
                "RETIRED"
              ]
            }
          },
          {
            "name": "includeRetired",
            "in": "query",
            "description": "Include retired integrations in results when no exact lifecycle is requested",
            "required": false,
            "schema": {
              "type": "boolean",
              "default": false
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Filter integrations created after this timestamp (ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Filter integrations created before this timestamp (ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "tenantId",
            "in": "query",
            "description": "Filter by tenant ID. GlobalAdmin only; when provided limits results to that tenant. Ignored for TenantAdmin.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search completed successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelIntegrationResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelIntegrationResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Integrations"
        ],
        "summary": "Create new integration",
        "description": "Creates a new integration with the provided data. Integration code must be unique per tenant.",
        "operationId": "create",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/IntegrationCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Integration created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationCreateResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid data (validation errors: invalid code format, blank code, etc.)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "409": {
            "description": "Integration code already exists for this tenant",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/{id}/retire": {
      "post": {
        "tags": [
          "Integrations"
        ],
        "summary": "Retire integration",
        "description": "Retires an integration from day-to-day use while preserving historical data. The operation bulk-revokes revocable enrollments before marking the integration RETIRED.",
        "operationId": "retire",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Integration ID to retire",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Audit justification for the retirement (min 10 characters)",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Integration retired successfully"
          },
          "403": {
            "description": "System integration cannot be retired",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/{id}/enrollments/revoke-all": {
      "post": {
        "tags": [
          "Integrations"
        ],
        "summary": "Bulk-revoke all enrollments for an integration",
        "description": "Permanently revokes all revocable enrollments for the specified integration, including deactivated VERIFIED enrollments and in-flight CREATED or BOUND enrollments. Intended for incident response (e.g., compromised API key). Cannot be applied to system integrations.",
        "operationId": "revokeAllEnrollments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Integration ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 5
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Optional justification for bulk revocation (min 10 characters when provided)",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bulk revocation completed successfully with result summary",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Access denied or system integration guard triggered",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/{id}/enrollments/reactivate-all": {
      "post": {
        "tags": [
          "Integrations"
        ],
        "summary": "Bulk-reactivate all enrollments for an integration",
        "description": "Reactivates all inactive VERIFIED enrollments for the specified integration. Use after a precautionary deactivate-all.",
        "operationId": "reactivateAllEnrollments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Integration ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 5
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Optional justification for bulk reactivation",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bulk reactivation completed successfully with result summary",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Access denied",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/{id}/enrollments/deactivate-all": {
      "post": {
        "tags": [
          "Integrations"
        ],
        "summary": "Bulk-deactivate all enrollments for an integration",
        "description": "Reversibly deactivates all active VERIFIED enrollments for the specified integration. Use for precautionary lockdowns. Restore with POST .../enrollments/reactivate-all. Cannot be applied to system integrations.",
        "operationId": "deactivateAllEnrollments",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Integration ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 5
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Optional justification for bulk deactivation",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 0
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Bulk deactivation completed successfully with result summary",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "403": {
            "description": "Access denied or system integration guard triggered",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BulkEnrollmentOperationResultDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enrollments": {
      "get": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Search enrollments",
        "description": "Retrieves enrollments with optional filters and pagination for security monitoring, forensic analysis, and compliance reporting. Supports dynamic sorting via ?sort=field,direction (e.g., ?sort=enrollmentId,asc). Default sort is by creation date descending (newest first).",
        "operationId": "search_1",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by enrollment status (CREATED, BOUND, VERIFIED, INVALID, REVOKED, EXPIRED)",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "CREATED",
                "BOUND",
                "VERIFIED",
                "INVALID",
                "REVOKED",
                "EXPIRED"
              ]
            }
          },
          {
            "name": "integrationId",
            "in": "query",
            "description": "Filter by integration ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "enrollmentName",
            "in": "query",
            "description": "Filter by enrollment name (partial match, case-insensitive)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Filter by active flag",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Filter enrollments created after this timestamp (ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Filter enrollments created before this timestamp (ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search completed successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelEnrollmentResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelEnrollmentResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelEnrollmentResponseDto"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Create new enrollment",
        "description": "Creates a new enrollment that can later be bound to a mobile device",
        "operationId": "create_1",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollmentCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Enrollment created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentCreateResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid data",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentCreateResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden by enrollment policy",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentCreateResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Enrollment conflict",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentCreateResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentCreateResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enrollments/{id}/revoke": {
      "post": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Permanently revoke an enrollment",
        "description": "Irrevocably revokes an enrollment. Sets status to REVOKED and active=false. If the enrollment belongs to an admin, their active bearer tokens are immediately invalidated. Self-revocation is not allowed.",
        "operationId": "revoke",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Enrollment ID to revoke",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Mandatory justification for revocation (min 10 characters)",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Enrollment revoked successfully"
          },
          "400": {
            "description": "Invalid parameters"
          },
          "403": {
            "description": "Access denied, self-revocation attempted, or system integration guard"
          },
          "404": {
            "description": "Enrollment not found"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/api/v1/enrollments/{id}/reactivate": {
      "post": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Reactivate a deactivated enrollment",
        "description": "Reactivates an enrollment that was previously deactivated via /deactivate. Only applicable to VERIFIED enrollments. Cannot reactivate REVOKED enrollments.",
        "operationId": "reactivate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Enrollment ID to reactivate",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Optional justification for reactivation",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 0
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Enrollment reactivated successfully"
          },
          "400": {
            "description": "Enrollment is already active, revoked, or not in VERIFIED status"
          },
          "403": {
            "description": "Access denied"
          },
          "404": {
            "description": "Enrollment not found"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/api/v1/enrollments/{id}/deactivate": {
      "post": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Deactivate an enrollment",
        "description": "Reversibly deactivates an enrollment (active=false). Status remains VERIFIED. Can be undone with /reactivate. If the enrollment belongs to an admin, their active bearer tokens are immediately invalidated. Self-deactivation is not allowed.",
        "operationId": "deactivate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Enrollment ID to deactivate",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Optional justification for deactivation",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 0
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Enrollment deactivated successfully"
          },
          "400": {
            "description": "Invalid parameters or state conflict"
          },
          "403": {
            "description": "Access denied or self-deactivation"
          },
          "404": {
            "description": "Enrollment not found"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      }
    },
    "/api/v1/encryption-keys/{keyId}/reencrypt": {
      "post": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Trigger re-encryption for specific key",
        "description": "Creates and processes re-encryption batches for a specific old key. The key must not be PRIMARY.",
        "operationId": "triggerReencryptionForKey",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Re-encryption triggered successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionKeyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (key not found or is PRIMARY)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionKeyResponse"
                }
              }
            }
          },
          "404": {
            "description": "Key not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionKeyResponse"
                }
              }
            }
          },
          "500": {
            "description": "Re-encryption failed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionKeyResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/rotate": {
      "post": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Manually trigger key rotation",
        "description": "Introduces a new encryption key (typically PENDING until the sync window elapses, then promoted to PRIMARY).",
        "operationId": "rotateKey",
        "parameters": [
          {
            "name": "reason",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key rotation completed successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/KeyRotationResponse"
                }
              }
            }
          },
          "409": {
            "description": "A PENDING encryption key already exists; wait for promotion or use immediate promotion",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "500": {
            "description": "Key rotation failed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/KeyRotationResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/reencryption-batches/{batchId}/resume": {
      "post": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Resume re-encryption batch",
        "description": "Resumes processing of a failed or paused re-encryption batch",
        "operationId": "resumeBatch",
        "parameters": [
          {
            "name": "batchId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batch resumed successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResumeResponse"
                }
              }
            }
          },
          "404": {
            "description": "Batch not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResumeResponse"
                }
              }
            }
          },
          "500": {
            "description": "Failed to resume batch",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResumeResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/reencrypt/trigger": {
      "post": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Trigger full re-encryption",
        "description": "Manually triggers full re-encryption process. Creates batches for all old keys and processes them immediately.",
        "operationId": "triggerFullReencryption",
        "responses": {
          "200": {
            "description": "Re-encryption triggered successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionTriggerResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request (encryption not available)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionTriggerResponse"
                }
              }
            }
          },
          "500": {
            "description": "Re-encryption failed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ReencryptionTriggerResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/reencrypt/create-batches": {
      "post": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Create re-encryption batches",
        "description": "Creates re-encryption batches for all old keys without processing them. Batches will be processed by the scheduled job.",
        "operationId": "createBatches",
        "responses": {
          "200": {
            "description": "Batches created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BatchCreationResponse"
                }
              }
            }
          },
          "500": {
            "description": "Batch creation failed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/BatchCreationResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth-attempts": {
      "get": {
        "tags": [
          "Auth Attempts"
        ],
        "summary": "Search auth attempts",
        "description": "Retrieves authentication attempts with optional filters and pagination for security monitoring, forensic analysis, and compliance reporting. Supports dynamic sorting via ?sort=field,direction (e.g., ?sort=authAttemptId,asc). Default sort is by creation date descending (newest first).",
        "operationId": "search_2",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by authentication attempt status (PENDING, READ, ACCEPTED, REJECTED, INVALID, EXPIRED)",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "PENDING",
                "READ",
                "INVALID",
                "REJECTED",
                "ACCEPTED",
                "EXPIRED"
              ]
            }
          },
          {
            "name": "enrollmentId",
            "in": "query",
            "description": "Filter by enrollment ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "integrationId",
            "in": "query",
            "description": "Filter by integration ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Filter attempts created after this timestamp (ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Filter attempts created before this timestamp (ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Search completed successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuthAttemptDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuthAttemptDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuthAttemptDto"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Auth Attempts"
        ],
        "summary": "Create new auth attempt",
        "description": "Creates a new authentication attempt for MFA validation",
        "operationId": "create_2",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthAttemptCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Auth attempt created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid data",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth-attempts/{id}/cancel": {
      "post": {
        "tags": [
          "Auth Attempts"
        ],
        "summary": "Cancel auth attempt",
        "description": "Cancels a pending or read authentication attempt by marking it as expired. Allows client applications to proactively abort authentication requests.",
        "operationId": "cancel",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Auth attempt ID to cancel",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Auth attempt cancelled successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          },
          "409": {
            "description": "Auth attempt already in final state (cannot be cancelled)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          },
          "404": {
            "description": "Auth attempt not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/lifecycle/seal-archive": {
      "post": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Seal an audit chain period for archival",
        "description": "Marks all chain checkpoints in the specified period as ARCHIVE_SEAL prior to dropping the corresponding DB partition. Runs a mandatory pre-flight integrity check -- rejected if any violation is detected. Returns the seal HMAC to include in the Git archive manifest. Global Admin only.\n\n**Period identification -- two alternative modes:**\n- **Timestamp mode**: provide `periodStart` (inclusive) and `periodEnd` (exclusive) as ISO-8601 timestamps.\n- **Checkpoint ID mode**: provide `checkpointIdFrom` and `checkpointIdTo` (both inclusive integers). The service resolves the effective time range from those checkpoints automatically. Ergonomic when working directly with the database -- short IDs are easier to read than full timestamps.\n\nExactly one mode must be used. Providing both is an error.",
        "operationId": "sealArchive",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ArchiveSealRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Period sealed successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ArchiveSealResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request: conflicting modes, missing required fields, or no checkpoints found for the given ID range",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "409": {
            "description": "Chain integrity violation detected -- resolve before sealing",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/lifecycle/incidents/{incidentId}/declare": {
      "post": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Declare an audit-chain heartbeat incident closed",
        "description": "Supplies justification and classified root cause for an incident in RECOVERED_PENDING_DECLARATION. Global Admin only.",
        "operationId": "declareLifecycleIncident",
        "parameters": [
          {
            "name": "incidentId",
            "in": "path",
            "description": "Incident identifier",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            },
            "example": 1
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeclareAuditChainIncidentRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Incident declared closed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditChainIncidentResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid payload or wrong incident state",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditChainIncidentResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditChainIncidentResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditChainIncidentResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Incident not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditChainIncidentResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/lifecycle/declare-gap": {
      "post": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Declare a downtime gap in the audit chain",
        "description": "Creates a single GAP_DECLARATION checkpoint covering the specified period and signs it into the chain with the admin's justification. Use when the system was offline longer than the scheduler lookback window. Must be called before the scheduler fills the gap with regular checkpoints. Global Admin only.\n\n**Gap start -- two alternative modes:**\n- **Timestamp mode**: provide `gapStart` as an ISO-8601 timestamp (the moment the system went offline).\n- **Anchor checkpoint mode**: provide `anchorCheckpointId`, the `checkpoint_id` of the last checkpoint recorded before the downtime. The service derives `gapStart = anchorCheckpoint.window_end` automatically. Ergonomic when working directly with the database -- look up the last checkpoint ID before the gap and pass it directly, no timestamp extraction needed.\n\n`gapEnd` is always a timestamp when provided. In anchor checkpoint mode it is **optional**: if omitted, the service auto-derives it as the `window_start` of the first checkpoint that exists after the anchor (the boundary between the undeclared gap and the scheduler's catch-up checkpoints). If no such checkpoint exists yet, falls back to the start of the current 5-minute window. Exactly one of `gapStart` or `anchorCheckpointId` must be provided.",
        "operationId": "declareGap",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GapDeclarationRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Gap declared successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/GapDeclarationResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request: conflicting modes, missing required fields, audit entries found in gap period, or anchor checkpoint not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "409": {
            "description": "Conflicting regular checkpoints already exist in the gap period",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/lifecycle/confirm-archived": {
      "post": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Confirm externally archived audit tranche",
        "description": "Marks a sealed checkpoint tranche as EXPORTED after an external archival workflow has successfully persisted the corresponding bundle. Supports both timestamp range and checkpoint ID identification modes, mirroring seal-archive. Global Admin only.",
        "operationId": "confirmArchived",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ArchiveConfirmArchivedRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Archive confirmation recorded",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ArchiveConfirmArchivedResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request: conflicting modes, missing required fields, or no checkpoints found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "409": {
            "description": "Checkpoint state conflict or external archival disabled by policy",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "List all API keys for current admin",
        "description": "Returns API keys with pagination, filtered by admin type. GlobalAdmin sees all keys, TenantAdmin sees only keys for their tenant's integrations. Optional filters: integrationId, active, description. Use page, size, sort for pagination. Secret keys are never included.",
        "operationId": "listAllApiKeys",
        "parameters": [
          {
            "name": "integrationId",
            "in": "query",
            "description": "Filter by integration ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "active",
            "in": "query",
            "description": "Filter by active flag (true/false; omit for all)",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "description",
            "in": "query",
            "description": "Filter by description (partial match, case-insensitive)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of API keys (content + page metadata)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - admin token required",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelApiKeyResponseDto"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "API Keys"
        ],
        "summary": "Create new API key pair",
        "description": "Generates a new API key pair for machine-to-machine authentication. The secret key is shown ONLY ONCE and cannot be retrieved later.",
        "operationId": "createApiKey",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "API key created successfully - SAVE THE SECRET KEY IMMEDIATELY",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreateResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request data",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreateResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - admin token required",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreateResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found or inactive",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreateResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Maximum active keys limit reached for integration",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyCreateResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}/recovery-codes/regenerate": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Regenerate administrator recovery codes",
        "description": "Generates a new set of single-use recovery codes for an administrator. Previous unused codes are invalidated immediately. GlobalAdmin can access any admin; TenantAdmin can access admins in their tenant.",
        "operationId": "regenerateRecoveryCodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Recovery codes regenerated successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Target administrator is inactive",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Administrator not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}/recovery-codes/issue-initial": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Issue initial administrator recovery codes",
        "description": "Generates the first set of single-use recovery codes for an administrator after first authenticated sign-in. This flow is distinct from regeneration and is only available when no recovery-code set exists yet.",
        "operationId": "issueInitialRecoveryCodes",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Initial recovery codes issued successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Administrator is not eligible yet",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Administrator not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}/deactivate": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Deactivate an administrator",
        "description": "Deactivates an administrator account and revokes all tokens. GlobalAdmin only. Enforces minimum limits and prevents self-deactivation.",
        "operationId": "deactivateAdmin",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Audit justification for the deactivation (min 10 characters)",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Administrator deactivated successfully"
          },
          "400": {
            "description": "Cannot deactivate: self-deactivation attempted or would violate limits (RFC 9457 Problem Detail)"
          },
          "403": {
            "description": "Forbidden - caller is not a global administrator"
          },
          "404": {
            "description": "Administrator not found"
          }
        }
      }
    },
    "/api/v1/admins/{id}/activation-code/regenerate": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Re-issue deferred onboarding activation code",
        "description": "Generates a new one-time activation code for an administrator still in pending activation who has no first enrollment yet. Any previously unused activation issuance rows for this administrator are deactivated immediately. GlobalAdmin only.",
        "operationId": "regenerateActivationCode",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Activation code re-issued successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Administrator inactive, tenant inactive, lifecycle not pending, or enrollment already exists",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Administrator not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}/activate": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Activate an administrator",
        "description": "Reactivates a deactivated administrator account. GlobalAdmin only. Idempotent if already active. Admin must log in again to obtain a new token.",
        "operationId": "activateAdmin",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Audit justification for the activation (min 10 characters)",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Administrator activated successfully"
          },
          "403": {
            "description": "Forbidden - caller is not a global administrator"
          },
          "404": {
            "description": "Administrator not found"
          }
        }
      }
    },
    "/api/v1/admins/tenant": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Create a peer tenant administrator",
        "description": "Creates a new tenant administrator. GlobalAdmin can create for any tenant. TenantAdmin can create for same tenant only. Enforces max limit. onboardingMode=IMMEDIATE returns enrollment/recovery bootstrap data; onboardingMode=ACTIVATION_CODE returns a one-time activation code and leaves the admin pending activation.",
        "operationId": "createTenantAdmin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Tenant administrator created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request, limit exceeded, username exists, or tenant not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized or tenant admin trying to create for different tenant",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/global": {
      "post": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Create a peer global administrator",
        "description": "Creates a new global administrator. GlobalAdmin only. Enforces max limit. onboardingMode=IMMEDIATE returns enrollment/recovery bootstrap data; onboardingMode=ACTIVATION_CODE returns a one-time activation code and leaves the admin pending activation.",
        "operationId": "createGlobalAdmin",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Global administrator created successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid request, username exists, or global administrator limit reached. When the configured maximum active global administrators is reached, the response is RFC 9457 application/problem+json with type https://ezkey.io/problems/admin-provisioning/global-admin-limit-reached and extension property parameters.maxGlobalAdmins (integer).",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not a global administrator",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/enrollments/reset": {
      "post": {
        "tags": [
          "Admin Enrollment Management"
        ],
        "operationId": "resetEnrollment",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollmentResetRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResetResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/auth/recover": {
      "post": {
        "tags": [
          "Admin Authentication"
        ],
        "summary": "Recover admin access with recovery code",
        "description": "Emergency access using single-use recovery code. Returns temporary token (30 min) with limited permissions (enrollment reset only).",
        "operationId": "recover",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminRecoveryRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Recovery successful, temporary token issued",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminRecoveryResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation error (invalid recovery code format) or invalid request data",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminRecoveryResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Recovery failed (invalid or expired recovery code)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminRecoveryResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminRecoveryResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/auth/passwordless-wait": {
      "post": {
        "tags": [
          "Admin Authentication"
        ],
        "summary": "Wait for passwordless authentication device response",
        "description": "Polls for passwordless authentication completion in two-call flows. Blocks for up to the wait window aligned with auth attempt TTL (capped at 300s). Supports both challenge-based (with display code) and non-blocking flows. Errors follow RFC 9457 Problem Details format.",
        "operationId": "passwordlessWait",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminPasswordlessWaitRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Authentication successful. Returns bearer token and admin session details.",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Device denied, signature failed, or challenge invalid. Returns RFC 9457 ProblemDetail with specific error type URI.",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid challenge code. Returns RFC 9457 ProblemDetail: type='...invalid-credentials'",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "408": {
            "description": "Request Timeout - No device response within the wait window (max 300 seconds). Returns RFC 9457 ProblemDetail: type='...auth-timeout'",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/auth/logout": {
      "post": {
        "tags": [
          "Admin Authentication"
        ],
        "operationId": "logout",
        "parameters": [
          {
            "name": "Authorization",
            "in": "header",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/api/v1/admin/auth/login": {
      "post": {
        "tags": [
          "Admin Authentication"
        ],
        "summary": "Authenticate administrator with passwordless Ezkey MFA",
        "description": "Passwordless authentication for administrators using device-based cryptography. Supports single-call (blocking) or two-call (challenge) flows. Returns bearer token on success, or challenge info for two-step authentication. Rate limiting applied per IP. Errors follow RFC 9457 Problem Details format.",
        "operationId": "login",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminLoginRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Authentication successful or pending. If status='approved', bearer token is present. If status='pending', authAttemptId and challengeCode present for two-call flow.",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Authentication failed with temporal issues (expired, rejected, invalid signature). Returns RFC 9457 ProblemDetail with specific error type URI.",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid credentials (username not found). Returns RFC 9457 ProblemDetail: type='...invalid-credentials'",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Account inactive or no device enrolled. Returns RFC 9457 ProblemDetail: type='...account-inactive' or '...no-enrollment'",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "408": {
            "description": "Request Timeout - No device response within the wait window (aligned with auth attempt TTL, maximum 300 seconds). Returns RFC 9457 ProblemDetail: type='...auth-timeout'",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate limit exceeded for this IP address. Applies after 10 failed attempts in 15 minutes.",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminLoginResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/auth/activate": {
      "post": {
        "tags": [
          "Admin Authentication"
        ],
        "summary": "Activate pending administrator with one-time activation code",
        "description": "Consumes a one-time activation code issued during deferred onboarding. Returns the first enrollment binding credentials while keeping recovery codes deferred from this unauthenticated bootstrap response.",
        "operationId": "activate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminActivationRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Activation successful",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminActivationResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Validation error or activation cannot proceed in the current state",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminActivationResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Invalid, expired, or unusable activation code",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminActivationResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminActivationResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enrollments/{id}": {
      "get": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Retrieve enrollment by ID",
        "description": "Returns details of a specific enrollment",
        "operationId": "getById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Unique enrollment ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Enrollment found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Enrollment not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Delete enrollment",
        "description": "Removes an enrollment from the system",
        "operationId": "delete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Enrollment ID to delete",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Audit justification for the deletion (min 10 characters)",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Enrollment deleted successfully"
          },
          "403": {
            "description": "Cannot delete your own MFA enrollment (RFC 9457)"
          },
          "404": {
            "description": "Enrollment not found"
          },
          "409": {
            "description": "Enrollment has authentication history (revoke instead) or is linked as an administrator's MFA (use recovery flow to reset that admin's MFA) (RFC 9457)"
          },
          "500": {
            "description": "Internal server error"
          }
        }
      },
      "patch": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Partially update enrollment metadata",
        "description": "Updates enrollment metadata (name, contactEmail, expiresAt, authAttemptChallengeRequired, userIdentifier). Only active VERIFIED enrollments. Include version from GET for optimistic locking.",
        "operationId": "update",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Enrollment ID to update",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollmentUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Enrollment updated successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid data, enrollment not updatable (revoked/inactive), or validation failed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Access denied",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Enrollment not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Optimistic lock conflict - resource was modified, re-fetch and retry",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/{keyId}": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "Get API key details",
        "description": "Returns details of a specific API key. Secret key is never included.",
        "operationId": "getApiKey",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "description": "API key ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 42
          }
        ],
        "responses": {
          "200": {
            "description": "API key details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - admin token required",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "API key not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "API Keys"
        ],
        "summary": "Revoke API key",
        "description": "Immediately revokes an API key, making it unusable for authentication. The key is preserved for audit purposes.",
        "operationId": "revokeApiKey",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "description": "API key ID to revoke",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 42
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Audit justification for the revocation (min 10 characters)",
            "required": false,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "API key revoked successfully"
          },
          "401": {
            "description": "Unauthorized - admin token required"
          },
          "404": {
            "description": "API key not found"
          },
          "429": {
            "description": "Too many revoke requests - rate limit exceeded"
          }
        }
      },
      "patch": {
        "tags": [
          "API Keys"
        ],
        "summary": "Partially update API key configuration",
        "description": "Updates API key config (ipWhitelist, description). Only active keys. Include version from GET for optimistic locking.",
        "operationId": "updateApiKey",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "description": "API key ID to update",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 42
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ApiKeyUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "API key updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid data, key revoked, or ipWhitelist validation failed (invalid CIDR)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Access denied",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "API key not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Optimistic lock conflict - resource was modified, re-fetch and retry",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "429": {
            "description": "Too many update requests - rate limit exceeded",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}": {
      "get": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Get administrator by ID",
        "description": "Returns a single administrator by ID. GlobalAdmin can access any admin. TenantAdmin can only access admins in their tenant.",
        "operationId": "getAdminById",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Administrator retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Administrator not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Update administrator profile",
        "description": "Partial update of administrator profile (firstName, lastName, email, challengeRequired). GlobalAdmin can update any admin. TenantAdmin can update admins in their tenant. Admins can update their own profile. Include version for optimistic locking.",
        "operationId": "updateAdmin",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminUpdateRequestDto"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "Administrator profile updated successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid data or email already exists",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Administrator not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          },
          "409": {
            "description": "Optimistic lock conflict - resource was modified, re-fetch and retry",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/public/instance-info": {
      "get": {
        "tags": [
          "Public"
        ],
        "summary": "Get public instance info",
        "description": "Returns read-only instance metadata for the Admin UI (login shell) and operators. authApiPublicBaseUrl matches the authUrl embedded in enrollment QR codes when ezkey.qr.auth-base-url is set.",
        "operationId": "getInstanceInfo",
        "responses": {
          "200": {
            "description": "Instance metadata",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicInstanceInfoResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/integrations/{id}": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "summary": "Retrieve integration by ID",
        "description": "Returns details of a specific integration",
        "operationId": "getById_1",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Unique integration ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Integration found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrationResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Integrations"
        ],
        "summary": "Delete integration",
        "description": "Permanently deletes an already-retired integration that no longer has enrollments.",
        "operationId": "delete_1",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Integration ID to delete",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "reason",
            "in": "query",
            "description": "Audit justification for the deletion (min 10 characters)",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 500,
              "minLength": 10
            }
          }
        ],
        "responses": {
          "204": {
            "description": "Integration deleted successfully"
          },
          "403": {
            "description": "System integration cannot be deleted",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "404": {
            "description": "Integration not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "409": {
            "description": "Integration must be retired first and must not have enrollments",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/enrollments/{id}/qrcode": {
      "get": {
        "tags": [
          "Enrollments"
        ],
        "summary": "Generate QR code for enrollment",
        "description": "Returns a PNG QR code image containing enrollment credentials as JSON ({enrollmentId, enrollmentProofToken, authUrl})",
        "operationId": "getQrCode",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Enrollment ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 4
          }
        ],
        "responses": {
          "200": {
            "description": "QR code generated successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "string",
                  "format": "byte"
                }
              }
            }
          },
          "400": {
            "description": "Enrollment missing proof token",
            "content": {
              "*/*": {
                "schema": {
                  "type": "string",
                  "format": "byte"
                }
              }
            }
          },
          "404": {
            "description": "Enrollment not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "string",
                  "format": "byte"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "type": "string",
                  "format": "byte"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys": {
      "get": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "List encryption keys",
        "description": "Returns encryption keys with pagination and optional keyStatus filter. Use page, size, sort for pagination. Optional keyStatus: PRIMARY, ENABLED, DISABLED, PENDING. Sortable: keyId, keyStatus, algorithm, introducedAt, promotedPrimaryAt, disabledAt, recordsEncrypted, recordsReencrypted, createdBy, createdAt.",
        "operationId": "listKeys",
        "parameters": [
          {
            "name": "keyStatus",
            "in": "query",
            "description": "Filter by key status (PRIMARY, ENABLED, DISABLED, PENDING); omit for all",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "introducedAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of keys (content + page)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelEncryptionKeyResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelEncryptionKeyResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/{keyId}": {
      "get": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Get encryption key by ID",
        "description": "Returns details for a specific encryption key",
        "operationId": "getKey",
        "parameters": [
          {
            "name": "keyId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Key retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyResponse"
                }
              }
            }
          },
          "404": {
            "description": "Key not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/reencryption-batches": {
      "get": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "List re-encryption batches",
        "description": "Returns re-encryption batches with pagination and optional filters. Use page, size, sort (default sort createdAt,DESC). Optional filters: status (PENDING, IN_PROGRESS, COMPLETED, FAILED, PAUSED), targetTable, targetColumn, oldKeyId, newKeyId, createdAfter, createdBefore (ISO-8601, inclusive bounds on createdAt). Sortable: batchId, status, targetTable, targetColumn, createdAt, startedAt, completedAt, progressPct, recordsTotal, recordsDone, oldKey.keyId, newKey.keyId.",
        "operationId": "listBatches",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by batch status (PENDING, IN_PROGRESS, COMPLETED, FAILED, PAUSED); omit for all",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "targetTable",
            "in": "query",
            "description": "Filter by target table name (exact match)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "targetColumn",
            "in": "query",
            "description": "Filter by target column name (exact match)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "oldKeyId",
            "in": "query",
            "description": "Filter by old encryption key id",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "newKeyId",
            "in": "query",
            "description": "Filter by new encryption key id",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Inclusive lower bound on createdAt (ISO-8601); aligns with Admin UI date range",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Inclusive upper bound on createdAt (ISO-8601); aligns with Admin UI date range",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Batches retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelReencryptionBatchResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelReencryptionBatchResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/encryption-keys/primary": {
      "get": {
        "tags": [
          "Encryption Keys"
        ],
        "summary": "Get primary encryption key",
        "description": "Returns the current primary encryption key used for new encryption operations",
        "operationId": "getPrimaryKey",
        "responses": {
          "200": {
            "description": "Primary key retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyResponse"
                }
              }
            }
          },
          "404": {
            "description": "No primary key found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyResponse"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/EncryptionKeyResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/dashboard/overview": {
      "get": {
        "tags": [
          "Dashboard"
        ],
        "summary": "Get dashboard overview",
        "description": "Returns aggregated stats (integrations, enrollments, auth 24h terminal-outcome health), recent activity, and for Global Admin only: instance-level alerts (e.g. audit chain gap pending). Designed for 60s refresh interval.",
        "operationId": "getOverview",
        "responses": {
          "200": {
            "description": "Dashboard overview",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardOverviewDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/DashboardOverviewDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth-attempts/{id}": {
      "get": {
        "tags": [
          "Auth Attempts"
        ],
        "summary": "Retrieve auth attempt by ID",
        "description": "Returns details of a specific authentication attempt",
        "operationId": "getById_2",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Unique auth attempt ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Auth attempt found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          },
          "404": {
            "description": "Auth attempt not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth-attempts/{id}/wait": {
      "get": {
        "tags": [
          "Auth Attempts"
        ],
        "summary": "Wait for authentication response",
        "description": "Blocks until authentication attempt is completed or timeout is reached. Provides polling mechanism for synchronous-like behavior in MFA flow.",
        "operationId": "waitForResponse",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Authentication attempt ID to wait for",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          },
          {
            "name": "timeout",
            "in": "query",
            "description": "Maximum wait duration in seconds",
            "required": false,
            "schema": {
              "type": "string",
              "default": "30",
              "maximum": 300,
              "minimum": 1
            },
            "example": 30
          },
          {
            "name": "polling",
            "in": "query",
            "description": "Polling interval in seconds",
            "required": false,
            "schema": {
              "type": "string",
              "default": "2",
              "maximum": 60,
              "minimum": 1
            },
            "example": 2
          }
        ],
        "responses": {
          "200": {
            "description": "Authentication completed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptWaitResponseDto"
                }
              }
            }
          },
          "408": {
            "description": "Timeout reached, authentication still pending",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptWaitResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Auth attempt not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptWaitResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters (timeout, polling)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptWaitResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuthAttemptWaitResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/auth-attempts/pending-count": {
      "get": {
        "tags": [
          "Auth Attempts"
        ],
        "summary": "Get pending auth attempt count",
        "description": "Returns the number of auth attempts with status PENDING for the current scope. Designed for dashboard live widget (e.g. 10s refresh).",
        "operationId": "getPendingCount",
        "responses": {
          "200": {
            "description": "Pending count",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "integer",
                    "format": "int64"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object",
                  "additionalProperties": {
                    "type": "integer",
                    "format": "int64"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Query audit logs",
        "description": "Retrieves audit logs with optional filters, tenant-scoped visibility, and pagination for security monitoring and compliance reporting. Tenant Admins automatically see only their tenant's audit logs. Global Admins see all logs and may optionally filter by tenantId. Supports dynamic sorting via ?sort=field,direction (e.g., ?sort=auditLogId,asc). Default sort is by creation date descending (newest first).",
        "operationId": "getAuditLogs",
        "parameters": [
          {
            "name": "eventType",
            "in": "query",
            "description": "Filter by a single event type (not together with eventTypeFamily)",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ADMIN_LOGIN",
                "ADMIN_LOGOUT",
                "ADMIN_PASSWORD_CHANGE",
                "ADMIN_RECOVERY_USE",
                "ADMIN_RECOVERY_CODES_ISSUED",
                "ADMIN_RECOVERY_CODES_REGENERATED",
                "ADMIN_ACTIVATION",
                "ADMIN_ACTIVATION_CODE_REISSUED",
                "ADMIN_RECOVERY_ENROLLMENT_RESET",
                "ADMIN_CREATED",
                "ADMIN_PROFILE_UPDATED",
                "ADMIN_DEACTIVATED",
                "ADMIN_ACTIVATED",
                "ENROLLMENT_CREATED",
                "ENROLLMENT_UPDATED",
                "ENROLLMENT_DELETED",
                "ENROLLMENT_BIND",
                "ENROLLMENT_VERIFY",
                "ENROLLMENT_REVOKED",
                "ENROLLMENT_DEACTIVATED",
                "ENROLLMENT_REACTIVATED",
                "ENROLLMENT_AUTH_ATTEMPT_BLOCKED",
                "ENROLLMENT_EXPIRED",
                "AUTH_ATTEMPT_CREATED",
                "AUTH_ATTEMPT_PENDING",
                "AUTH_ATTEMPT_RESPOND",
                "AUTH_ATTEMPT_CANCELLED",
                "AUTH_ATTEMPT_EXPIRED",
                "API_KEY_CREATED",
                "API_KEY_UPDATED",
                "API_KEY_REVOKED",
                "API_KEY_EXPIRED",
                "API_KEY_AUTH_SUCCESS",
                "API_KEY_AUTH_FAILED",
                "API_KEY_IP_BLOCKED",
                "SYSTEM_ERROR",
                "KEY_INTRODUCED",
                "KEY_PROMOTED_PRIMARY",
                "KEY_DEMOTED",
                "KEY_DISABLED",
                "KEYSET_BACKUP_CREATED",
                "REENCRYPTION_STARTED",
                "REENCRYPTION_BATCH_PROGRESS",
                "REENCRYPTION_COMPLETED",
                "REENCRYPTION_FAILED",
                "REENCRYPTION_RESUMED",
                "REENCRYPTION_PAUSED",
                "INTEGRATION_CREATED",
                "INTEGRATION_UPDATED",
                "INTEGRATION_RETIRED",
                "INTEGRATION_DELETED",
                "TENANT_CREATED",
                "TENANT_UPDATED",
                "TENANT_DEACTIVATED",
                "TENANT_ACTIVATED",
                "EVALUATOR_SELF_REGISTRATION",
                "AUDIT_CHAIN_ARCHIVE_SEALED",
                "AUDIT_CHAIN_ARCHIVE_EXPORTED",
                "AUDIT_CHAIN_GAP_DECLARED",
                "AUDIT_CHAIN_INCIDENT_DECLARED",
                "ALERT_RAISED",
                "ALERT_RESOLVED"
              ]
            }
          },
          {
            "name": "eventTypeFamily",
            "in": "query",
            "description": "Filter by event family (all types in the family). Mutually exclusive with eventType.",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ADMIN",
                "ENROLLMENT",
                "AUTH_ATTEMPT",
                "API_KEY",
                "SYSTEM",
                "ENCRYPTION_KEY",
                "REENCRYPTION",
                "INTEGRATION",
                "TENANT",
                "AUDIT_CHAIN",
                "ALERT"
              ]
            }
          },
          {
            "name": "eventStatus",
            "in": "query",
            "description": "Filter by event status",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "SUCCESS",
                "FAILURE",
                "ERROR"
              ]
            }
          },
          {
            "name": "apiName",
            "in": "query",
            "description": "Filter by API name",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "ADMIN_API",
                "AUTH_API",
                "INTEGRATION_API"
              ]
            }
          },
          {
            "name": "enrollmentId",
            "in": "query",
            "description": "Filter by enrollment ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "authAttemptId",
            "in": "query",
            "description": "Filter by auth attempt ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "integrationId",
            "in": "query",
            "description": "Filter by integration ID",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "adminId",
            "in": "query",
            "description": "Filter by admin ID (actor)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "targetAdminId",
            "in": "query",
            "description": "Filter by target admin ID (subject of event, e.g. created/deactivated/activated)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "tenantId",
            "in": "query",
            "description": "Filter by tenant ID (Global Admin only). Ignored for Tenant Admin whose scope is enforced automatically.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Filter by creation time (inclusive start), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Filter by creation time (inclusive end), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit logs retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditLogResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameters",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditLogResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditLogResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditLogResponseDto"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditLogResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/{id}/integrity-check": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Verify integrity of a single audit log entry",
        "description": "Recomputes the HMAC-SHA256 signature for a single audit log entry and compares it to the stored value. Returns OK if the entry is intact, INTEGRITY_VIOLATION_DETECTED if modified, UNSIGNED if not signed, or NOT_FOUND if the ID does not exist. Global Admin only.",
        "operationId": "checkSingleEntryIntegrity",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Audit log entry ID to verify",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            },
            "example": 42
          }
        ],
        "responses": {
          "200": {
            "description": "Integrity check completed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/{auditLogId}/context": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Get audit log context around an anchor event",
        "description": "Retrieves a bounded neighborhood of audit events around a single anchor log for operator investigation. Tenant visibility rules are enforced exactly like the standard audit search.",
        "operationId": "getAuditLogContext",
        "parameters": [
          {
            "name": "auditLogId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          },
          {
            "name": "beforeCount",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "afterCount",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "tenantId",
            "in": "query",
            "description": "Filter by tenant ID (Global Admin only). Ignored for Tenant Admin whose scope is enforced automatically.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Audit log context retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogContextResponseDto"
                }
              }
            }
          },
          "400": {
            "description": "Invalid before/after counts",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogContextResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogContextResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogContextResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Anchor audit log not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AuditLogContextResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/lifecycle/incidents": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "List audit-chain heartbeat incidents",
        "description": "Paginated list of operational incidents raised when peripheral supervision detected stalled checkpoints (bounded unsupervised activity / degraded mode). Separate from GAP_DECLARATION checkpoints. Global Admin only.",
        "operationId": "listLifecycleIncidents",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Incidents retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditChainIncidentResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditChainIncidentResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditChainIncidentResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/lifecycle/archive-eligibility": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Get archive eligibility summary",
        "description": "Returns the current backend lifecycle summary used by future archival automation. This endpoint does not materialize an export bundle; it reports whether external archival is enabled and which sealed checkpoint tranche currently awaits confirmation.",
        "operationId": "getArchiveEligibility",
        "responses": {
          "200": {
            "description": "Archive eligibility returned",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ArchiveEligibilityResult"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetail"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/integrity-check": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Verify audit log integrity",
        "description": "Recomputes HMAC-SHA256 signatures for audit log entries in the specified date range and reports any tampered or unsigned entries. Global Admin only.",
        "operationId": "checkIntegrity",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "description": "Start of verification window (inclusive, ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "End of verification window (exclusive, ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Integrity check completed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          },
          "400": {
            "description": "Date range required -- provide from and to as ISO-8601",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/IntegrityReport"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/chain-integrity": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Verify audit chain checkpoint integrity",
        "description": "Verifies chain checkpoint integrity by recomputing entry digests and validating chain linkage. Detects entry insertion, deletion, reordering, checkpoint tampering, and undeclared temporal gaps (missing checkpoints between consecutive windows or uncovered leading/trailing periods in the requested range). Global Admin only.\n\n**Range handling:** The requested from/to may extend before the first checkpoint or after the last in the database. Such periods are not reported as undeclared gaps (they are before/after \"EZKey time\"). Only real gaps within the system's checkpoint extent are reported. The response fields effectiveFrom and effectiveTo indicate the range actually used for boundary gap reporting (clamped to coverageStart/coverageEnd when the request extended beyond the first/last checkpoint).",
        "operationId": "checkChainIntegrity",
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "description": "Start of verification range (inclusive, ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "End of verification range (exclusive, ISO-8601)",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Chain verification completed",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ChainVerificationReport"
                }
              }
            }
          },
          "400": {
            "description": "Date range required -- provide from and to as ISO-8601",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ChainVerificationReport"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ChainVerificationReport"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/ChainVerificationReport"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/audit-logs/chain-checkpoints": {
      "get": {
        "tags": [
          "Audit Logs"
        ],
        "summary": "Search audit chain checkpoints",
        "description": "Paginated search over audit chain checkpoints with optional filters (window range, entry count, checkpoint type, created range). Supports SEAL range selection and Declare Gap anchor lookup. Global Admin only. Default sort: windowStart,asc.",
        "operationId": "getChainCheckpoints",
        "parameters": [
          {
            "name": "windowStartAfter",
            "in": "query",
            "description": "Filter: window_start >= value (inclusive), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "windowStartBefore",
            "in": "query",
            "description": "Filter: window_start < value (exclusive), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "entryCountMin",
            "in": "query",
            "description": "Filter: entry_count >= value (e.g. 1 for non-empty windows)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "entryCountMax",
            "in": "query",
            "description": "Filter: entry_count <= value (e.g. 0 for empty windows only)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          },
          {
            "name": "checkpointType",
            "in": "query",
            "description": "Filter by checkpoint type",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "REGULAR",
                "ARCHIVE_SEAL",
                "GAP_DECLARATION"
              ]
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Filter: created_at >= value (inclusive), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Filter: created_at < value (exclusive), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "windowStart,ASC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Checkpoints retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditChainCheckpointResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditChainCheckpointResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Not a Global Admin",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAuditChainCheckpointResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/api-keys/integration/{integrationId}": {
      "get": {
        "tags": [
          "API Keys"
        ],
        "summary": "List API keys for integration",
        "description": "Returns API keys for the specified integration with pagination. When active is omitted, returns only active keys. Use page, size, sort. Secret keys are never included in responses.",
        "operationId": "listApiKeys",
        "parameters": [
          {
            "name": "integrationId",
            "in": "path",
            "description": "Integration ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 123
          },
          {
            "name": "active",
            "in": "query",
            "description": "Filter by active flag (omit = active only)",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of API keys (content + page metadata)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - admin token required",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelApiKeyResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "List alerts",
        "description": "Returns a paginated list of operator-facing alerts. Supports filtering by status, alert type, severity, dedupe key, and creation-time range. Default sort is by createdAt descending (newest first). Sortable fields: createdAt, lastSeenAt, severity, status. Restricted to Global Admin.",
        "operationId": "listAlerts",
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "description": "Filter by alert status",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "OPEN",
                "RESOLVED"
              ]
            }
          },
          {
            "name": "alertType",
            "in": "query",
            "description": "Filter by alert type",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "AUDIT_CHAIN_GAP_PENDING",
                "AUDIT_CHAIN_HEARTBEAT_STALE"
              ]
            }
          },
          {
            "name": "severity",
            "in": "query",
            "description": "Filter by severity",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "INFO",
                "WARNING",
                "CRITICAL"
              ]
            }
          },
          {
            "name": "dedupeKey",
            "in": "query",
            "description": "Exact dedupe-key match (debug / forensic aid)",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "createdAfter",
            "in": "query",
            "description": "Filter by creation time (inclusive start), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "createdBefore",
            "in": "query",
            "description": "Filter by creation time (inclusive end), ISO-8601",
            "required": false,
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alerts retrieved",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAlertResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAlertResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (not a Global Admin)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAlertResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/alerts/{alertId}": {
      "get": {
        "tags": [
          "Alerts"
        ],
        "summary": "Get alert by id",
        "description": "Returns the alert with the given id. Restricted to Global Admin.",
        "operationId": "getAlert",
        "parameters": [
          {
            "name": "alertId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int64"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Alert returned",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden (not a Global Admin)",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponseDto"
                }
              }
            }
          },
          "404": {
            "description": "Alert not found",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AlertResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins": {
      "get": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "List administrators",
        "description": "Lists administrators with tenant-based filtering. GlobalAdmin sees all admins. TenantAdmin sees only admins from their tenant. Supports pagination and sorting.",
        "operationId": "listAdmins",
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Zero-based page index (0..N)",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 0,
              "minimum": 0
            }
          },
          {
            "name": "size",
            "in": "query",
            "description": "The size of the page to be returned",
            "required": false,
            "schema": {
              "type": "integer",
              "default": 20,
              "minimum": 1
            }
          },
          {
            "name": "sort",
            "in": "query",
            "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
            "required": false,
            "style": "form",
            "explode": true,
            "schema": {
              "type": "array",
              "default": [
                "createdAt,DESC"
              ],
              "items": {
                "type": "string"
              }
            }
          },
          {
            "name": "tenantId",
            "in": "query",
            "description": "Filter by tenant ID. GlobalAdmin only; when provided, limits results to that tenant. Ignored for TenantAdmin.",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of administrators retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAdminResponseDto"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not an administrator",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/PagedModelAdminResponseDto"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}/onboarding": {
      "get": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Retrieve onboarding credentials",
        "description": "Retrieves onboarding credentials (enrollment proof token, challenge code) for an administrator. Recovery codes cannot be retrieved after initial provisioning.",
        "operationId": "getAdminOnboarding",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Onboarding credentials retrieved successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Administrator or enrollment not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admins/{id}/onboarding/qrcode": {
      "get": {
        "tags": [
          "Administrator Provisioning"
        ],
        "summary": "Generate QR code for onboarding",
        "description": "Returns a PNG QR code image containing enrollment credentials as JSON ({enrollmentId, enrollmentProofToken, authUrl}) for passwordless enrollment binding.",
        "operationId": "getAdminOnboardingQrCode",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "Administrator ID",
            "required": true,
            "schema": {
              "type": "integer",
              "format": "int32"
            },
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "QR code generated successfully",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Enrollment missing proof token",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - not authorized",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "404": {
            "description": "Administrator or enrollment not found",
            "content": {
              "*/*": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/admin/auth/me": {
      "get": {
        "tags": [
          "Admin Authentication"
        ],
        "summary": "Get current administrator session metadata",
        "description": "Returns non-secret session metadata for the authenticated administrator. Browser cookie sessions also receive a non-secret CSRF token for unsafe requests.",
        "operationId": "me",
        "responses": {
          "200": {
            "description": "Current session metadata",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminSessionResponseDto"
                }
              }
            }
          },
          "401": {
            "description": "Not authenticated",
            "content": {
              "*/*": {
                "schema": {
                  "$ref": "#/components/schemas/AdminSessionResponseDto"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "TenantUpdateRequestDto": {
        "type": "object",
        "description": "Request DTO for updating a tenant (partial update)",
        "properties": {
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version from GET response. When provided, update fails with 409 if resource was modified since last fetch.",
            "example": 0
          },
          "tenantName": {
            "type": "string",
            "description": "New unique name for the tenant",
            "example": "Acme Corporation",
            "maxLength": 100,
            "minLength": 3
          },
          "tenantDescription": {
            "type": "string",
            "description": "Updated description of the tenant",
            "example": "Acme Corp MFA tenant",
            "maxLength": 500,
            "minLength": 0
          },
          "organizationName": {
            "type": "string",
            "description": "Legal name of the organization",
            "example": "Acme Corporation Inc.",
            "maxLength": 255,
            "minLength": 0
          },
          "organizationDomain": {
            "type": "string",
            "description": "Primary domain of the organization",
            "example": "acme.com",
            "maxLength": 255,
            "minLength": 0,
            "pattern": "^[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
          },
          "countryCode": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code",
            "example": "CA",
            "maxLength": 2,
            "minLength": 2,
            "pattern": "^[A-Z]{2}$"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone identifier",
            "example": "America/Montreal",
            "maxLength": 50,
            "minLength": 0
          },
          "primaryContactName": {
            "type": "string",
            "description": "Primary contact full name",
            "example": "Jane Doe",
            "maxLength": 255,
            "minLength": 0
          },
          "primaryContactEmail": {
            "type": "string",
            "format": "email",
            "description": "Primary contact email address",
            "example": "jane.doe@acme.com",
            "maxLength": 255,
            "minLength": 0
          },
          "primaryContactPhoneNumber": {
            "type": "string",
            "description": "Primary contact phone number. Accepts common separators and is normalized to E.164 on write.",
            "example": "+1 514 555 1234",
            "maxLength": 50,
            "minLength": 0
          }
        }
      },
      "TenantResponseDto": {
        "type": "object",
        "description": "Response DTO containing tenant information",
        "properties": {
          "tenantId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier for the tenant",
            "example": 1
          },
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version. Include in PATCH/PUT requests to prevent concurrent update conflicts.",
            "example": 0
          },
          "tenantName": {
            "type": "string",
            "description": "Unique name of the tenant",
            "example": "Acme Corporation"
          },
          "tenantDescription": {
            "type": "string",
            "description": "Optional description of the tenant",
            "example": "Acme Corp's Ezkey tenant"
          },
          "organizationName": {
            "type": "string",
            "description": "Legal name of the organization",
            "example": "Acme Corporation Inc."
          },
          "organizationDomain": {
            "type": "string",
            "description": "Primary domain of the organization",
            "example": "acme.com"
          },
          "countryCode": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code",
            "example": "CA"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone identifier",
            "example": "America/Montreal"
          },
          "primaryContactName": {
            "type": "string",
            "description": "Primary contact full name",
            "example": "Jane Doe"
          },
          "primaryContactEmail": {
            "type": "string",
            "description": "Primary contact email address",
            "example": "jane.doe@acme.com"
          },
          "primaryContactPhoneNumber": {
            "type": "string",
            "description": "Primary contact phone number in canonical E.164 format",
            "example": "+15145551234"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the tenant was created",
            "example": "2025-10-15T14:30:00Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp of the last modification",
            "example": "2025-11-01T09:15:00Z"
          },
          "active": {
            "type": "boolean",
            "description": "Flag indicating if the tenant is active",
            "example": true
          },
          "isSystemTenant": {
            "type": "boolean",
            "description": "Flag indicating if this is the system tenant",
            "example": false
          },
          "deactivatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the tenant was deactivated (null if never deactivated; preserved for audit traceability)",
            "example": "2025-11-15T10:00:00Z"
          },
          "operational": {
            "type": "boolean",
            "description": "Whether the tenant is currently operational (active flag is true)",
            "example": true
          }
        }
      },
      "TenantCreateRequestDto": {
        "type": "object",
        "description": "Request DTO for creating a tenant",
        "properties": {
          "tenantName": {
            "type": "string",
            "description": "Unique name for the tenant",
            "example": "Acme Corporation",
            "maxLength": 100,
            "minLength": 3
          },
          "tenantDescription": {
            "type": "string",
            "description": "Optional description of the tenant",
            "example": "Acme Corp's Ezkey tenant for MFA authentication",
            "maxLength": 500,
            "minLength": 0
          },
          "organizationName": {
            "type": "string",
            "description": "Legal name of the organization",
            "example": "Acme Corporation Inc.",
            "maxLength": 255,
            "minLength": 0
          },
          "organizationDomain": {
            "type": "string",
            "description": "Primary domain of the organization",
            "example": "acme.com",
            "maxLength": 255,
            "minLength": 0,
            "pattern": "^[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
          },
          "countryCode": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 country code",
            "example": "CA",
            "maxLength": 2,
            "minLength": 2,
            "pattern": "^[A-Z]{2}$"
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone identifier",
            "example": "America/Montreal",
            "maxLength": 50,
            "minLength": 0
          },
          "primaryContactName": {
            "type": "string",
            "description": "Primary contact full name",
            "example": "Jane Doe",
            "maxLength": 255,
            "minLength": 0
          },
          "primaryContactEmail": {
            "type": "string",
            "format": "email",
            "description": "Primary contact email address",
            "example": "jane.doe@acme.com",
            "maxLength": 255,
            "minLength": 0
          },
          "primaryContactPhoneNumber": {
            "type": "string",
            "description": "Primary contact phone number. Accepts common separators and is normalized to E.164 on write.",
            "example": "+1 514 555 1234",
            "maxLength": 50,
            "minLength": 0
          }
        },
        "required": [
          "tenantName"
        ]
      },
      "TenantDeactivateRequestDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10
          }
        }
      },
      "TenantActivateRequestDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10
          }
        }
      },
      "EvaluatorSelfRegistrationRequestDto": {
        "type": "object",
        "description": "Anonymous evaluator self-registration request",
        "properties": {
          "tenantLabel": {
            "type": "string",
            "description": "Optional short label for the preview tenant (max 40 characters; no email or URL)",
            "example": "My preview workspace",
            "maxLength": 40,
            "minLength": 0
          }
        }
      },
      "EvaluatorSelfRegistrationResponseDto": {
        "type": "object",
        "description": "Anonymous evaluator self-registration response",
        "properties": {
          "activationCode": {
            "type": "string",
            "description": "One-time activation code (save immediately)",
            "example": "ABCD-1234"
          },
          "activationCodeExpiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Activation code expiration instant (UTC)"
          },
          "adminUiUrl": {
            "type": "string",
            "description": "Admin UI URL for this preview instance"
          },
          "guidedTourUrl": {
            "type": "string",
            "description": "Guided tour URL on ezkey.org"
          },
          "tenantLabel": {
            "type": "string",
            "description": "Server-generated tenant slug",
            "example": "eval-a1b2c3d4"
          }
        }
      },
      "IntegrationCreateRequestDto": {
        "type": "object",
        "description": "Integration creation data including code, name, and description",
        "properties": {
          "code": {
            "type": "string",
            "description": "Unique business identifier code for the integration",
            "example": "web-portal",
            "maxLength": 100,
            "minLength": 2,
            "pattern": "^[a-zA-Z0-9_-]+$"
          },
          "name": {
            "type": "string",
            "description": "Display name for the integration",
            "example": "Web Portal",
            "maxLength": 255,
            "minLength": 0
          },
          "description": {
            "type": "string",
            "description": "Optional description of the integration",
            "example": "Administration console",
            "maxLength": 500,
            "minLength": 0
          }
        },
        "required": [
          "code",
          "name"
        ]
      },
      "IntegrationCreateResponseDto": {
        "type": "object",
        "description": "Response DTO containing created integration details",
        "properties": {
          "code": {
            "type": "string",
            "description": "Unique business identifier code for the integration",
            "example": "web-portal"
          },
          "id": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier of the newly created integration",
            "example": 42
          }
        }
      },
      "ProblemDetail": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer",
            "format": "int32"
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "format": "uri"
          },
          "properties": {
            "type": "object",
            "additionalProperties": {}
          }
        }
      },
      "BulkEnrollmentOperationResultDto": {
        "type": "object",
        "properties": {
          "affectedCount": {
            "type": "integer",
            "format": "int32"
          },
          "skippedCount": {
            "type": "integer",
            "format": "int32"
          },
          "noOp": {
            "type": "boolean"
          }
        }
      },
      "EnrollmentCreateRequestDto": {
        "type": "object",
        "description": "Enrollment creation data",
        "properties": {
          "integrationId": {
            "type": "integer",
            "format": "int32",
            "description": "The integration ID to which this enrollment belongs",
            "example": 1
          },
          "name": {
            "type": "string",
            "description": "Human-readable name for the enrollment",
            "example": "John's iPhone",
            "minLength": 1
          },
          "authAttemptChallengeRequired": {
            "type": "boolean",
            "description": "Whether authentication attempts require challenge validation",
            "example": true
          },
          "contactEmail": {
            "type": "string",
            "description": "Optional contact email for the end-user"
          },
          "contactPhoneNumber": {
            "type": "string",
            "description": "Optional contact phone number for the end-user"
          },
          "userIdentifier": {
            "type": "string",
            "description": "Optional user identifier from the integrating application"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional invitation expiry (UTC instant). Pending phase only; must be in the future when set. Omit to use ezkey.enrollment.pending-expiration-days.",
            "example": "2026-12-31T23:59:59Z"
          }
        },
        "required": [
          "integrationId",
          "name"
        ]
      },
      "EnrollmentCreateResponseDto": {
        "type": "object",
        "description": "Response DTO containing created enrollment details",
        "properties": {
          "enrollmentId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier of the created enrollment",
            "example": 21
          },
          "enrollmentChallenge": {
            "type": "integer",
            "format": "int32",
            "description": "Challenge number for enrollment verification",
            "example": 154982
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Invitation expiry (UTC) for the pending enrollment phase, when set on the server"
          }
        }
      },
      "ReencryptionKeyResponse": {
        "type": "object",
        "properties": {
          "keyId": {
            "type": "integer",
            "format": "int64"
          },
          "batchesCreated": {
            "type": "integer",
            "format": "int32"
          },
          "batchesProcessed": {
            "type": "integer",
            "format": "int32"
          },
          "batchesFailed": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "KeyRotationResponse": {
        "type": "object",
        "properties": {
          "newPrimaryKeyId": {
            "type": "integer",
            "format": "int64"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "BatchResumeResponse": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "ReencryptionTriggerResponse": {
        "type": "object",
        "properties": {
          "batchesCreated": {
            "type": "integer",
            "format": "int32"
          },
          "batchesProcessed": {
            "type": "integer",
            "format": "int32"
          },
          "batchesFailed": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "BatchCreationResponse": {
        "type": "object",
        "properties": {
          "batchesCreated": {
            "type": "integer",
            "format": "int32"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "AuthAttemptCreateRequestDto": {
        "type": "object",
        "description": "Auth attempt creation data",
        "properties": {
          "enrollmentId": {
            "type": "integer",
            "format": "int32",
            "description": "Enrollment ID (use this OR userIdentifier). Direct reference to enrollment.",
            "example": 123
          },
          "userIdentifier": {
            "type": "string",
            "description": "User identifier (username, user_id) for lookup within integration scope. Use this OR enrollmentId. When used with admin token, integrationId is required.",
            "example": "alice"
          },
          "integrationId": {
            "type": "integer",
            "format": "int32",
            "description": "Integration ID. Required when userIdentifier is used with admin token. Ignored when API key (derived from credentials).",
            "example": 1
          },
          "challengeRequested": {
            "type": "boolean",
            "description": "Whether a challenge code is requested for this attempt",
            "example": false
          },
          "contextTitle": {
            "type": "string",
            "description": "Optional short title for the approval request, displayed as the mobile card header. Max 200 characters. Example: \"Payment Approval\"",
            "example": "Payment Approval",
            "maxLength": 200,
            "minLength": 0
          },
          "contextMessage": {
            "type": "string",
            "description": "Optional descriptive message explaining what the approver is authorizing. Max 2000 characters.",
            "example": "Authorize payment batch #1497 to Acme Corp for $1,400",
            "maxLength": 2000,
            "minLength": 0
          },
          "demoMitmSignatureRequested": {
            "type": "boolean",
            "description": "Demo only: when true, this attempt is flagged for simulated MITM (tampered Pending body after signing) if Auth API ezkey.demo.mitm-signature-enabled is true.",
            "example": false
          }
        },
        "required": [
          "challengeRequested"
        ]
      },
      "AuthAttemptDto": {
        "type": "object",
        "description": "Authentication attempt details",
        "properties": {
          "authAttemptId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique auth attempt ID",
            "example": 42
          },
          "enrollmentId": {
            "type": "integer",
            "format": "int32",
            "description": "Associated enrollment ID",
            "example": 7
          },
          "authAttemptStatus": {
            "type": "string",
            "description": "Current status of the authentication attempt",
            "enum": [
              "PENDING",
              "READ",
              "INVALID",
              "REJECTED",
              "ACCEPTED",
              "EXPIRED"
            ],
            "example": "PENDING"
          },
          "authAttemptChallenge": {
            "type": "integer",
            "format": "int32",
            "description": "Numeric challenge displayed to user for verification (null if not requested)",
            "example": 123456
          },
          "authAttemptProofToken": {
            "type": "string",
            "description": "Signed JWT proof token (present only when status is ACCEPTED)"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp with timezone",
            "example": "2025-01-27T10:00:00+01:00"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Expiration timestamp with timezone",
            "example": "2025-01-27T10:05:00+01:00"
          },
          "contextTitle": {
            "type": "string",
            "description": "Short title for the approval request (null if no context provided)",
            "example": "Payment Approval"
          },
          "contextMessage": {
            "type": "string",
            "description": "Descriptive approval message (null if no context provided)",
            "example": "Authorize payment batch #1497 to Acme Corp for $1,400"
          },
          "demoMitmSignatureEnabled": {
            "type": "boolean",
            "description": "Demo MITM opt-in at creation time (Pending tampering only when Auth API demo flag is on)",
            "example": false
          }
        },
        "required": [
          "authAttemptId",
          "authAttemptStatus",
          "createdAt",
          "enrollmentId",
          "expiresAt"
        ]
      },
      "ArchiveSealRequest": {
        "type": "object",
        "properties": {
          "periodStart": {
            "type": "string",
            "format": "date-time"
          },
          "periodEnd": {
            "type": "string",
            "format": "date-time"
          },
          "checkpointIdFrom": {
            "type": "integer",
            "format": "int64"
          },
          "checkpointIdTo": {
            "type": "integer",
            "format": "int64"
          },
          "justification": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10
          }
        },
        "required": [
          "justification"
        ]
      },
      "ArchiveSealResult": {
        "type": "object",
        "properties": {
          "periodStart": {
            "type": "string",
            "format": "date-time"
          },
          "periodEnd": {
            "type": "string",
            "format": "date-time"
          },
          "checkpointsSealed": {
            "type": "integer",
            "format": "int32"
          },
          "sealChainHmac": {
            "type": "string"
          },
          "auditLogId": {
            "type": "integer",
            "format": "int64"
          },
          "justification": {
            "type": "string"
          }
        }
      },
      "DeclareAuditChainIncidentRequest": {
        "type": "object",
        "properties": {
          "justification": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10
          },
          "rootCause": {
            "type": "string",
            "enum": [
              "ADMIN_API_DOWN",
              "SCHEDULER_FAILURE",
              "DB_UNAVAILABLE",
              "NETWORK_PARTITION",
              "MISCONFIGURATION",
              "UNKNOWN"
            ]
          }
        },
        "required": [
          "justification",
          "rootCause"
        ]
      },
      "AuditChainIncidentResponseDto": {
        "type": "object",
        "description": "Operational audit-chain heartbeat incident summary",
        "properties": {
          "incidentId": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "type": "string",
            "enum": [
              "IN_PROGRESS",
              "RECOVERED_PENDING_DECLARATION",
              "CLOSED"
            ]
          },
          "anchorCheckpointId": {
            "type": "integer",
            "format": "int64"
          },
          "staleSince": {
            "type": "string",
            "format": "date-time"
          },
          "degradedSince": {
            "type": "string",
            "format": "date-time"
          },
          "recoveredAt": {
            "type": "string",
            "format": "date-time"
          },
          "justification": {
            "type": "string"
          },
          "rootCause": {
            "type": "string",
            "enum": [
              "ADMIN_API_DOWN",
              "SCHEDULER_FAILURE",
              "DB_UNAVAILABLE",
              "NETWORK_PARTITION",
              "MISCONFIGURATION",
              "UNKNOWN"
            ]
          },
          "declaredAt": {
            "type": "string",
            "format": "date-time"
          },
          "declaredByAdminId": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "GapDeclarationRequest": {
        "type": "object",
        "properties": {
          "gapStart": {
            "type": "string",
            "format": "date-time"
          },
          "anchorCheckpointId": {
            "type": "integer",
            "format": "int64"
          },
          "gapEnd": {
            "type": "string",
            "format": "date-time"
          },
          "justification": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10
          }
        },
        "required": [
          "justification"
        ]
      },
      "GapDeclarationResult": {
        "type": "object",
        "properties": {
          "gapStart": {
            "type": "string",
            "format": "date-time"
          },
          "gapEnd": {
            "type": "string",
            "format": "date-time"
          },
          "gapCheckpointId": {
            "type": "integer",
            "format": "int64"
          },
          "gapChainHmac": {
            "type": "string"
          },
          "auditLogId": {
            "type": "integer",
            "format": "int64"
          },
          "justification": {
            "type": "string"
          }
        }
      },
      "ArchiveConfirmArchivedRequest": {
        "type": "object",
        "properties": {
          "periodStart": {
            "type": "string",
            "format": "date-time"
          },
          "periodEnd": {
            "type": "string",
            "format": "date-time"
          },
          "checkpointIdFrom": {
            "type": "integer",
            "format": "int64"
          },
          "checkpointIdTo": {
            "type": "integer",
            "format": "int64"
          },
          "exportBundleDigest": {
            "type": "string",
            "maxLength": 88,
            "minLength": 16
          },
          "archivedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "exportBundleDigest"
        ]
      },
      "ArchiveConfirmArchivedResult": {
        "type": "object",
        "properties": {
          "periodStart": {
            "type": "string",
            "format": "date-time"
          },
          "periodEnd": {
            "type": "string",
            "format": "date-time"
          },
          "checkpointsExported": {
            "type": "integer",
            "format": "int32"
          },
          "exportBundleDigest": {
            "type": "string"
          },
          "exportedAt": {
            "type": "string",
            "format": "date-time"
          },
          "auditLogId": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ApiKeyCreateRequestDto": {
        "type": "object",
        "description": "Request to create a new API key for an integration",
        "properties": {
          "integrationId": {
            "type": "integer",
            "format": "int32",
            "description": "Integration ID to create the API key for",
            "example": 123
          },
          "description": {
            "type": "string",
            "description": "Optional human-readable description to identify this API key (e.g., 'Production Server')",
            "example": "Production Server API Key",
            "maxLength": 255,
            "minLength": 0
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional expiration date for automatic key rotation enforcement (null = no expiration). Must be in the future.",
            "example": "2025-12-31T23:59:59Z"
          },
          "ipWhitelist": {
            "type": "array",
            "description": "Optional array of IP addresses or CIDR ranges allowed to use this key (recommended for production)",
            "example": [
              "192.168.1.0/24",
              "10.0.0.100"
            ],
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "integrationId"
        ]
      },
      "ApiKeyCreateResponseDto": {
        "type": "object",
        "description": "Response containing newly created API key pair with secret key shown ONCE",
        "properties": {
          "apiKeyId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier for the API key record",
            "example": 42
          },
          "integrationKey": {
            "type": "string",
            "description": "Public integration key (safe to display, used as HTTP Basic Auth username)",
            "example": "ezkey_ikey_a1b2c3d4e5f6g7h8i9j0"
          },
          "secretKey": {
            "type": "string",
            "description": "Secret key (SHOWN ONCE ONLY - save immediately! Used as HTTP Basic Auth password)",
            "example": "ezkey_skey_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0"
          },
          "description": {
            "type": "string",
            "description": "Optional description to identify this API key",
            "example": "Production Server API Key"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp in UTC",
            "example": "2025-10-17T10:30:00Z"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional expiration date (null = no expiration)",
            "example": "2025-12-31T23:59:59Z"
          },
          "ipWhitelist": {
            "type": "array",
            "description": "Optional IP whitelist (null = no restrictions)",
            "example": [
              "192.168.1.0/24",
              "10.0.0.100"
            ],
            "items": {
              "type": "string"
            }
          },
          "warning": {
            "type": "string",
            "description": "Security warning about saving the secret key",
            "example": "IMPORTANT: Save the secret key now. It will not be shown again."
          }
        }
      },
      "AdminCreateRequestDto": {
        "type": "object",
        "description": "Request DTO for creating an administrator",
        "properties": {
          "username": {
            "type": "string",
            "description": "Unique username for the administrator",
            "example": "john.doe",
            "maxLength": 50,
            "minLength": 3
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address (required for global admins, optional for tenant admins)",
            "example": "john.doe@example.com",
            "maxLength": 255,
            "minLength": 0
          },
          "phoneNumber": {
            "type": "string",
            "description": "Phone number (optional contact metadata; accepts common separators and is normalized to E.164 on write)",
            "example": "+1 514 555 1234",
            "maxLength": 50,
            "minLength": 0
          },
          "firstName": {
            "type": "string",
            "description": "First name (required for global admins, optional for tenant admins)",
            "example": "John",
            "maxLength": 100,
            "minLength": 0
          },
          "lastName": {
            "type": "string",
            "description": "Last name (required for global admins, optional for tenant admins)",
            "example": "Doe",
            "maxLength": 100,
            "minLength": 0
          },
          "tenantId": {
            "type": "integer",
            "format": "int32",
            "description": "Tenant ID (required for tenant admin creation, ignored for global admin)",
            "example": 1
          },
          "onboardingMode": {
            "type": "string",
            "description": "Onboarding mode. IMMEDIATE creates enrollment and recovery codes now. ACTIVATION_CODE creates a pending admin and returns a one-time activation code instead.",
            "enum": [
              "IMMEDIATE",
              "ACTIVATION_CODE"
            ],
            "example": "ACTIVATION_CODE"
          }
        },
        "required": [
          "username"
        ]
      },
      "EnrollmentResetRequestDto": {
        "type": "object",
        "properties": {
          "enrollmentId": {
            "type": "integer",
            "format": "int32"
          },
          "reason": {
            "type": "string",
            "maxLength": 500,
            "minLength": 10
          }
        },
        "required": [
          "enrollmentId"
        ]
      },
      "EnrollmentResetResponseDto": {
        "type": "object",
        "description": "Response for enrollment reset operation",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indicates if the reset was successful",
            "example": true
          },
          "enrollmentId": {
            "type": "integer",
            "format": "int32",
            "description": "The enrollment ID",
            "example": 123
          },
          "enrollmentProofToken": {
            "type": "string",
            "description": "New enrollment proof token for binding",
            "example": "ezkey_proof_a1b2c3d4e5f6g7h8i9j0"
          },
          "enrollmentChallenge": {
            "type": "integer",
            "format": "int32",
            "description": "New enrollment challenge code for verification",
            "example": 123456
          },
          "integrationId": {
            "type": "integer",
            "format": "int32",
            "description": "Integration ID for reference",
            "example": 456
          },
          "message": {
            "type": "string",
            "description": "Response message",
            "example": "Enrollment reset successfully. Old device unbound. Use these credentials to bind new device."
          }
        }
      },
      "AdminRecoveryRequestDto": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "maxLength": 50,
            "minLength": 3
          },
          "recoveryCode": {
            "type": "string",
            "minLength": 1,
            "pattern": "^\\d{4}-\\d{4}-\\d{4}-\\d{4}-\\d{4}-\\d{4}-\\d{4}-\\d{4}$"
          }
        },
        "required": [
          "recoveryCode",
          "username"
        ]
      },
      "AdminRecoveryResponseDto": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          },
          "recoveryToken": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "codesRemaining": {
            "type": "integer",
            "format": "int32"
          },
          "enrollmentId": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "AdminPasswordlessWaitRequestDto": {
        "type": "object",
        "properties": {
          "authAttemptId": {
            "type": "integer",
            "format": "int32"
          },
          "challengeCode": {
            "type": "integer",
            "format": "int32"
          }
        },
        "required": [
          "authAttemptId"
        ]
      },
      "AdminLoginResponseDto": {
        "type": "object",
        "description": "Response DTO for passwordless administrator login",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indicates if the authentication was successful",
            "example": true
          },
          "message": {
            "type": "string",
            "description": "Response message describing authentication result",
            "example": "Authentication successful"
          },
          "status": {
            "type": "string",
            "description": "Authentication attempt status",
            "enum": [
              "pending",
              "accepted",
              "rejected"
            ],
            "example": "pending"
          },
          "token": {
            "type": "string",
            "description": "Bearer token for authenticated API requests. Omitted when the API issues an HttpOnly session cookie (browser split UI/API).",
            "example": "ezkey_abc123def456..."
          },
          "adminType": {
            "type": "string",
            "description": "Type of administrator",
            "enum": [
              "GLOBAL_ADMIN",
              "TENANT_ADMIN",
              "INTEGRATION_ADMIN"
            ],
            "example": "GLOBAL_ADMIN"
          },
          "username": {
            "type": "string",
            "description": "Administrator username",
            "example": "admin"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Expiration timestamp (UTC). When authentication succeeded: bearer token expiry. When status is pending (two-step passwordless): authentication attempt expiry — matches the persisted attempt and core setting ezkey.core.auth-attempt.ttl-seconds (not a fixed duration).",
            "example": "2025-10-15T14:30:00+01:00"
          },
          "authAttemptId": {
            "type": "integer",
            "format": "int32",
            "description": "Authentication attempt ID for two-step flow",
            "example": 123
          },
          "challengeCode": {
            "type": "integer",
            "format": "int32",
            "description": "6-digit challenge code for device verification",
            "example": 654321
          },
          "adminId": {
            "type": "integer",
            "format": "int32",
            "description": "Administrator ID for the authenticated session",
            "example": 2
          },
          "tenantId": {
            "type": "integer",
            "format": "int32",
            "description": "Tenant scope ID when the administrator is tenant- or integration-scoped; null for global administrators",
            "example": 3
          },
          "csrfToken": {
            "type": "string",
            "description": "Non-secret CSRF token to send in X-CSRF-TOKEN for cookie-authenticated unsafe requests. Present only in browser session cookie mode."
          }
        }
      },
      "AdminLoginRequestDto": {
        "type": "object",
        "description": "Request DTO for passwordless administrator login",
        "properties": {
          "username": {
            "type": "string",
            "description": "Administrator username for passwordless authentication",
            "example": "admin",
            "maxLength": 50,
            "minLength": 3
          },
          "challengeRequested": {
            "type": "boolean",
            "description": "Request challenge verification on device (6-digit code). When true, returns authAttemptId and challengeCode for two-step flow",
            "example": false
          },
          "nonBlocking": {
            "type": "boolean",
            "description": "Request immediate response with authAttemptId and expiresAt instead of blocking until device responds. Allows client to display countdown timer and poll /passwordless-wait endpoint. When false (default), blocking wait is used when no challenge is required (backward compatible). This flag has no effect when challenge is required (challenge flow is always non-blocking).",
            "example": false
          }
        },
        "required": [
          "username"
        ]
      },
      "AdminActivationRequestDto": {
        "type": "object",
        "properties": {
          "activationCode": {
            "type": "string",
            "minLength": 1,
            "pattern": "^ezkey_activation_[A-Za-z0-9]+$"
          }
        },
        "required": [
          "activationCode"
        ]
      },
      "AdminActivationResponseDto": {
        "type": "object",
        "description": "Response for first-time administrator activation",
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Indicates whether activation succeeded",
            "example": true
          },
          "message": {
            "type": "string",
            "description": "Response message"
          },
          "username": {
            "type": "string",
            "description": "Activated administrator username",
            "example": "pending.admin"
          },
          "enrollmentId": {
            "type": "integer",
            "format": "int32",
            "description": "Enrollment ID created during activation",
            "example": 123
          },
          "enrollmentProofToken": {
            "type": "string",
            "description": "Enrollment proof token shown once for binding",
            "example": "ezkey_proof_a1b2c3d4e5f6g7h8i9j0"
          },
          "enrollmentChallenge": {
            "type": "integer",
            "format": "int32",
            "description": "Enrollment challenge code shown once for binding",
            "example": 123456
          },
          "recoveryCodes": {
            "type": "array",
            "description": "Recovery codes are intentionally omitted from this unauthenticated activation response and must be revealed later through an authenticated recovery-code management flow",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "EnrollmentUpdateRequestDto": {
        "type": "object",
        "description": "Request DTO for partial update of enrollment metadata",
        "properties": {
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version from GET response. When provided, update fails with 409 if resource was modified since last fetch.",
            "example": 0
          },
          "enrollmentName": {
            "type": "string",
            "description": "Human-readable name for the enrollment",
            "example": "John's iPhone",
            "maxLength": 255,
            "minLength": 0
          },
          "contactEmail": {
            "type": "string",
            "description": "Optional contact email for the end-user (validated when non-blank; use clearContactEmail to remove)",
            "example": "john@example.com",
            "maxLength": 255,
            "minLength": 0
          },
          "contactPhoneNumber": {
            "type": "string",
            "description": "Optional contact phone number for the end-user (accepts common separators and is normalized to E.164 on write)",
            "example": "+1 514 555 1234",
            "maxLength": 50,
            "minLength": 0
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional expiration timestamp (must be in future). Null = no expiration."
          },
          "authAttemptChallengeRequired": {
            "type": "boolean",
            "description": "Whether authentication attempts require challenge",
            "example": false
          },
          "userIdentifier": {
            "type": "string",
            "description": "Optional user identifier from the integrating application",
            "maxLength": 255,
            "minLength": 0
          },
          "clearContactEmail": {
            "type": "boolean",
            "description": "When true, clears contact email. Takes precedence over contactEmail in the same request."
          },
          "clearExpiresAt": {
            "type": "boolean",
            "description": "When true, clears invitation expiry (expiresAt). Ignored if expiresAt is set to a non-null instant in the same request."
          }
        }
      },
      "EnrollmentResponseDto": {
        "type": "object",
        "description": "Response DTO containing complete enrollment information for administrative purposes",
        "properties": {
          "enrollmentId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier for the enrollment",
            "example": 123
          },
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version. Include in PATCH requests to prevent concurrent update",
            "example": 0
          },
          "integrationId": {
            "type": "integer",
            "format": "int32",
            "description": "Integration identifier this enrollment belongs to",
            "example": 1
          },
          "enrollmentName": {
            "type": "string",
            "description": "Human-readable name for the enrollment",
            "example": "John's iPhone"
          },
          "enrollmentStatus": {
            "type": "string",
            "description": "Enrollment lifecycle status",
            "enum": [
              "CREATED",
              "BOUND",
              "VERIFIED",
              "INVALID",
              "REVOKED",
              "EXPIRED"
            ],
            "example": "VERIFIED"
          },
          "enrollmentActive": {
            "type": "boolean",
            "description": "Flag indicating if the enrollment is currently active",
            "example": true
          },
          "enrollmentChallenge": {
            "type": "integer",
            "format": "int32",
            "description": "Challenge value for enrollment verification",
            "example": 123456
          },
          "enrollmentProofToken": {
            "type": "string",
            "description": "Unique code for enrollment verification",
            "example": "EZK-ABC123-DEF456"
          },
          "authAttemptChallengeRequired": {
            "type": "boolean",
            "description": "Flag indicating if authentication attempts require challenge",
            "example": false
          },
          "integrationPublicKey": {
            "type": "string",
            "description": "Public key for integration communication"
          },
          "devicePublicKey": {
            "type": "string",
            "description": "Public key for the device"
          },
          "devicePrivateKeyStorageTier": {
            "type": "string",
            "description": "Client-reported device private key storage tier at verify (NONE, STANDARD, STRONG); null if unknown or legacy",
            "enum": [
              "NONE",
              "STANDARD",
              "STRONG"
            ]
          },
          "verifiedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When enrollment was verified (device completed binding)"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional expiration for pending enrollment (CREATED/BOUND); null = no expiration"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the enrollment row was created (audit / sorting)"
          },
          "createdByAdminId": {
            "type": "integer",
            "format": "int32",
            "description": "Admin who created this enrollment (null when via API key)"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When enrollment was last used for successful authentication"
          },
          "contactEmail": {
            "type": "string",
            "description": "Optional contact email for the end-user"
          },
          "contactPhoneNumber": {
            "type": "string",
            "description": "Optional contact phone number for the end-user in canonical E.164 format"
          },
          "userIdentifier": {
            "type": "string",
            "description": "Optional user identifier from the integrating application"
          },
          "deactivatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the enrollment was deactivated (reversible soft-disable); null if never"
          },
          "deactivatedByAdminId": {
            "type": "integer",
            "format": "int32",
            "description": "Admin who deactivated this enrollment; null if never deactivated"
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the enrollment was permanently revoked; null if never"
          },
          "revokedByAdminId": {
            "type": "integer",
            "format": "int32",
            "description": "Admin who revoked this enrollment; null if never revoked"
          },
          "integrationName": {
            "type": "string",
            "description": "Display name for the enrollment's integration (e.g. Ezkey System); populated on GET by ID"
          },
          "isSystemIntegration": {
            "type": "boolean",
            "description": "Whether this enrollment's integration is the system integration; populated on GET by ID"
          },
          "operational": {
            "type": "boolean",
            "description": "Whether the enrollment is currently operational: VERIFIED status, active flag true, and (when integration context is available) full parent chain also operational",
            "example": true
          }
        }
      },
      "ApiKeyUpdateRequestDto": {
        "type": "object",
        "description": "Request DTO for partial update of API key configuration",
        "properties": {
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version from GET response. When provided, update fails with 409 if resource was modified since last fetch.",
            "example": 0
          },
          "ipWhitelist": {
            "type": "array",
            "description": "IP whitelist (null or empty = no restrictions). Each entry: IP address or CIDR (e.g. 192.168.1.0/24)",
            "example": [
              "192.168.1.0/24",
              "10.0.0.100"
            ],
            "items": {
              "type": "string"
            }
          },
          "description": {
            "type": "string",
            "description": "Human-readable description for this API key",
            "example": "Production Server API Key",
            "maxLength": 255,
            "minLength": 0
          }
        }
      },
      "ApiKeyResponseDto": {
        "type": "object",
        "description": "Response containing API key details (secret key NOT included)",
        "properties": {
          "apiKeyId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier for the API key record",
            "example": 42
          },
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version. Include in PATCH requests to prevent concurrent update",
            "example": 0
          },
          "integrationId": {
            "type": "integer",
            "format": "int32",
            "description": "Integration ID this API key authenticates for",
            "example": 123
          },
          "integrationKey": {
            "type": "string",
            "description": "Public integration key (safe to display)",
            "example": "ezkey_ikey_a1b2c3d4e5f6g7h8i9j0"
          },
          "description": {
            "type": "string",
            "description": "Optional description to identify this API key",
            "example": "Production Server API Key"
          },
          "active": {
            "type": "boolean",
            "description": "Whether the key is active (false if revoked)",
            "example": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Creation timestamp in UTC",
            "example": "2025-10-17T10:30:00Z"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Optional expiration date (null = no expiration)",
            "example": "2025-12-31T23:59:59Z"
          },
          "lastUsedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Last successful authentication timestamp (null if never used)",
            "example": "2025-10-17T15:45:30Z"
          },
          "ipWhitelist": {
            "type": "array",
            "description": "Optional IP whitelist (null = no restrictions)",
            "example": [
              "192.168.1.0/24",
              "10.0.0.100"
            ],
            "items": {
              "type": "string"
            }
          },
          "revokedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Revocation timestamp (null if active)",
            "example": "2025-10-17T16:00:00Z"
          },
          "revokedByUsername": {
            "type": "string",
            "description": "Admin who revoked this key (null if active)",
            "example": "admin"
          },
          "operational": {
            "type": "boolean",
            "description": "Whether this API key is fully operational (active, not expired, integration and tenant also active)",
            "example": true
          }
        }
      },
      "AdminUpdateRequestDto": {
        "type": "object",
        "description": "Request DTO for partial update of administrator profile",
        "properties": {
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version from GET response. When provided, update fails with 409 if resource was modified since last fetch.",
            "example": 0
          },
          "firstName": {
            "type": "string",
            "description": "First name of the administrator",
            "example": "John",
            "maxLength": 100,
            "minLength": 0
          },
          "lastName": {
            "type": "string",
            "description": "Last name of the administrator",
            "example": "Doe",
            "maxLength": 100,
            "minLength": 0
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "Email address (must be unique)",
            "example": "john.doe@example.com",
            "maxLength": 255,
            "minLength": 0
          },
          "phoneNumber": {
            "type": "string",
            "description": "Phone number for the administrator. Accepts common separators and is normalized to E.164 on write.",
            "example": "+1 514 555 1234",
            "maxLength": 50,
            "minLength": 0
          },
          "challengeRequired": {
            "type": "boolean",
            "description": "Whether challenge verification is required during passwordless login",
            "example": false
          }
        }
      },
      "AdminResponseDto": {
        "type": "object",
        "description": "Response DTO containing administrator information for listing purposes",
        "properties": {
          "adminId": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier for the administrator",
            "example": 1
          },
          "version": {
            "type": "integer",
            "format": "int64",
            "description": "Optimistic lock version. Include in PATCH requests to prevent concurrent update conflicts.",
            "example": 0
          },
          "username": {
            "type": "string",
            "description": "Username for the administrator",
            "example": "john.doe"
          },
          "email": {
            "type": "string",
            "description": "Email address",
            "example": "john.doe@example.com"
          },
          "phoneNumber": {
            "type": "string",
            "description": "Phone number stored in canonical E.164 format",
            "example": "+15145551234"
          },
          "firstName": {
            "type": "string",
            "description": "First name",
            "example": "John"
          },
          "lastName": {
            "type": "string",
            "description": "Last name",
            "example": "Doe"
          },
          "adminType": {
            "type": "string",
            "description": "Type of administrator",
            "enum": [
              "GLOBAL_ADMIN",
              "TENANT_ADMIN",
              "INTEGRATION_ADMIN"
            ],
            "example": "TENANT_ADMIN"
          },
          "tenantId": {
            "type": "integer",
            "format": "int32",
            "description": "Tenant ID (null for global admins)",
            "example": 1
          },
          "tenantName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Tenant display name from the tenant record (null for global administrators)",
            "example": "Acme Corp"
          },
          "enrollmentId": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Enrollment ID for MFA (passwordless admin identity). Null if not linked to an enrollment.",
            "example": 123
          },
          "active": {
            "type": "boolean",
            "description": "Flag indicating if the administrator is currently active",
            "example": true
          },
          "lifecycleStatus": {
            "type": "string",
            "description": "Explicit lifecycle status for the administrator account",
            "enum": [
              "PENDING_ACTIVATION",
              "ACTIVE",
              "DEACTIVATED"
            ],
            "example": "ACTIVE"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the administrator was created",
            "example": "2025-10-15T14:30:00Z"
          },
          "lastLoginAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Timestamp of last successful login (null if never logged in)",
            "example": "2025-10-20T09:15:00Z"
          },
          "hasRecoveryCodes": {
            "type": "boolean",
            "description": "Whether this administrator currently has a recovery-code set stored server-side",
            "example": false
          },
          "operational": {
            "type": "boolean",
            "description": "Whether this administrator is fully operational (active and, for tenant admins, tenant also active)",
            "example": true
          }
        }
      },
      "PageMetadata": {
        "type": "object",
        "properties": {
          "size": {
            "type": "integer",
            "format": "int64"
          },
          "number": {
            "type": "integer",
            "format": "int64"
          },
          "totalElements": {
            "type": "integer",
            "format": "int64"
          },
          "totalPages": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "PagedModelTenantResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "PublicInstanceInfoResponseDto": {
        "type": "object",
        "description": "Public instance metadata (branding, optional public Auth API URL for QR alignment)",
        "properties": {
          "authApiPublicBaseUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Public base URL of the Auth API (same as authUrl in enrollment QR JSON when configured)",
            "example": "https://auth.example.com:8080"
          },
          "instanceName": {
            "type": "string",
            "description": "Instance / organization display name",
            "example": "Acme Corporation"
          },
          "instanceDescription": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional instance or organization description",
            "example": "Acme Corp Ezkey MFA"
          },
          "aboutUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "Optional URL for About / learn more (e.g. company instance page)",
            "example": "https://www.example.com/about-ezkey"
          }
        }
      },
      "IntegrationResponseDto": {
        "type": "object",
        "description": "Response DTO containing complete integration details",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int32",
            "description": "Unique identifier for the integration",
            "example": 1
          },
          "code": {
            "type": "string",
            "description": "Unique business identifier code for the integration",
            "example": "web-portal"
          },
          "tenantId": {
            "type": "integer",
            "format": "int32",
            "description": "Tenant ID that owns this integration",
            "example": 2
          },
          "lifecycleStatus": {
            "type": "string",
            "description": "Explicit integration lifecycle status",
            "enum": [
              "ACTIVE",
              "RETIRED"
            ],
            "example": "ACTIVE"
          },
          "operational": {
            "type": "boolean",
            "description": "Whether the integration is currently operational: ACTIVE lifecycle state and parent tenant active",
            "example": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when the integration was created (with timezone)",
            "example": "2025-01-15T10:30:00+01:00"
          },
          "name": {
            "type": "string",
            "description": "Display name for the integration",
            "example": "Web Portal"
          },
          "description": {
            "type": "string",
            "description": "Optional description of the integration"
          },
          "isSystemIntegration": {
            "type": "boolean",
            "description": "Whether this is the system integration (e.g. admin MFA); used by UI to adapt detail page"
          }
        }
      },
      "PagedModelIntegrationResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/IntegrationResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "PagedModelEnrollmentResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EnrollmentResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "EncryptionKeyResponse": {
        "type": "object",
        "description": "Encryption key row with derived lifecycle fields for operators.",
        "properties": {
          "keyId": {
            "type": "integer",
            "format": "int64",
            "description": "Unique key identifier (Tink keyset id)"
          },
          "keyStatus": {
            "type": "string",
            "description": "PRIMARY, ENABLED, DISABLED, or PENDING"
          },
          "algorithm": {
            "type": "string",
            "description": "Algorithm label, e.g. AES256_GCM"
          },
          "introducedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When the key was introduced"
          },
          "promotedPrimaryAt": {
            "type": "string",
            "format": "date-time",
            "description": "When promoted to PRIMARY, if applicable"
          },
          "disabledAt": {
            "type": "string",
            "format": "date-time",
            "description": "When disabled, if applicable"
          },
          "recordsEncrypted": {
            "type": "integer",
            "format": "int64",
            "description": "Migration baseline: ciphertext units when key became ENABLED (demotion); 0 while PRIMARY"
          },
          "recordsReencrypted": {
            "type": "integer",
            "format": "int64",
            "description": "Cumulative ciphertext units re-encrypted off this key (completed batches; reset at demotion)"
          },
          "createdBy": {
            "type": "string",
            "description": "Creator label (SYSTEM or admin)"
          },
          "notes": {
            "type": "string",
            "description": "Optional operator notes"
          },
          "lifecycleStage": {
            "type": "string",
            "description": "Derived lifecycle stage (e.g. PRIMARY, ENABLED_IN_USE, DRAINED, DISABLED)"
          },
          "remainingRecords": {
            "type": "integer",
            "format": "int64",
            "description": "Derived ciphertext units (prefix scan): ENABLED = migration backlog; PRIMARY = current live volume; null when not applicable"
          },
          "remainingTargets": {
            "type": "integer",
            "format": "int32",
            "description": "Targets with rows counted for this key; null when not applicable"
          },
          "lastVerifiedAt": {
            "type": "string",
            "format": "date-time",
            "description": "When this snapshot was computed"
          },
          "verificationState": {
            "type": "string",
            "description": "Verification outcome (e.g. NOT_APPLICABLE, VERIFIED_ZERO)"
          },
          "decommissionEligible": {
            "type": "boolean",
            "description": "True when drained and ready for a future decommission workflow"
          },
          "incompleteMigrationBatches": {
            "type": "boolean",
            "description": "True when migration batches for this key are not all completed"
          }
        }
      },
      "PagedModelEncryptionKeyResponse": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EncryptionKeyResponse"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "PagedModelReencryptionBatchResponse": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ReencryptionBatchResponse"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "ReencryptionBatchResponse": {
        "type": "object",
        "properties": {
          "batchId": {
            "type": "integer",
            "format": "int32"
          },
          "targetTable": {
            "type": "string"
          },
          "targetColumn": {
            "type": "string"
          },
          "oldKeyId": {
            "type": "integer",
            "format": "int64"
          },
          "newKeyId": {
            "type": "integer",
            "format": "int64"
          },
          "status": {
            "type": "string"
          },
          "recordsTotal": {
            "type": "integer",
            "format": "int32"
          },
          "recordsDone": {
            "type": "integer",
            "format": "int32"
          },
          "recordsFailed": {
            "type": "integer",
            "format": "int32"
          },
          "recordsSkipped": {
            "type": "integer",
            "format": "int32"
          },
          "progressPct": {
            "type": "number"
          },
          "startedAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "errorMessage": {
            "type": "string"
          },
          "retryCount": {
            "type": "integer",
            "format": "int32"
          },
          "shardIndex": {
            "type": "integer",
            "format": "int32"
          },
          "shardCount": {
            "type": "integer",
            "format": "int32"
          }
        }
      },
      "DashboardAlertItemDto": {
        "type": "object",
        "description": "Admin console alert for dashboard overview (Global Admin only)",
        "properties": {
          "alertId": {
            "type": "integer",
            "format": "int64"
          },
          "alertType": {
            "type": "string",
            "enum": [
              "AUDIT_CHAIN_GAP_PENDING",
              "AUDIT_CHAIN_HEARTBEAT_STALE"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "INFO",
              "WARNING",
              "CRITICAL"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "OPEN",
              "RESOLVED"
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "payload": {
            "type": "string",
            "description": "Producer-defined JSON payload (string). Shape depends on alertType; clients aware of the type render structured fields."
          }
        }
      },
      "DashboardAuth24hStatsDto": {
        "type": "object",
        "description": "Auth attempt counts and terminal-outcome rates in the last 24h (dashboard)",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int64",
            "description": "All attempts created in the rolling 24h window"
          },
          "pending": {
            "type": "integer",
            "format": "int64",
            "description": "Attempts still pending on the device"
          },
          "readCount": {
            "type": "integer",
            "format": "int64",
            "description": "Attempts claimed by the device (read) but not yet completed"
          },
          "accepted": {
            "type": "integer",
            "format": "int64",
            "description": "User approved"
          },
          "rejected": {
            "type": "integer",
            "format": "int64",
            "description": "User explicitly denied"
          },
          "invalid": {
            "type": "integer",
            "format": "int64",
            "description": "Cryptographic validation failed"
          },
          "expired": {
            "type": "integer",
            "format": "int64",
            "description": "Timed out or superseded"
          },
          "terminalTotal": {
            "type": "integer",
            "format": "int64",
            "description": "Terminal outcomes: accepted + rejected + invalid + expired (denominator for rate fields)"
          },
          "successRatePct": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Accepted as % of terminal outcomes; null if terminalTotal is 0"
          },
          "invalidRatePct": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Invalid as % of terminal outcomes; null if terminalTotal is 0"
          },
          "expiredRatePct": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Expired as % of terminal outcomes; null if terminalTotal is 0"
          },
          "rejectedRatePct": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int32",
            "description": "Rejected as % of terminal outcomes; null if terminalTotal is 0"
          }
        }
      },
      "DashboardEnrollmentStatsDto": {
        "type": "object",
        "description": "Operational enrollment counts (by status and active flag) for dashboard overview",
        "properties": {
          "verified": {
            "type": "integer",
            "format": "int64",
            "description": "Devices ready for MFA: VERIFIED + active=true"
          },
          "inProgress": {
            "type": "integer",
            "format": "int64",
            "description": "Onboarding in progress: CREATED or BOUND (any active state)"
          },
          "suspended": {
            "type": "integer",
            "format": "int64",
            "description": "Admin-disabled devices: VERIFIED + active=false"
          },
          "expired": {
            "type": "integer",
            "format": "int64",
            "description": "Timed out before verification: EXPIRED (any active state)"
          },
          "incidents": {
            "type": "integer",
            "format": "int64",
            "description": "Security events: INVALID or REVOKED (any active state)"
          }
        }
      },
      "DashboardIntegrationStatsDto": {
        "type": "object",
        "description": "Integration counts for dashboard overview",
        "properties": {
          "total": {
            "type": "integer",
            "format": "int64"
          },
          "active": {
            "type": "integer",
            "format": "int64"
          },
          "retired": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "DashboardOverviewDto": {
        "type": "object",
        "description": "Aggregated dashboard overview (stats, recent activity, optional alerts)",
        "properties": {
          "integrations": {
            "$ref": "#/components/schemas/DashboardIntegrationStatsDto"
          },
          "enrollments": {
            "$ref": "#/components/schemas/DashboardEnrollmentStatsDto"
          },
          "auth24h": {
            "$ref": "#/components/schemas/DashboardAuth24hStatsDto"
          },
          "recentActivity": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DashboardRecentActivityItemDto"
            }
          },
          "alerts": {
            "type": "array",
            "description": "Instance-level alerts (e.g. audit chain gap pending). Populated only for Global Admin.",
            "items": {
              "$ref": "#/components/schemas/DashboardAlertItemDto"
            }
          }
        }
      },
      "DashboardRecentActivityItemDto": {
        "type": "object",
        "description": "Recent audit log entry for dashboard overview",
        "properties": {
          "auditLogId": {
            "type": "integer",
            "format": "int64"
          },
          "eventType": {
            "type": "string"
          },
          "eventStatus": {
            "type": "string"
          },
          "eventAction": {
            "type": "string"
          },
          "apiName": {
            "type": "string"
          },
          "adminId": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PagedModelAuthAttemptDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuthAttemptDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "AuthAttemptWaitResponseDto": {
        "type": "object",
        "description": "Response from the wait endpoint after waiting for device authentication",
        "properties": {
          "authAttempt": {
            "$ref": "#/components/schemas/AuthAttemptDto",
            "description": "Current authentication attempt state"
          },
          "status": {
            "type": "string",
            "description": "Calculated authentication status",
            "enum": [
              "PENDING",
              "READ",
              "INVALID",
              "REJECTED",
              "ACCEPTED"
            ],
            "example": "ACCEPTED"
          },
          "completed": {
            "type": "boolean",
            "description": "Whether authentication process is complete",
            "example": true
          },
          "timeoutReached": {
            "type": "boolean",
            "description": "Whether wait ended due to timeout",
            "example": false
          },
          "waitDuration": {
            "type": "integer",
            "format": "int32",
            "description": "Actual duration waited in seconds",
            "example": 15
          },
          "completedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Timestamp when wait operation completed (with timezone)",
            "example": "2025-01-27T10:30:15+01:00"
          }
        },
        "required": [
          "authAttempt",
          "completed",
          "completedAt",
          "status",
          "timeoutReached",
          "waitDuration"
        ]
      },
      "AuditLogResponseDto": {
        "type": "object",
        "properties": {
          "auditLogId": {
            "type": "integer",
            "format": "int64"
          },
          "eventType": {
            "type": "string",
            "enum": [
              "ADMIN_LOGIN",
              "ADMIN_LOGOUT",
              "ADMIN_PASSWORD_CHANGE",
              "ADMIN_RECOVERY_USE",
              "ADMIN_RECOVERY_CODES_ISSUED",
              "ADMIN_RECOVERY_CODES_REGENERATED",
              "ADMIN_ACTIVATION",
              "ADMIN_ACTIVATION_CODE_REISSUED",
              "ADMIN_RECOVERY_ENROLLMENT_RESET",
              "ADMIN_CREATED",
              "ADMIN_PROFILE_UPDATED",
              "ADMIN_DEACTIVATED",
              "ADMIN_ACTIVATED",
              "ENROLLMENT_CREATED",
              "ENROLLMENT_UPDATED",
              "ENROLLMENT_DELETED",
              "ENROLLMENT_BIND",
              "ENROLLMENT_VERIFY",
              "ENROLLMENT_REVOKED",
              "ENROLLMENT_DEACTIVATED",
              "ENROLLMENT_REACTIVATED",
              "ENROLLMENT_AUTH_ATTEMPT_BLOCKED",
              "ENROLLMENT_EXPIRED",
              "AUTH_ATTEMPT_CREATED",
              "AUTH_ATTEMPT_PENDING",
              "AUTH_ATTEMPT_RESPOND",
              "AUTH_ATTEMPT_CANCELLED",
              "AUTH_ATTEMPT_EXPIRED",
              "API_KEY_CREATED",
              "API_KEY_UPDATED",
              "API_KEY_REVOKED",
              "API_KEY_EXPIRED",
              "API_KEY_AUTH_SUCCESS",
              "API_KEY_AUTH_FAILED",
              "API_KEY_IP_BLOCKED",
              "SYSTEM_ERROR",
              "KEY_INTRODUCED",
              "KEY_PROMOTED_PRIMARY",
              "KEY_DEMOTED",
              "KEY_DISABLED",
              "KEYSET_BACKUP_CREATED",
              "REENCRYPTION_STARTED",
              "REENCRYPTION_BATCH_PROGRESS",
              "REENCRYPTION_COMPLETED",
              "REENCRYPTION_FAILED",
              "REENCRYPTION_RESUMED",
              "REENCRYPTION_PAUSED",
              "INTEGRATION_CREATED",
              "INTEGRATION_UPDATED",
              "INTEGRATION_RETIRED",
              "INTEGRATION_DELETED",
              "TENANT_CREATED",
              "TENANT_UPDATED",
              "TENANT_DEACTIVATED",
              "TENANT_ACTIVATED",
              "EVALUATOR_SELF_REGISTRATION",
              "AUDIT_CHAIN_ARCHIVE_SEALED",
              "AUDIT_CHAIN_ARCHIVE_EXPORTED",
              "AUDIT_CHAIN_GAP_DECLARED",
              "AUDIT_CHAIN_INCIDENT_DECLARED",
              "ALERT_RAISED",
              "ALERT_RESOLVED"
            ]
          },
          "eventAction": {
            "type": "string"
          },
          "eventStatus": {
            "type": "string",
            "enum": [
              "SUCCESS",
              "FAILURE",
              "ERROR"
            ]
          },
          "apiName": {
            "type": "string",
            "enum": [
              "ADMIN_API",
              "AUTH_API",
              "INTEGRATION_API"
            ]
          },
          "ipAddress": {
            "type": "string"
          },
          "userAgent": {
            "type": "string"
          },
          "adminId": {
            "type": "integer",
            "format": "int32"
          },
          "integrationId": {
            "type": "integer",
            "format": "int32"
          },
          "enrollmentId": {
            "type": "integer",
            "format": "int32"
          },
          "authAttemptId": {
            "type": "integer",
            "format": "int32"
          },
          "tenantId": {
            "type": "integer",
            "format": "int32"
          },
          "targetAdminId": {
            "type": "integer",
            "format": "int32"
          },
          "eventDetails": {
            "type": "string"
          },
          "errorMessage": {
            "type": "string"
          },
          "instanceId": {
            "type": "string"
          },
          "entryHmac": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "reason": {
            "type": "string"
          }
        }
      },
      "PagedModelAuditLogResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditLogResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "IntegrityReport": {
        "type": "object",
        "properties": {
          "totalEntries": {
            "type": "integer",
            "format": "int64"
          },
          "validEntries": {
            "type": "integer",
            "format": "int64"
          },
          "invalidEntries": {
            "type": "integer",
            "format": "int64"
          },
          "unsignedEntries": {
            "type": "integer",
            "format": "int64"
          },
          "intact": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "AuditLogContextResponseDto": {
        "type": "object",
        "properties": {
          "anchorAuditLogId": {
            "type": "integer",
            "format": "int64"
          },
          "hasMoreBefore": {
            "type": "boolean"
          },
          "hasMoreAfter": {
            "type": "boolean"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditLogResponseDto"
            }
          }
        }
      },
      "PagedModelAuditChainIncidentResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditChainIncidentResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "ArchiveEligibilityResult": {
        "type": "object",
        "properties": {
          "externalArchivalEnabled": {
            "type": "boolean"
          },
          "confirmationRequired": {
            "type": "boolean"
          },
          "sealedCheckpointCount": {
            "type": "integer",
            "format": "int32"
          },
          "oldestSealedWindowStart": {
            "type": "string",
            "format": "date-time"
          },
          "newestSealedWindowEnd": {
            "type": "string",
            "format": "date-time"
          },
          "checkpointIdFrom": {
            "type": "integer",
            "format": "int64"
          },
          "checkpointIdTo": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "ChainVerificationReport": {
        "type": "object",
        "properties": {
          "totalCheckpoints": {
            "type": "integer",
            "format": "int32"
          },
          "validCheckpoints": {
            "type": "integer",
            "format": "int32"
          },
          "invalidCheckpoints": {
            "type": "integer",
            "format": "int32"
          },
          "archivedCheckpoints": {
            "type": "integer",
            "format": "int32"
          },
          "gapDeclaredCheckpoints": {
            "type": "integer",
            "format": "int32"
          },
          "violations": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "undeclaredGaps": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UndeclaredGap"
            }
          },
          "coverageStart": {
            "type": "string",
            "format": "date-time"
          },
          "coverageEnd": {
            "type": "string",
            "format": "date-time"
          },
          "effectiveFrom": {
            "type": "string",
            "format": "date-time"
          },
          "effectiveTo": {
            "type": "string",
            "format": "date-time"
          },
          "continuousCoverage": {
            "type": "boolean"
          },
          "intact": {
            "type": "boolean"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "UndeclaredGap": {
        "type": "object",
        "properties": {
          "gapStart": {
            "type": "string",
            "format": "date-time"
          },
          "gapEnd": {
            "type": "string",
            "format": "date-time"
          },
          "gapMinutes": {
            "type": "integer",
            "format": "int64"
          }
        }
      },
      "AuditChainCheckpointResponseDto": {
        "type": "object",
        "properties": {
          "checkpointId": {
            "type": "integer",
            "format": "int64"
          },
          "windowStart": {
            "type": "string",
            "format": "date-time"
          },
          "windowEnd": {
            "type": "string",
            "format": "date-time"
          },
          "entryCount": {
            "type": "integer",
            "format": "int32"
          },
          "firstEntryId": {
            "type": "integer",
            "format": "int64"
          },
          "lastEntryId": {
            "type": "integer",
            "format": "int64"
          },
          "entriesDigest": {
            "type": "string"
          },
          "prevChainHmac": {
            "type": "string"
          },
          "chainHmac": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lifecycleState": {
            "type": "string",
            "enum": [
              "ACTIVE",
              "SEALED",
              "EXPORTED",
              "PURGEABLE",
              "PURGED"
            ]
          },
          "checkpointType": {
            "type": "string",
            "enum": [
              "REGULAR",
              "ARCHIVE_SEAL",
              "GAP_DECLARATION"
            ]
          },
          "notes": {
            "type": "string"
          }
        }
      },
      "PagedModelAuditChainCheckpointResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuditChainCheckpointResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "PagedModelApiKeyResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ApiKeyResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "AlertResponseDto": {
        "type": "object",
        "description": "Operator-facing alert (read model).",
        "properties": {
          "alertId": {
            "type": "integer",
            "format": "int64"
          },
          "alertType": {
            "type": "string",
            "enum": [
              "AUDIT_CHAIN_GAP_PENDING",
              "AUDIT_CHAIN_HEARTBEAT_STALE"
            ]
          },
          "severity": {
            "type": "string",
            "enum": [
              "INFO",
              "WARNING",
              "CRITICAL"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "OPEN",
              "RESOLVED"
            ]
          },
          "dedupeKey": {
            "type": "string"
          },
          "payload": {
            "type": "string",
            "description": "Producer-defined JSON payload (string). Shape depends on alertType; clients aware of the type render structured fields, others fall back to raw display."
          },
          "occurrenceCount": {
            "type": "integer",
            "format": "int32"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastSeenAt": {
            "type": "string",
            "format": "date-time"
          },
          "resolvedAt": {
            "type": "string",
            "format": "date-time"
          },
          "resolvedByAdminId": {
            "type": "integer",
            "format": "int32"
          },
          "resolutionReason": {
            "type": "string",
            "enum": [
              "GAP_DECLARED",
              "HEARTBEAT_RESTORED",
              "MANUAL"
            ]
          }
        }
      },
      "PagedModelAlertResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AlertResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "PagedModelAdminResponseDto": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AdminResponseDto"
            }
          },
          "page": {
            "$ref": "#/components/schemas/PageMetadata"
          }
        }
      },
      "AdminSessionResponseDto": {
        "type": "object",
        "description": "Current administrator session metadata",
        "properties": {
          "username": {
            "type": "string",
            "description": "Administrator username",
            "example": "admin"
          },
          "adminType": {
            "type": "string",
            "description": "Type of administrator",
            "enum": [
              "GLOBAL_ADMIN",
              "TENANT_ADMIN",
              "INTEGRATION_ADMIN"
            ],
            "example": "GLOBAL_ADMIN"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "description": "Current session expiration timestamp",
            "example": "2026-04-28T14:00:00Z"
          },
          "adminId": {
            "type": "integer",
            "format": "int32",
            "description": "Administrator ID for the authenticated session",
            "example": 2
          },
          "tenantId": {
            "type": "integer",
            "format": "int32",
            "description": "Tenant scope ID when applicable; null for global administrators"
          },
          "csrfToken": {
            "type": "string",
            "description": "Non-secret CSRF token to send in X-CSRF-TOKEN for cookie-authenticated unsafe requests"
          }
        }
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "description": "JWT authentication token for admin API",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "x-tagGroups": [
    {
      "name": "Getting started",
      "tags": [
        "Public",
        "Admin Authentication"
      ]
    },
    {
      "name": "Tenant and integration setup",
      "tags": [
        "Tenants",
        "Integrations",
        "Enrollments",
        "API Keys"
      ]
    },
    {
      "name": "MFA operations",
      "tags": [
        "Auth Attempts",
        "Admin Enrollment Management"
      ]
    },
    {
      "name": "Administration",
      "tags": [
        "Administrator Provisioning"
      ]
    },
    {
      "name": "Platform operations",
      "tags": [
        "Audit Logs",
        "Encryption Keys",
        "Alerts",
        "Dashboard"
      ]
    }
  ]
}
