{
  "openapi": "3.1.1",
  "info": {
    "title": "认证中心 · 登录与应用授权 API",
    "version": "1.2.2",
    "description": "覆盖 OAuth/OIDC 发现、授权、令牌、用户信息、撤销，以及软件授权激活、即时域名或设备绑定、查询和扣减。并非全部后台 API。servers 使用当前网站根路径，生产必须 HTTPS。OAuth 返回原始 JSON；/api/v1 使用 code/message/data 信封。所有示例都是虚构数据。"
  },
  "servers": [
    {
      "url": "/"
    }
  ],
  "security": [],
  "paths": {
    "/.well-known/openid-configuration": {
      "get": {
        "operationId": "discoverOIDC",
        "summary": "获取 OIDC 配置",
        "description": "issuer 与所有端点均使用部署的 APP_ORIGIN。客户端应优先使用发现文档。",
        "responses": {
          "200": {
            "description": "OIDC 配置",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Discovery"
                }
              }
            }
          }
        }
      }
    },
    "/.well-known/jwks.json": {
      "get": {
        "operationId": "getJWKS",
        "summary": "获取 ID Token 验签公钥",
        "responses": {
          "200": {
            "description": "RSA 公钥集，无私钥",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "keys"
                  ],
                  "properties": {
                    "keys": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/JWK"
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/oauth/authorize": {
      "get": {
        "operationId": "authorize",
        "summary": "浏览器发起授权码登录",
        "description": "该端点先跳转本站授权页面，参数在后续授权请求中校验；最终回调包含 code/state/iss 或 error/state/iss。code 有效期 60 秒且只能使用一次。state 必须核对。默认要求所有客户端使用 PKCE S256；申请 openid 必须提供 nonce。兼容例外见登录指南。",
        "parameters": [
          {
            "name": "response_type",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "enum": [
                "code"
              ]
            }
          },
          {
            "name": "client_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "应用的公开 Client ID，不是应用 UUID"
          },
          {
            "name": "redirect_uri",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "format": "uri"
            },
            "description": "与登记值精确一致，含路径编码"
          },
          {
            "name": "scope",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "example": "openid profile email"
            },
            "description": "空格分隔，必须在应用允许的范围内"
          },
          {
            "name": "state",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 1024
            },
            "description": "每次授权生成不可预测的随机值"
          },
          {
            "name": "nonce",
            "in": "query",
            "schema": {
              "type": "string",
              "minLength": 16,
              "maxLength": 512
            },
            "description": "请求 openid 时必需；核对 ID Token nonce。仅显式启用兼容的机密客户端可省略"
          },
          {
            "name": "code_challenge",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "默认必需：BASE64URL(SHA256(code_verifier))，无填充；仅显式启用传统 OIDC 兼容的机密客户端可省略"
          },
          {
            "name": "code_challenge_method",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "S256"
              ]
            },
            "description": "提供 challenge 时必需"
          },
          {
            "name": "prompt",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "consent",
                "login"
              ]
            },
            "description": "none 可能回调 login_required 或 consent_required；login 重新验证密码"
          }
        ],
        "responses": {
          "302": {
            "description": "跳转本站授权页",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string"
                },
                "description": "本站 /authorize 与原始查询参数"
              }
            }
          }
        }
      }
    },
    "/oauth/token": {
      "post": {
        "operationId": "exchangeToken",
        "summary": "交换授权码或刷新令牌",
        "description": "机密客户端使用 HTTP Basic（用户名 client_id、密码 client_secret）或表单认证；公开客户端只传 client_id。表单认证对应下列空 security 选项，仍须服务端校验。不要发送 JSON。刷新会轮换令牌，旧刷新令牌重放会撤销整个令牌族。access_token 为不透明字符串，不能当 JWT 解码。",
        "security": [
          {
            "clientBasic": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/CodeExchange"
                  },
                  {
                    "$ref": "#/components/schemas/RefreshExchange"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "原始 JSON，无 data 包装",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                },
                "example": {
                  "access_token": "example-access-token",
                  "token_type": "Bearer",
                  "expires_in": 900,
                  "scope": "openid profile email",
                  "id_token": "example.header.signature"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/OAuthBadRequest"
          },
          "401": {
            "description": "invalid_client：客户端不存在、禁用或凭据错误",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/OAuthUnavailable"
          }
        }
      }
    },
    "/oauth/userinfo": {
      "get": {
        "operationId": "getUserInfo",
        "summary": "查询用户信息 · 字段映射",
        "description": "使用 OAuth access_token，必须含 openid；始终返回 application_creator 布尔值，表示当前用户是否为当前应用的创建人。profile 返回 name，email 返回 email/email_verified。所有字段位于根对象。当前不返回 picture、avatar、nickname、id、username、preferred_username、roles、phone_number。请验证响应 sub 与已经验签的 ID Token sub 一致。",
        "security": [
          {
            "oauthAccess": [
              "openid"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "根据 token 实际 scope 返回用户声明；没有申请的字段会缺省",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserInfo"
                },
                "examples": {
                  "identity": {
                    "summary": "仅 openid",
                    "value": {
                      "sub": "00000000-0000-4000-8000-000000000001",
                      "application_creator": false
                    }
                  },
                  "profileEmail": {
                    "summary": "openid profile email",
                    "value": {
                      "sub": "00000000-0000-4000-8000-000000000001",
                      "name": "示例用户",
                      "email": "person@example.test",
                      "email_verified": false,
                      "application_creator": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "description": "invalid_token：访问令牌失效、被撤销、会话失效或账号/应用停用",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                },
                "example": {
                  "error": "invalid_token"
                }
              }
            }
          },
          "403": {
            "description": "insufficient_scope：缺少 openid",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                },
                "example": {
                  "error": "insufficient_scope"
                }
              }
            }
          }
        }
      }
    },
    "/oauth/revoke": {
      "post": {
        "operationId": "revokeToken",
        "summary": "撤销访问/刷新令牌所属令牌族",
        "description": "与 token 端点使用相同客户端认证。未知或已撤销的 token 仍返回 200 空正文；不会退出认证中心全部浏览器会话。token_type_hint 当前不参与处理。",
        "security": [
          {
            "clientBasic": []
          },
          {}
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "token"
                ],
                "properties": {
                  "token": {
                    "type": "string",
                    "description": "待撤销的访问或刷新令牌"
                  },
                  "client_id": {
                    "type": "string",
                    "description": "未用 Basic 时必需"
                  },
                  "client_secret": {
                    "type": "string",
                    "description": "未用 Basic 的机密客户端必需"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "成功，空正文"
          },
          "401": {
            "description": "invalid_client",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/OAuthUnavailable"
          }
        }
      }
    },
    "/api/v1/auth/check": {
      "post": {
        "operationId": "checkLicense",
        "summary": "查询应用授权是否可用",
        "description": "API Key 只用于服务端、限制所属应用且应用须允许 license:read；OAuth token 还限制本人授权。不需要浏览器 Cookie/CSRF。HTTP 200 不表示授权有效，必须判断 data.valid。",
        "security": [
          {
            "applicationKey": []
          },
          {
            "oauthAccess": [
              "license:read"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LicenseInput"
              },
              "example": {
                "authorization_id": "00000000-0000-4000-8000-000000000002",
                "binding_value": "example.test"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "授权结果；not_found 时只含 valid/reason",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "const": 0
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/LicenseCheck"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "message": "success",
                  "data": {
                    "valid": false,
                    "reason": "not_found"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "403": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PlatformFailure"
          }
        }
      }
    },
    "/api/v1/auth/consume": {
      "post": {
        "operationId": "consumeLicense",
        "summary": "按幂等键扣减用量",
        "description": "应用须允许 license:consume；OAuth 同时限制用户。幂等范围为 authorization_id + idempotency_key，同键同数量重试返回当前 used，同键不同数量返回 409。仅支持 metered 授权。",
        "security": [
          {
            "applicationKey": []
          },
          {
            "oauthAccess": [
              "license:consume"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "allOf": [
                  {
                    "$ref": "#/components/schemas/LicenseInput"
                  },
                  {
                    "type": "object",
                    "required": [
                      "quantity",
                      "idempotency_key"
                    ],
                    "properties": {
                      "quantity": {
                        "type": "integer",
                        "minimum": 1,
                        "maximum": 1000000000
                      },
                      "idempotency_key": {
                        "type": "string",
                        "minLength": 8,
                        "maxLength": 128
                      }
                    }
                  }
                ]
              },
              "example": {
                "authorization_id": "00000000-0000-4000-8000-000000000002",
                "quantity": 1,
                "idempotency_key": "example-order-001"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "累计用量，不是剩余额度",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "const": 0
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "used"
                      ],
                      "properties": {
                        "used": {
                          "type": "integer",
                          "format": "int64"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "message": "success",
                  "data": {
                    "used": 1
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "403": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "404": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "409": {
            "description": "授权不可用、额度不足、非按量授权或同键不同数量",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PlatformError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/PlatformFailure"
          }
        }
      }
    },
    "/api/v1/authorizations/activate": {
      "post": {
        "operationId": "activateAuthorization",
        "summary": "为当前 OAuth 用户兑换软件授权激活码",
        "description": "仅接受用户 OAuth Access Token，不接受应用 API Key。认证中心从令牌确定用户和应用，并拒绝不属于该应用的激活码。浏览器工作台也使用同一路径，但采用站内会话与 CSRF。",
        "security": [
          {
            "oauthAccess": [
              "license:activate"
            ]
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActivationRequest"
              },
              "example": {
                "code": "AC-example-code"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "已创建并归属当前用户的授权",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "const": 0
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/ActivationResult"
                    }
                  }
                },
                "example": {
                  "code": 0,
                  "message": "success",
                  "data": {
                    "authorization_id": "00000000-0000-4000-8000-000000000002",
                    "license_key": "00000000-0000-4000-8000-000000000002",
                    "application_id": "00000000-0000-4000-8000-000000000003",
                    "auth_type": "domain",
                    "binding_limit": 1,
                    "subdomain_limit": 5,
                    "quota": 0
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "401": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "403": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "404": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "409": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "503": {
            "$ref": "#/components/responses/PlatformFailure"
          }
        }
      }
    },
    "/api/v1/authorizations/{id}/bindings": {
      "post": {
        "operationId": "addAuthorizationBinding",
        "summary": "为当前用户的软件授权添加设备或域名绑定",
        "description": "令牌用户和令牌应用必须同时与目标授权匹配。设备、根域名以及根域名下明确配置的子域名在绑定成功后立即生效，不需要 DNS 验证。",
        "security": [
          {
            "oauthAccess": [
              "license:activate"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "activate 返回的 authorization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BindingRequest"
              },
              "example": {
                "binding_type": "domain",
                "binding_value": "example.test"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "绑定已创建",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "const": 0
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "$ref": "#/components/schemas/BindingResult"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "401": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "403": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "404": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "409": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "503": {
            "$ref": "#/components/responses/PlatformFailure"
          }
        }
      }
    },
    "/api/v1/authorizations/{id}/bindings/{binding}/verify": {
      "post": {
        "operationId": "confirmLegacyAuthorizationDomainBinding",
        "summary": "兼容旧客户端确认域名绑定",
        "description": "兼容旧客户端保留的入口。确认目标属于当前用户和当前应用后立即将旧绑定设为有效，不查询 DNS；新客户端无需调用。",
        "security": [
          {
            "oauthAccess": [
              "license:activate"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "activate 返回的 authorization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "binding",
            "in": "path",
            "required": true,
            "description": "创建绑定返回的绑定 ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "旧域名绑定已确认生效",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "const": 0
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object",
                      "required": [
                        "verified"
                      ],
                      "properties": {
                        "verified": {
                          "const": true
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "401": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "403": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "404": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "409": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "503": {
            "$ref": "#/components/responses/PlatformFailure"
          }
        }
      }
    },
    "/api/v1/authorizations/{id}/bindings/{binding}": {
      "delete": {
        "operationId": "removeAuthorizationBinding",
        "summary": "解绑设备或域名",
        "description": "受应用解绑冷却时间限制；移除根域名会级联移除其子域名。",
        "security": [
          {
            "oauthAccess": [
              "license:activate"
            ]
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "activate 返回的 authorization_id",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "binding",
            "in": "path",
            "required": true,
            "description": "创建绑定返回的绑定 ID",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "解绑成功",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "code",
                    "message",
                    "data"
                  ],
                  "properties": {
                    "code": {
                      "const": 0
                    },
                    "message": {
                      "type": "string"
                    },
                    "data": {
                      "type": "null"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "401": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "403": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "404": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "409": {
            "$ref": "#/components/responses/PlatformFailure"
          },
          "503": {
            "$ref": "#/components/responses/PlatformFailure"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "clientBasic": {
        "type": "http",
        "scheme": "basic",
        "description": "机密客户端 client_id / client_secret；也支持表单 client_secret_post"
      },
      "oauthAccess": {
        "type": "oauth2",
        "description": "Authorization: Bearer <access_token>；不可使用 id_token 或机器发布 token",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "/oauth/authorize",
            "tokenUrl": "/oauth/token",
            "refreshUrl": "/oauth/token",
            "scopes": {
              "openid": "稳定用户标识与 ID Token",
              "profile": "显示名称 name",
              "email": "邮箱与验证标志",
              "offline_access": "刷新令牌",
              "license:read": "查询本人应用授权",
              "license:consume": "扣减本人应用用量",
              "license:activate": "兑换激活码并管理本人在当前应用的即时授权绑定"
            }
          }
        }
      },
      "applicationKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "创建应用时显示的 API Key；仅存服务端"
      }
    },
    "responses": {
      "OAuthBadRequest": {
        "description": "invalid_grant（含过期、重放、PKCE/回调不符）、unsupported_grant_type 或其他授权校验失败",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/OAuthError"
            },
            "example": {
              "error": "invalid_grant"
            }
          }
        }
      },
      "OAuthUnavailable": {
        "description": "OAuth 处理器返回 error；Redis 限流中间件返回 code/message。两种结构都须处理",
        "content": {
          "application/json": {
            "schema": {
              "oneOf": [
                {
                  "$ref": "#/components/schemas/OAuthError"
                },
                {
                  "$ref": "#/components/schemas/PlatformError"
                }
              ]
            }
          }
        }
      },
      "RateLimited": {
        "description": "按 IP 限流，稍后重试；平台错误结构，不含 data",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PlatformError"
            },
            "example": {
              "code": 42900,
              "message": "操作过于频繁，请稍后再试"
            }
          }
        }
      },
      "PlatformFailure": {
        "description": "400 输入错误；403 凭据/范围不符；404 授权不存在；503 服务不可用。错误 code 为 HTTP 状态 × 100",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/PlatformError"
            }
          }
        }
      }
    },
    "schemas": {
      "UserInfo": {
        "type": "object",
        "required": [
          "sub",
          "application_creator"
        ],
        "additionalProperties": false,
        "properties": {
          "sub": {
            "type": "string",
            "format": "uuid",
            "description": "稳定的用户 UUID；用户唯一标识映射填 sub，JSONPath 填 $.sub。跨 issuer 使用 iss + sub 关联",
            "x-scope": "openid",
            "x-mapping": "用户唯一标识"
          },
          "application_creator": {
            "type": "boolean",
            "description": "当前登录用户是否为当前 OAuth 应用的创建人。由服务端按 access_token 绑定的 application_id 与不可由用户提交的 owner_id 比较；可作为该应用的初始管理员依据，不代表认证中心平台管理员或其他应用权限",
            "x-scope": "openid",
            "x-mapping": "当前应用创建人"
          },
          "name": {
            "type": "string",
            "description": "平台昵称，可变且不保证唯一；映射填 name / $.name",
            "x-scope": "profile",
            "x-mapping": "显示名称 / 昵称"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "邮箱；映射填 email / $.email，不用作稳定用户 ID",
            "x-scope": "email",
            "x-mapping": "邮箱"
          },
          "email_verified": {
            "type": "boolean",
            "description": "真实布尔值，可为 false；不要将未验证邮箱视为已验证身份",
            "x-scope": "email",
            "x-mapping": "邮箱已验证"
          }
        }
      },
      "IDTokenClaims": {
        "type": "object",
        "description": "这是对解码后的声明结构的说明，不是 token 接口中的嵌套 JSON。必须通过 JWKS 验签，并验证 iss/aud/exp/nonce、UserInfo sub 一致性。刷新响应通常没有 nonce，不要将它作为新登录。",
        "required": [
          "iss",
          "sub",
          "aud",
          "iat",
          "exp",
          "at_hash",
          "application_creator"
        ],
        "properties": {
          "iss": {
            "type": "string",
            "format": "uri",
            "description": "APP_ORIGIN"
          },
          "sub": {
            "type": "string",
            "format": "uuid"
          },
          "aud": {
            "type": "string",
            "description": "client_id"
          },
          "iat": {
            "type": "integer",
            "description": "签发时间，Unix 秒"
          },
          "exp": {
            "type": "integer",
            "description": "过期时间，Unix 秒，签发后 900 秒"
          },
          "nonce": {
            "type": "string",
            "description": "授权码请求中提供时返回；刷新时省略"
          },
          "at_hash": {
            "type": "string",
            "description": "access_token SHA256 左半段的 Base64URL"
          },
          "application_creator": {
            "type": "boolean",
            "description": "当前登录用户是否为 aud 所指应用的创建人；仅在验签并校验 iss、aud、exp、nonce 后用于该应用内的管理员判定，不代表平台管理员权限"
          },
          "name": {
            "type": "string",
            "description": "profile scope"
          },
          "email": {
            "type": "string",
            "format": "email",
            "description": "email scope"
          },
          "email_verified": {
            "type": "boolean",
            "description": "email scope"
          }
        }
      },
      "TokenResponse": {
        "type": "object",
        "required": [
          "access_token",
          "token_type",
          "expires_in",
          "scope"
        ],
        "properties": {
          "access_token": {
            "type": "string",
            "description": "不透明访问令牌；放入 Authorization: Bearer"
          },
          "token_type": {
            "type": "string",
            "enum": [
              "Bearer"
            ]
          },
          "expires_in": {
            "type": "integer",
            "const": 900,
            "description": "秒"
          },
          "scope": {
            "type": "string",
            "description": "实际授权范围，空格分隔"
          },
          "refresh_token": {
            "type": "string",
            "description": "仅 offline_access 返回；受登录会话有效期限制，轮换后原子替换旧值"
          },
          "id_token": {
            "type": "string",
            "description": "仅 openid 返回，RS256 JWT 字符串；声明结构见 IDTokenClaims"
          }
        }
      },
      "CodeExchange": {
        "type": "object",
        "required": [
          "grant_type",
          "code",
          "redirect_uri"
        ],
        "properties": {
          "grant_type": {
            "const": "authorization_code",
            "type": "string"
          },
          "code": {
            "type": "string",
            "description": "回调中的一次性授权码"
          },
          "redirect_uri": {
            "type": "string",
            "format": "uri",
            "description": "与发起授权的值完全一致"
          },
          "code_verifier": {
            "type": "string",
            "minLength": 43,
            "maxLength": 128,
            "description": "默认必需，原始 PKCE verifier；仅未提交 challenge 且显式启用传统 OIDC 兼容的机密客户端可省略"
          },
          "client_id": {
            "type": "string",
            "description": "未用 Basic 时必需"
          },
          "client_secret": {
            "type": "string",
            "description": "未用 Basic 的机密客户端必需；公开客户端不携带"
          }
        }
      },
      "RefreshExchange": {
        "type": "object",
        "required": [
          "grant_type",
          "refresh_token"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "const": "refresh_token"
          },
          "refresh_token": {
            "type": "string",
            "description": "上次返回的最新刷新令牌，不可并发复用"
          },
          "client_id": {
            "type": "string",
            "description": "未用 Basic 时必需"
          },
          "client_secret": {
            "type": "string",
            "description": "未用 Basic 的机密客户端必需"
          }
        }
      },
      "OAuthError": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "string",
            "description": "OAuth 错误码"
          }
        }
      },
      "PlatformError": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "LicenseInput": {
        "type": "object",
        "required": [
          "authorization_id"
        ],
        "properties": {
          "authorization_id": {
            "type": "string",
            "format": "uuid",
            "description": "具体软件授权 ID，不是应用 ID 或 client_id"
          },
          "binding_value": {
            "type": "string",
            "description": "域名/设备型授权须传已验证绑定；其他类型可省略"
          }
        }
      },
      "LicenseCheck": {
        "type": "object",
        "required": [
          "valid",
          "reason"
        ],
        "properties": {
          "valid": {
            "type": "boolean"
          },
          "reason": {
            "type": "string",
            "enum": [
              "",
              "not_found",
              "expired_or_cancelled",
              "binding_not_verified",
              "quota_exhausted"
            ],
            "description": "空字符串表示有效；not_found 也可能表示当前凭据不可见该授权"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "null 表示没有到期时间；not_found 时省略"
          },
          "quota": {
            "type": "integer",
            "format": "int64",
            "description": "总额度；not_found 时省略"
          },
          "used": {
            "type": "integer",
            "format": "int64",
            "description": "已用额度；not_found 时省略"
          },
          "auth_type": {
            "type": "string",
            "description": "授权类型；not_found 时省略"
          }
        }
      },
      "JWK": {
        "type": "object",
        "required": [
          "kty",
          "use",
          "alg",
          "kid",
          "n",
          "e"
        ],
        "properties": {
          "kty": {
            "type": "string",
            "enum": [
              "RSA"
            ]
          },
          "use": {
            "type": "string",
            "enum": [
              "sig"
            ]
          },
          "alg": {
            "type": "string",
            "enum": [
              "RS256"
            ]
          },
          "kid": {
            "type": "string",
            "description": "当前 primary；按 token kid 选公钥"
          },
          "n": {
            "type": "string",
            "description": "RSA modulus，Base64URL"
          },
          "e": {
            "type": "string",
            "description": "RSA exponent，Base64URL"
          }
        }
      },
      "Discovery": {
        "type": "object",
        "required": [
          "issuer",
          "authorization_endpoint",
          "token_endpoint",
          "userinfo_endpoint",
          "revocation_endpoint",
          "jwks_uri",
          "claims_supported"
        ],
        "properties": {
          "issuer": {
            "type": "string",
            "format": "uri"
          },
          "authorization_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "token_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "userinfo_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "revocation_endpoint": {
            "type": "string",
            "format": "uri"
          },
          "jwks_uri": {
            "type": "string",
            "format": "uri"
          },
          "response_types_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "grant_types_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "subject_types_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "id_token_signing_alg_values_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "scopes_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token_endpoint_auth_methods_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "code_challenge_methods_supported": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "claims_supported": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "sub",
                "name",
                "email",
                "email_verified",
                "application_creator"
              ]
            }
          }
        }
      },
      "ActivationRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "code"
        ],
        "properties": {
          "code": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "软件授权激活码；与通用码券不同"
          }
        }
      },
      "ActivationResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "authorization_id",
          "license_key",
          "application_id",
          "auth_type",
          "binding_limit",
          "subdomain_limit",
          "quota"
        ],
        "properties": {
          "authorization_id": {
            "type": "string",
            "format": "uuid",
            "description": "兼容字段，与 license_key 相同"
          },
          "license_key": {
            "type": "string",
            "format": "uuid",
            "description": "接入应用保存并用于后续授权校验的许可证密钥"
          },
          "application_id": {
            "type": "string",
            "format": "uuid"
          },
          "auth_type": {
            "type": "string",
            "enum": [
              "membership",
              "subscription",
              "domain",
              "device",
              "metered"
            ]
          },
          "binding_limit": {
            "type": "integer",
            "minimum": 0
          },
          "subdomain_limit": {
            "type": "integer",
            "minimum": 0
          },
          "quota": {
            "type": "integer",
            "format": "int64",
            "minimum": 0
          }
        }
      },
      "BindingRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "binding_type",
          "binding_value"
        ],
        "properties": {
          "binding_type": {
            "type": "string",
            "enum": [
              "domain",
              "device"
            ]
          },
          "binding_value": {
            "type": "string",
            "maxLength": 255,
            "description": "域名不含协议、端口或路径；设备值由应用生成并保持稳定"
          },
          "parent_binding_id": {
            "type": "string",
            "format": "uuid",
            "description": "添加子域名时填写所属根域名的绑定 ID"
          }
        }
      },
      "BindingResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "verified"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "verified": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
