{
  "openapi": "3.1.0",
  "info": {
    "title": "QAuth Auth Server API",
    "description": "OAuth 2.1 / OIDC 1.0 authorization server for MCP servers and AI agents: authorization_code + PKCE and client_credentials grants, RFC 8693 on-behalf-of agent delegation, and environment-aware authorization policy. Wallet federation (OID4VP) transport ships behind a default-off flag.",
    "version": "1.0.0"
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Access token obtained from login, refresh, or OAuth token endpoint."
      }
    },
    "schemas": {}
  },
  "paths": {
    "/health": {
      "get": {
        "tags": [
          "System"
        ],
        "description": "Health check endpoint. Returns database and Redis connectivity status. Used for liveness and readiness probes.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/metrics": {
      "get": {
        "tags": [
          "System"
        ],
        "description": "Prometheus metrics endpoint. Returns process/runtime metrics plus auth counters in Prometheus text exposition format.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/": {
      "get": {
        "tags": [
          "System"
        ],
        "description": "Root API endpoint. Returns a simple greeting to verify the auth server is running.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/.well-known/oauth-authorization-server": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "description": "OAuth 2.0 Authorization Server Metadata (RFC 8414). Unauthenticated, cacheable.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/.well-known/openid-configuration": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "description": "OpenID Connect Discovery 1.0 document. Superset of RFC 8414 AS metadata with OIDC-specific fields. Unauthenticated, cacheable.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "description": "JSON Web Key Set (RFC 7517) containing the active EdDSA public signing key(s). Used by clients and resource servers to verify JWT signatures.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/auth/link/wallet": {
      "post": {
        "tags": [
          "Auth"
        ],
        "description": "Start linking a wallet credential to the signed-in account. Requires a valid session cookie and an `X-CSRF-Token` header matching the per-session token returned by `GET /consents`. Issues an OID4VP 1.0 presentation request in LINKING mode: the validated response is bound to the caller's authenticated users.id and is never used to resolve or create an account (ADR-009 §5). Issue #238.",
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "handle": {
                      "type": "string"
                    },
                    "invocation_uri": {
                      "type": "string"
                    },
                    "expires_at": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "handle",
                    "invocation_uri",
                    "expires_at"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "404": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "500": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/auth/link/wallet/{handle}": {
      "get": {
        "tags": [
          "Auth"
        ],
        "description": "Poll a wallet-linking flow. Reports whether the direct_post presentation response has arrived, and COMPLETES the link when it has — writing a second user_credentials row (provider_type=wallet) under the same users.id. Issue #238.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "handle",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "linked",
                        "conflict",
                        "expired",
                        "rejected"
                      ]
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/auth/login": {
      "post": {
        "tags": [
          "Auth"
        ],
        "description": "Authenticate with email and password. Returns access token, refresh token, and expiration. Requires valid credentials.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "password": {
                    "type": "string"
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "access_token": {
                      "type": "string"
                    },
                    "refresh_token": {
                      "type": "string"
                    },
                    "expires_in": {
                      "type": "number"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    }
                  },
                  "required": [
                    "access_token",
                    "refresh_token",
                    "expires_in",
                    "token_type"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "tags": [
          "Auth"
        ],
        "description": "Log out the current user. Revokes all refresh tokens for the user. Accepts expired access tokens.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^Bearer .+$"
            },
            "in": "header",
            "name": "authorization",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "success": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    },
                    "message": {
                      "type": "string",
                      "enum": [
                        "Successfully logged out"
                      ]
                    }
                  },
                  "required": [
                    "success",
                    "message"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/auth/register": {
      "post": {
        "tags": [
          "Auth"
        ],
        "description": "Register a new user account. Creates user, sends verification email, and returns user data. Password must meet strength requirements.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  },
                  "password": {
                    "type": "string"
                  },
                  "realmId": {
                    "type": "string",
                    "format": "uuid",
                    "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                  }
                },
                "required": [
                  "email",
                  "password"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    },
                    "emailVerified": {
                      "type": "boolean"
                    },
                    "realmId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "updatedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "email",
                    "emailVerified",
                    "realmId",
                    "createdAt",
                    "updatedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/auth/resend-verification": {
      "post": {
        "tags": [
          "Auth"
        ],
        "description": "Request a new verification email. Rate limited per IP and per email. Always returns success to prevent email enumeration.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "format": "email",
                    "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                  }
                },
                "required": [
                  "email"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "message"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "429": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "error": {
                      "type": "string"
                    },
                    "statusCode": {
                      "type": "number"
                    }
                  },
                  "required": [
                    "error",
                    "statusCode"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/auth/verify": {
      "get": {
        "tags": [
          "Auth"
        ],
        "description": "Verify email address using token sent via email. Single-use; marks token as used. Returns success message.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 64,
              "maxLength": 64,
              "pattern": "^[0-9a-fA-F]{64}$"
            },
            "in": "query",
            "name": "token",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "message": {
                      "type": "string"
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    }
                  },
                  "required": [
                    "message",
                    "email"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/api/clients/": {
      "get": {
        "tags": [
          "Clients"
        ],
        "description": "List the OAuth clients owned by the authenticated developer. Scoped by oauth_clients.developer_id. Requires a developer Bearer access token. Never returns the client secret. (Phase 2.2, issue #85.)",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "clients": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "clientId": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "anyOf": [
                              {
                                "type": "string"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "redirectUris": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "grantTypes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "responseTypes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "tokenEndpointAuthMethod": {
                            "type": "string"
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "requirePkce": {
                            "type": "boolean"
                          },
                          "environment": {
                            "type": "string",
                            "enum": [
                              "development",
                              "staging",
                              "production"
                            ]
                          },
                          "staticApiKeysAllowed": {
                            "type": "boolean"
                          },
                          "createdAt": {
                            "type": "number"
                          },
                          "updatedAt": {
                            "type": "number"
                          },
                          "lastUsedAt": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "clientId",
                          "name",
                          "description",
                          "redirectUris",
                          "scopes",
                          "grantTypes",
                          "responseTypes",
                          "tokenEndpointAuthMethod",
                          "enabled",
                          "requirePkce",
                          "environment",
                          "staticApiKeysAllowed",
                          "createdAt",
                          "updatedAt",
                          "lastUsedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "clients"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "Clients"
        ],
        "description": "Create an OAuth client owned by the authenticated developer. The server generates the client_id and (for confidential clients) a client_secret; the plaintext secret is returned in THIS response only and never again. Requires a developer Bearer access token. (Phase 2.2, issue #86.)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "redirectUris": {
                    "default": [],
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "scopes": {
                    "default": [],
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "grantTypes": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "authorization_code",
                        "refresh_token",
                        "client_credentials"
                      ]
                    }
                  },
                  "responseTypes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "code"
                      ]
                    }
                  },
                  "tokenEndpointAuthMethod": {
                    "type": "string",
                    "enum": [
                      "client_secret_post",
                      "client_secret_basic",
                      "private_key_jwt",
                      "none"
                    ]
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "clientId": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "redirectUris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "grantTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "responseTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "tokenEndpointAuthMethod": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "requirePkce": {
                      "type": "boolean"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "staging",
                        "production"
                      ]
                    },
                    "staticApiKeysAllowed": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "updatedAt": {
                      "type": "number"
                    },
                    "lastUsedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "clientSecret": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "clientId",
                    "name",
                    "description",
                    "redirectUris",
                    "scopes",
                    "grantTypes",
                    "responseTypes",
                    "tokenEndpointAuthMethod",
                    "enabled",
                    "requirePkce",
                    "environment",
                    "staticApiKeysAllowed",
                    "createdAt",
                    "updatedAt",
                    "lastUsedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/api/clients/{id}": {
      "get": {
        "tags": [
          "Clients"
        ],
        "description": "Get one of the authenticated developer's OAuth clients by id. Returns 404 if the client does not exist or is owned by another developer (no existence enumeration). Never returns the client secret. (Phase 2.2, issue #87.)",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "clientId": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "redirectUris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "grantTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "responseTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "tokenEndpointAuthMethod": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "requirePkce": {
                      "type": "boolean"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "staging",
                        "production"
                      ]
                    },
                    "staticApiKeysAllowed": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "updatedAt": {
                      "type": "number"
                    },
                    "lastUsedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "clientId",
                    "name",
                    "description",
                    "redirectUris",
                    "scopes",
                    "grantTypes",
                    "responseTypes",
                    "tokenEndpointAuthMethod",
                    "enabled",
                    "requirePkce",
                    "environment",
                    "staticApiKeysAllowed",
                    "createdAt",
                    "updatedAt",
                    "lastUsedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Clients"
        ],
        "description": "Update mutable fields of one of the developer's OAuth clients (name, description, redirectUris, scopes, grantTypes, responseTypes, tokenEndpointAuthMethod, enabled). client_id and client_secret are immutable here. Returns 404 if the client does not exist or is owned by another developer. (Phase 2.2, issue #88.)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "description": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2000
                      },
                      {
                        "type": "null"
                      }
                    ]
                  },
                  "redirectUris": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "format": "uri"
                    }
                  },
                  "scopes": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "grantTypes": {
                    "minItems": 1,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "authorization_code",
                        "refresh_token",
                        "client_credentials"
                      ]
                    }
                  },
                  "responseTypes": {
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "code"
                      ]
                    }
                  },
                  "tokenEndpointAuthMethod": {
                    "type": "string",
                    "enum": [
                      "client_secret_post",
                      "client_secret_basic",
                      "private_key_jwt",
                      "none"
                    ]
                  },
                  "enabled": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "clientId": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "redirectUris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "grantTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "responseTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "tokenEndpointAuthMethod": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "requirePkce": {
                      "type": "boolean"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "staging",
                        "production"
                      ]
                    },
                    "staticApiKeysAllowed": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "updatedAt": {
                      "type": "number"
                    },
                    "lastUsedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "clientId",
                    "name",
                    "description",
                    "redirectUris",
                    "scopes",
                    "grantTypes",
                    "responseTypes",
                    "tokenEndpointAuthMethod",
                    "enabled",
                    "requirePkce",
                    "environment",
                    "staticApiKeysAllowed",
                    "createdAt",
                    "updatedAt",
                    "lastUsedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Clients"
        ],
        "description": "Delete one of the developer's OAuth clients. Returns 404 if the client does not exist or is owned by another developer. After deletion the client can no longer authenticate. (Phase 2.2, issue #89.)",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          }
        }
      }
    },
    "/api/clients/{id}/regenerate-secret": {
      "post": {
        "tags": [
          "Clients"
        ],
        "description": "Issue a new client_secret for one of the developer's OAuth clients. The previous secret is invalidated immediately and the new plaintext secret is returned in THIS response only. Returns 404 if the client does not exist or is owned by another developer; 400 for a public client that has no secret. (Phase 2.2, issue #90.)",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "clientId": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "redirectUris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "scopes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "grantTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "responseTypes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "tokenEndpointAuthMethod": {
                      "type": "string"
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "requirePkce": {
                      "type": "boolean"
                    },
                    "environment": {
                      "type": "string",
                      "enum": [
                        "development",
                        "staging",
                        "production"
                      ]
                    },
                    "staticApiKeysAllowed": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "updatedAt": {
                      "type": "number"
                    },
                    "lastUsedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "clientSecret": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "clientId",
                    "name",
                    "description",
                    "redirectUris",
                    "scopes",
                    "grantTypes",
                    "responseTypes",
                    "tokenEndpointAuthMethod",
                    "enabled",
                    "requirePkce",
                    "environment",
                    "staticApiKeysAllowed",
                    "createdAt",
                    "updatedAt",
                    "lastUsedAt",
                    "clientSecret"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/api/clients/{clientId}/api-keys": {
      "post": {
        "tags": [
          "API Keys"
        ],
        "description": "Mint a static developer API key for one of the developer's OAuth clients. ENVIRONMENT-GATED (ADR-008 §6): permitted only while the client resolves to a development environment; a staging/production (or unset-environment) client is refused with 403 and must use the OAuth client_credentials grant. The plaintext key is returned in THIS response only and never again. Returns 404 if the client does not exist or is owned by another developer. (Issue #97.)",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  }
                },
                "required": [
                  "name"
                ]
              }
            }
          }
        },
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "clientId",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "clientId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "prefix": {
                      "type": "string"
                    },
                    "last4": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "lastUsedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "revokedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "key": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "id",
                    "clientId",
                    "name",
                    "prefix",
                    "last4",
                    "createdAt",
                    "lastUsedAt",
                    "revokedAt",
                    "key"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "API Keys"
        ],
        "description": "List the static API keys for one of the developer's OAuth clients. Returns masked fields only (prefix + last4) — never the key or its hash. Includes revoked keys (with revokedAt set). Returns 404 if the client does not exist or is owned by another developer. (Issue #97.)",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "clientId",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "apiKeys": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "clientId": {
                            "type": "string",
                            "format": "uuid",
                            "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                          },
                          "name": {
                            "type": "string"
                          },
                          "prefix": {
                            "type": "string"
                          },
                          "last4": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": "number"
                          },
                          "lastUsedAt": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          },
                          "revokedAt": {
                            "anyOf": [
                              {
                                "type": "number"
                              },
                              {
                                "type": "null"
                              }
                            ]
                          }
                        },
                        "required": [
                          "id",
                          "clientId",
                          "name",
                          "prefix",
                          "last4",
                          "createdAt",
                          "lastUsedAt",
                          "revokedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "apiKeys"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/api/clients/{clientId}/api-keys/{keyId}": {
      "delete": {
        "tags": [
          "API Keys"
        ],
        "description": "Revoke one static API key for one of the developer's OAuth clients. Idempotent soft-delete: the row is retained with revokedAt set, and a revoked key never authenticates again. Returns 404 if the client or key does not exist or is owned by another developer. (Issue #97.)",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "clientId",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "keyId",
            "required": true
          }
        ],
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "clientId": {
                      "type": "string",
                      "format": "uuid",
                      "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
                    },
                    "name": {
                      "type": "string"
                    },
                    "prefix": {
                      "type": "string"
                    },
                    "last4": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": "number"
                    },
                    "lastUsedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    },
                    "revokedAt": {
                      "anyOf": [
                        {
                          "type": "number"
                        },
                        {
                          "type": "null"
                        }
                      ]
                    }
                  },
                  "required": [
                    "id",
                    "clientId",
                    "name",
                    "prefix",
                    "last4",
                    "createdAt",
                    "lastUsedAt",
                    "revokedAt"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/consents/": {
      "get": {
        "tags": [
          "Consents"
        ],
        "description": "List the active OAuth consents for the currently signed-in user. Drives the developer portal revocation screen (issue #150). The response also carries a per-session CSRF token that the caller MUST echo back as the `X-CSRF-Token` header on `DELETE /consents/:id`.",
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "consents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "clientId": {
                            "type": "string"
                          },
                          "clientName": {
                            "type": "string"
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "grantedAt": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "id",
                          "clientId",
                          "clientName",
                          "scopes",
                          "grantedAt"
                        ],
                        "additionalProperties": false
                      }
                    },
                    "csrfToken": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "consents",
                    "csrfToken"
                  ],
                  "additionalProperties": false
                }
              }
            }
          },
          "401": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "consents": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "clientId": {
                            "type": "string"
                          },
                          "clientName": {
                            "type": "string"
                          },
                          "scopes": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          },
                          "grantedAt": {
                            "type": "number"
                          }
                        },
                        "required": [
                          "id",
                          "clientId",
                          "clientName",
                          "scopes",
                          "grantedAt"
                        ],
                        "additionalProperties": false
                      }
                    }
                  },
                  "required": [
                    "consents"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/consents/{id}": {
      "delete": {
        "tags": [
          "Consents"
        ],
        "description": "Revoke an OAuth consent row owned by the currently signed-in user. Requires a valid `X-CSRF-Token` header whose value matches the session CSRF token returned by `GET /consents`.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
            },
            "in": "path",
            "name": "id",
            "required": true
          }
        ],
        "responses": {
          "204": {
            "description": "Default Response"
          },
          "401": {
            "description": "Default Response"
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "tags": [
          "OAuth",
          "Authorization"
        ],
        "description": "OAuth 2.1 authorization endpoint (GET). Issues an authorization code with PKCE and redirects to the client redirect_uri.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            },
            "in": "query",
            "name": "response_type",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "client_id",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "in": "query",
            "name": "redirect_uri",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 43,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._~-]+$"
            },
            "in": "query",
            "name": "code_challenge",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            },
            "in": "query",
            "name": "code_challenge_method",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "in": "query",
            "name": "state",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "in": "query",
            "name": "scope",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "in": "query",
            "name": "nonce",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "login",
                "consent"
              ]
            },
            "in": "query",
            "name": "prompt",
            "required": false
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 315360000
            },
            "in": "query",
            "name": "max_age",
            "required": false
          },
          {
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 2048,
                  "format": "uri"
                },
                {
                  "maxItems": 10,
                  "type": "array",
                  "items": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  }
                }
              ]
            },
            "in": "query",
            "name": "resource",
            "required": false
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      },
      "post": {
        "tags": [
          "OAuth",
          "Authorization"
        ],
        "description": "OAuth 2.1 authorization endpoint (POST). Identical to GET; parameters are form-encoded in the request body (OIDC Core §3.1.2.1).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "response_type": {
                    "type": "string",
                    "enum": [
                      "code"
                    ]
                  },
                  "client_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "redirect_uri": {
                    "type": "string",
                    "format": "uri"
                  },
                  "code_challenge": {
                    "type": "string",
                    "minLength": 43,
                    "maxLength": 128,
                    "pattern": "^[A-Za-z0-9._~-]+$"
                  },
                  "code_challenge_method": {
                    "type": "string",
                    "enum": [
                      "S256"
                    ]
                  },
                  "state": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "scope": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "nonce": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "prompt": {
                    "type": "string",
                    "enum": [
                      "none",
                      "login",
                      "consent"
                    ]
                  },
                  "max_age": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 315360000
                  },
                  "resource": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2048,
                        "format": "uri"
                      },
                      {
                        "maxItems": 10,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 2048,
                          "format": "uri"
                        }
                      }
                    ]
                  }
                },
                "required": [
                  "response_type",
                  "client_id",
                  "redirect_uri",
                  "code_challenge",
                  "code_challenge_method"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/oauth/introspect": {
      "post": {
        "tags": [
          "OAuth",
          "Introspection"
        ],
        "description": "RFC 7662 token introspection. Send access token and client credentials in application/x-www-form-urlencoded body. Returns active and claims when token is valid for the client.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 1
                  },
                  "token_type_hint": {
                    "type": "string",
                    "maxLength": 64
                  },
                  "client_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "client_secret": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "token"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "active": {
                      "type": "boolean"
                    },
                    "sub": {
                      "type": "string"
                    },
                    "client_id": {
                      "type": "string"
                    },
                    "exp": {
                      "type": "number"
                    },
                    "iat": {
                      "type": "number"
                    },
                    "iss": {
                      "type": "string"
                    },
                    "aud": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    },
                    "scope": {
                      "type": "string"
                    },
                    "token_type": {
                      "type": "string",
                      "enum": [
                        "Bearer"
                      ]
                    },
                    "pqc_signature": {
                      "type": "string"
                    },
                    "pqc_alg": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "active"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/oauth/register": {
      "post": {
        "tags": [
          "OAuth",
          "Registration"
        ],
        "description": "OAuth 2.0 Dynamic Client Registration (RFC 7591). Open-mode — no initial_access_token required. Scope requests are capped to the realm's dynamic_registration_allowed_scopes list.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "client_name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "redirect_uris": {
                    "maxItems": 20,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 2048
                    }
                  },
                  "grant_types": {
                    "maxItems": 8,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "authorization_code",
                        "refresh_token",
                        "client_credentials"
                      ]
                    }
                  },
                  "response_types": {
                    "maxItems": 4,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "code"
                      ]
                    }
                  },
                  "token_endpoint_auth_method": {
                    "type": "string",
                    "enum": [
                      "none",
                      "client_secret_basic",
                      "client_secret_post"
                    ]
                  },
                  "scope": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "client_uri": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "logo_uri": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "tos_uri": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "policy_uri": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  },
                  "contacts": {
                    "maxItems": 10,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "maxLength": 255,
                      "format": "email",
                      "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    }
                  },
                  "software_id": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "software_version": {
                    "type": "string",
                    "maxLength": 64
                  },
                  "is_agent": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "client_id": {
                      "type": "string"
                    },
                    "client_secret": {
                      "type": "string"
                    },
                    "client_id_issued_at": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "client_secret_expires_at": {
                      "type": "integer",
                      "minimum": 0,
                      "maximum": 9007199254740991
                    },
                    "client_name": {
                      "type": "string"
                    },
                    "redirect_uris": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "grant_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "response_types": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "token_endpoint_auth_method": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    },
                    "client_uri": {
                      "type": "string"
                    },
                    "logo_uri": {
                      "type": "string"
                    },
                    "tos_uri": {
                      "type": "string"
                    },
                    "policy_uri": {
                      "type": "string"
                    },
                    "contacts": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "software_id": {
                      "type": "string"
                    },
                    "software_version": {
                      "type": "string"
                    },
                    "is_agent": {
                      "type": "boolean"
                    }
                  },
                  "required": [
                    "client_id",
                    "client_id_issued_at",
                    "grant_types",
                    "response_types",
                    "token_endpoint_auth_method"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/oauth/revoke": {
      "post": {
        "tags": [
          "OAuth",
          "Revocation"
        ],
        "description": "RFC 7009 token revocation. Send the token and confidential client credentials in an application/x-www-form-urlencoded body. Always returns 200 with an empty body on success.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "token": {
                    "type": "string",
                    "minLength": 1
                  },
                  "token_type_hint": {
                    "type": "string",
                    "enum": [
                      "access_token",
                      "refresh_token"
                    ]
                  },
                  "client_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "client_secret": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "token"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "tags": [
          "OAuth",
          "Token"
        ],
        "description": "OAuth 2.1 token endpoint. Supports authorization_code (with PKCE) and client_credentials grants. Client auth via client_secret_post or client_secret_basic.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "enum": [
                          "authorization_code"
                        ]
                      },
                      "code": {
                        "type": "string",
                        "minLength": 1
                      },
                      "redirect_uri": {
                        "type": "string",
                        "minLength": 1
                      },
                      "code_verifier": {
                        "type": "string",
                        "minLength": 43,
                        "maxLength": 128,
                        "pattern": "^[A-Za-z0-9._~-]+$"
                      },
                      "resource": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 2048,
                            "format": "uri"
                          },
                          {
                            "maxItems": 10,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "maxLength": 2048,
                              "format": "uri"
                            }
                          }
                        ]
                      },
                      "client_id": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_secret": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_assertion_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "client_assertion": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      }
                    },
                    "required": [
                      "grant_type",
                      "code",
                      "redirect_uri",
                      "code_verifier"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "enum": [
                          "client_credentials"
                        ]
                      },
                      "scope": {
                        "type": "string"
                      },
                      "resource": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 2048,
                            "format": "uri"
                          },
                          {
                            "maxItems": 10,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "maxLength": 2048,
                              "format": "uri"
                            }
                          }
                        ]
                      },
                      "client_id": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_secret": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_assertion_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "client_assertion": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      }
                    },
                    "required": [
                      "grant_type"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "enum": [
                          "refresh_token"
                        ]
                      },
                      "refresh_token": {
                        "type": "string",
                        "minLength": 64,
                        "maxLength": 64,
                        "pattern": "^[0-9a-fA-F]{64}$"
                      },
                      "scope": {
                        "type": "string"
                      },
                      "resource": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 2048,
                            "format": "uri"
                          },
                          {
                            "maxItems": 10,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "maxLength": 2048,
                              "format": "uri"
                            }
                          }
                        ]
                      },
                      "client_id": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_secret": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_assertion_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "client_assertion": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      }
                    },
                    "required": [
                      "grant_type",
                      "refresh_token"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "enum": [
                          "urn:ietf:params:oauth:grant-type:token-exchange"
                        ]
                      },
                      "subject_token": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      },
                      "subject_token_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "actor_token": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      },
                      "actor_token_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "requested_token_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "scope": {
                        "type": "string",
                        "maxLength": 2048
                      },
                      "audience": {
                        "anyOf": [
                          {
                            "type": "string",
                            "minLength": 1,
                            "maxLength": 2048
                          },
                          {
                            "maxItems": 10,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "minLength": 1,
                              "maxLength": 2048
                            }
                          }
                        ]
                      },
                      "resource": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 2048,
                            "format": "uri"
                          },
                          {
                            "maxItems": 10,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "maxLength": 2048,
                              "format": "uri"
                            }
                          }
                        ]
                      },
                      "client_id": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_secret": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_assertion_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "client_assertion": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      }
                    },
                    "required": [
                      "grant_type",
                      "subject_token",
                      "subject_token_type"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "grant_type": {
                        "type": "string",
                        "enum": [
                          "urn:ietf:params:oauth:grant-type:jwt-bearer"
                        ]
                      },
                      "assertion": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      },
                      "scope": {
                        "type": "string",
                        "maxLength": 2048
                      },
                      "resource": {
                        "anyOf": [
                          {
                            "type": "string",
                            "maxLength": 2048,
                            "format": "uri"
                          },
                          {
                            "maxItems": 10,
                            "type": "array",
                            "items": {
                              "type": "string",
                              "maxLength": 2048,
                              "format": "uri"
                            }
                          }
                        ]
                      },
                      "client_id": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_secret": {
                        "type": "string",
                        "minLength": 1
                      },
                      "client_assertion_type": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 256
                      },
                      "client_assertion": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 8192
                      }
                    },
                    "required": [
                      "grant_type",
                      "assertion"
                    ]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "type": "object",
                      "properties": {
                        "access_token": {
                          "type": "string"
                        },
                        "issued_token_type": {
                          "type": "string",
                          "enum": [
                            "urn:ietf:params:oauth:token-type:id-jag"
                          ]
                        },
                        "token_type": {
                          "type": "string",
                          "enum": [
                            "N_A"
                          ]
                        },
                        "expires_in": {
                          "type": "number"
                        },
                        "scope": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "access_token",
                        "issued_token_type",
                        "token_type",
                        "expires_in"
                      ],
                      "additionalProperties": false
                    },
                    {
                      "type": "object",
                      "properties": {
                        "access_token": {
                          "type": "string"
                        },
                        "refresh_token": {
                          "type": "string"
                        },
                        "expires_in": {
                          "type": "number"
                        },
                        "token_type": {
                          "type": "string",
                          "enum": [
                            "Bearer"
                          ]
                        },
                        "scope": {
                          "type": "string"
                        },
                        "issued_token_type": {
                          "type": "string"
                        },
                        "id_token": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "access_token",
                        "expires_in",
                        "token_type"
                      ],
                      "additionalProperties": false
                    }
                  ]
                }
              }
            }
          }
        }
      }
    },
    "/oauth/userinfo": {
      "get": {
        "tags": [
          "OAuth",
          "Userinfo"
        ],
        "description": "OIDC userinfo endpoint (GET). Returns claims for the authenticated user. Requires a Bearer access token.",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sub": {
                      "type": "string",
                      "minLength": 1
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    },
                    "email_verified": {
                      "type": "boolean"
                    },
                    "name": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "sub"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": [
          "OAuth",
          "Userinfo"
        ],
        "description": "OIDC userinfo endpoint (POST). Returns claims for the authenticated user. Accepts a Bearer access token in the Authorization header or a form-encoded access_token body parameter (RFC 6750 §2.2).",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "sub": {
                      "type": "string",
                      "minLength": 1
                    },
                    "email": {
                      "type": "string",
                      "format": "email",
                      "pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
                    },
                    "email_verified": {
                      "type": "boolean"
                    },
                    "name": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "sub"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    },
    "/oid4vp/request/{handle}": {
      "get": {
        "tags": [
          "OID4VP"
        ],
        "description": "OID4VP 1.0 / RFC 9101 Request Object Endpoint. Serves the signed Authorization Request a `request_uri` refers to, as application/oauth-authz-req+jwt. TRANSPORT ONLY: the request state is neither read nor consumed here, nothing is written, and an unknown or expired reference is indistinguishable from a malformed one.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "handle",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/oid4vp/response": {
      "post": {
        "tags": [
          "OID4VP"
        ],
        "description": "OID4VP 1.0 direct_post Response Endpoint. Accepts a wallet Authorization Response (vp_token + state, or error + state) as application/x-www-form-urlencoded. TRANSPORT ONLY: the response is correlated against a single-use presentation request and structurally parsed. No signature, credential or issuer validation is performed and no user is authenticated (that is #234/#236).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "vp_token": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 524288
                  },
                  "state": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 512
                  },
                  "error": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 256
                  },
                  "error_description": {
                    "type": "string",
                    "maxLength": 1024
                  }
                },
                "required": [
                  "state"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transport-level acknowledgement (OID4VP 1.0 §8.3). Confirms the response was well-formed and correlated with a pending presentation request. It does NOT assert that any credential was verified or that any user was authenticated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": false,
                  "description": "Transport-level acknowledgement (OID4VP 1.0 §8.3). Confirms the response was well-formed and correlated with a pending presentation request. It does NOT assert that any credential was verified or that any user was authenticated."
                }
              }
            }
          }
        }
      }
    },
    "/ui/consent": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Render the OAuth consent screen. Requires a valid __Host-qauth_session cookie; otherwise redirects to /ui/login.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            },
            "in": "query",
            "name": "response_type",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "in": "query",
            "name": "client_id",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "in": "query",
            "name": "redirect_uri",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "minLength": 43,
              "maxLength": 128,
              "pattern": "^[A-Za-z0-9._~-]+$"
            },
            "in": "query",
            "name": "code_challenge",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            },
            "in": "query",
            "name": "code_challenge_method",
            "required": true
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "in": "query",
            "name": "state",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "in": "query",
            "name": "scope",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 2048
            },
            "in": "query",
            "name": "nonce",
            "required": false
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "login",
                "consent"
              ]
            },
            "in": "query",
            "name": "prompt",
            "required": false
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 315360000
            },
            "in": "query",
            "name": "max_age",
            "required": false
          },
          {
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "maxLength": 2048,
                  "format": "uri"
                },
                {
                  "maxItems": 10,
                  "type": "array",
                  "items": {
                    "type": "string",
                    "maxLength": 2048,
                    "format": "uri"
                  }
                }
              ]
            },
            "in": "query",
            "name": "resource",
            "required": false
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      },
      "post": {
        "tags": [
          "UI"
        ],
        "description": "Submit the consent decision. CSRF-protected; re-uses the authorize params to issue a code on Allow.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "decision": {
                    "type": "string",
                    "enum": [
                      "allow",
                      "deny"
                    ]
                  },
                  "allow_forever": {
                    "type": "string"
                  },
                  "csrf_token": {
                    "type": "string",
                    "minLength": 1
                  },
                  "client_id": {
                    "type": "string",
                    "minLength": 1
                  },
                  "redirect_uri": {
                    "type": "string",
                    "format": "uri"
                  },
                  "state": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "scope": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "nonce": {
                    "type": "string",
                    "maxLength": 2048
                  },
                  "code_challenge": {
                    "type": "string",
                    "minLength": 43,
                    "maxLength": 128
                  },
                  "code_challenge_method": {
                    "type": "string",
                    "enum": [
                      "S256"
                    ]
                  },
                  "response_type": {
                    "type": "string",
                    "enum": [
                      "code"
                    ]
                  },
                  "prompt": {
                    "type": "string",
                    "enum": [
                      "none",
                      "login",
                      "consent"
                    ]
                  },
                  "max_age": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 315360000
                  },
                  "resource": {
                    "anyOf": [
                      {
                        "type": "string",
                        "maxLength": 2048,
                        "format": "uri"
                      },
                      {
                        "maxItems": 10,
                        "type": "array",
                        "items": {
                          "type": "string",
                          "maxLength": 2048,
                          "format": "uri"
                        }
                      }
                    ]
                  }
                },
                "required": [
                  "decision",
                  "csrf_token",
                  "client_id",
                  "redirect_uri",
                  "code_challenge",
                  "code_challenge_method",
                  "response_type"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/login": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Renders the session-cookie login page. `return_to` is a relative path to redirect to after a successful sign-in. Issue #150.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "return_to",
            "required": false
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "error",
            "required": false
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      },
      "post": {
        "tags": [
          "UI"
        ],
        "description": "Submit the session-cookie login form. Sets __Host-qauth_session on success.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "email": {
                    "type": "string",
                    "minLength": 1
                  },
                  "password": {
                    "type": "string",
                    "minLength": 1
                  },
                  "return_to": {
                    "type": "string"
                  },
                  "csrf_token": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "email",
                  "password",
                  "csrf_token"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/resume/{handle}": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Resume a pending authorization request after login. The handle is single-use and resolves ONLY to an authorize URL this server minted. Issue #316.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "handle",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/wallet-link": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Renders the wallet-linking confirmation screen for the signed-in user. Issue #238.",
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      },
      "post": {
        "tags": [
          "UI"
        ],
        "description": "Starts a wallet-linking flow for the signed-in user and issues an OID4VP presentation request. Issue #238.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "csrf_token": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "csrf_token"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/wallet-link/{handle}": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Re-renders a wallet-linking flow in progress, completing it if the wallet has responded. Also the no-JavaScript refresh path. Issue #238.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "handle",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/wallet-login": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Renders the wallet sign-in screen, which collects the account identifier the user asserts (ADR-009). Issue #239.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "return_to",
            "required": false
          },
          {
            "schema": {
              "type": "string"
            },
            "in": "query",
            "name": "error",
            "required": false
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      },
      "post": {
        "tags": [
          "UI"
        ],
        "description": "Starts a wallet sign-in: records the asserted account identifier and issues an OID4VP presentation request. Issue #239.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "identifier": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 320
                  },
                  "return_to": {
                    "type": "string"
                  },
                  "csrf_token": {
                    "type": "string",
                    "minLength": 1
                  }
                },
                "required": [
                  "identifier",
                  "csrf_token"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/wallet-login/{handle}": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Re-renders a wallet sign-in in progress, advancing it if the wallet has responded. Also the no-JavaScript refresh path. Issue #239.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "handle",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response"
          }
        }
      }
    },
    "/ui/wallet-login/{handle}/status": {
      "get": {
        "tags": [
          "UI"
        ],
        "description": "Polled by the wallet sign-in screen. Reports whether the direct_post presentation response has arrived, and completes the sign-in when it has. Issue #239.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "in": "path",
            "name": "handle",
            "required": true
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "complete",
                        "expired",
                        "rejected"
                      ]
                    },
                    "message": {
                      "type": "string"
                    },
                    "redirect_to": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "status"
                  ],
                  "additionalProperties": false
                }
              }
            }
          }
        }
      }
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Default"
    }
  ]
}
