Skip to content
Clone
dd4650a
8681 lines 228.4 KB JSON
{
"openapi": "3.1.0",
"info": {
"title": "auth",
"description": "认证与账号服务:工作量证明、口令与验证码登录、二次验证、注册、口令重置、访问令牌与 SSH 公钥。",
"license": {
"name": "MIT",
"identifier": "MIT"
},
"version": "1.0.0"
},
"paths": {
"/.well-known/oauth-authorization-server": {
"get": {
"tags": [
"oauth"
],
"summary": "OAuth 授权服务器元数据(含 OIDC 字段)",
"operationId": "oauth_metadata",
"responses": {
"200": {
"description": "RFC 8414 元数据"
}
}
}
},
"/.well-known/openid-configuration": {
"get": {
"tags": [
"oauth"
],
"summary": "OIDC 发现文档",
"operationId": "oauth_openid_configuration",
"responses": {
"200": {
"description": "OpenID Provider 元数据"
}
}
}
},
"/api/v1/oauth/access-tokens": {
"get": {
"tags": [
"auth"
],
"summary": "列示访问令牌",
"description": "按创建时间倒序返回当前账号的令牌摘要,只给指纹与状态,不回吐令牌原文。分页参数由 `page` / `page_size` 控制。查询串不是合法分页参数或路径/方法不匹配时返回 400 / 404 由 actix-web 直接给出。",
"operationId": "auth_access_token_list",
"parameters": [
{
"name": "page",
"in": "query",
"description": "页码,从 1 开始;默认 1",
"required": false,
"schema": {
"type": "integer",
"format": "int64",
"minimum": 0
}
},
{
"name": "page_size",
"in": "query",
"description": "每页条数,默认 20,最多 100",
"required": false,
"schema": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
],
"responses": {
"200": {
"description": "令牌摘要列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_AccessTokenSummary"
},
"example": {
"code": 200,
"data": [
{
"created_at": "2026-01-02T03:04:05Z",
"description": "本机命令行",
"expires_at": null,
"fingerprint": "3f9c1a7b2d4e6058",
"id": "018f2b1c-4d5e-7f80-9a1b-2c3d4e5f6071",
"last_used_at": null,
"name": "cli",
"revoked_at": null,
"scope": [
"ssh_key",
"assets"
]
}
],
"message": "success"
}
}
}
},
"401": {
"description": "会话未绑定账号(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
},
"post": {
"tags": [
"auth"
],
"summary": "签发访问令牌",
"description": "名称 1~64 字符、备注最长 255 字符,`scope` 必须全部命中白名单(最多 32 项),`expires_in_secs` 取值 60 ~ 31536000(不填表示长期有效)。同一账号未吊销的令牌上限 50 个。签发成功记 `AccessKeyAdded` 审计事件。",
"operationId": "auth_access_token_create",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AccessTokenCreateRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "令牌已签发,`token` 只在此响应里出现一次",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_AccessTokenCreateResponse"
},
"example": {
"code": 200,
"data": {
"created_at": "2026-01-02T03:04:05Z",
"expires_at": null,
"id": "018f2b1c-4d5e-7f80-9a1b-2c3d4e5f6071",
"name": "cli",
"scope": [
"ssh_key",
"assets"
],
"token": "Zk9tQ2h5cFJ2TjB3U3gxbUhhcTRkRmc2WXpVMEJqTDlLbVNu"
},
"message": "success"
}
}
}
},
"400": {
"description": "名称、备注、范围或有效期不合法(`invalid_access_key_name`、`malformed_request`、`invalid_scope`、`invalid_expiry`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_scope",
"message": "access token scope is invalid"
}
}
}
},
"401": {
"description": "会话未绑定账号,或账号已删除 / 不允许使用(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"429": {
"description": "未吊销的令牌已达上限(`too_many_access_keys`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "too_many_access_keys",
"message": "too many access keys"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/access-tokens/{token_id}": {
"delete": {
"tags": [
"auth"
],
"summary": "吊销访问令牌",
"description": "把令牌标记为已吊销,记录保留不硬删;重复调用幂等。令牌不存在或不属于当前账号返回 `access_token_not_found`(按 `errors.rs` 的归类为 401)。吊销成功记 `AccessKeyRemoved` 审计事件。",
"operationId": "auth_access_token_revoke",
"parameters": [
{
"name": "token_id",
"in": "path",
"description": "令牌编号",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已吊销;重复调用同样返回成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": 200,
"data": null,
"message": "success"
}
}
}
},
"401": {
"description": "会话未绑定账号(`unauthenticated`),或令牌不属于当前账号 / 不存在(`access_token_not_found`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "access_token_not_found",
"message": "access token does not exist"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/app-tokens": {
"post": {
"tags": [
"auth"
],
"summary": "签发内部应用令牌",
"description": "认证中心用 Ed25519 私钥签发 JWT(`alg=EdDSA`),`aud` 为目标 app 的 audience,`client_id` 为 app 标识。任何服务只需 `/.well-known/jwks.json` 的公钥即可本地验签。`ttl_seconds` 取值 1 ~ 3600,不填或填 0 用默认 900。会话未绑定账号返回 `unauthenticated`(401);app 未在 `apps` 清单里返回 `app_not_found`(404);私钥未配置返回 `unavailable`(503)。",
"operationId": "auth_app_token_issue",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AppTokenRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "令牌已签发,`token` 是 EdDSA JWT",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_AppTokenResponse"
},
"example": {
"code": 200,
"data": {
"app_id": "api",
"audience": "api",
"expires_at": "2026-01-02T03:19:05Z",
"issued_at": "2026-01-02T03:04:05Z",
"key_id": "app-local-1",
"token": "eyJhbGciOiJFZERTQSIsImtpZCI6ImsxIiwidHlwIjoiSldUIn0.…"
},
"message": "success"
}
}
}
},
"400": {
"description": "app_id 为空或 ttl_seconds 超出上限(`malformed_request`、`invalid_expiry`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_expiry",
"message": "expires_at is invalid"
}
}
}
},
"401": {
"description": "会话未绑定账号(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"404": {
"description": "app_id 不在认证中心的 `apps` 清单里(`app_not_found`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "app_not_found",
"message": "app does not exist"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
},
"503": {
"description": "签名密钥未配置(`unavailable`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unavailable",
"message": "dependency is unavailable: jwt.private_key is required to issue tokens"
}
}
}
}
}
}
},
"/api/v1/oauth/authorize": {
"get": {
"tags": [
"oauth"
],
"summary": "授权端点(授权码 + PKCE S256)",
"description": "未登录跳到 `/login`;首次授权跳 `/consent`;`prompt=none` 直接返回 `login_required` / `consent_required`。",
"operationId": "oauth_authorize",
"parameters": [
{
"name": "response_type",
"in": "query",
"description": "固定为 `code`",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "client_id",
"in": "query",
"description": "已注册的客户端 id",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "redirect_uri",
"in": "query",
"description": "已注册的回调地址,支持子域通配",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "state",
"in": "query",
"description": "16..=512 字符的不透明串",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "code_challenge",
"in": "query",
"description": "PKCE S256 challenge(43 字符 base64url)",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "code_challenge_method",
"in": "query",
"description": "固定为 `S256`",
"required": true,
"schema": {
"type": "string"
}
},
{
"name": "scope",
"in": "query",
"description": "空格分隔,必须 ⊆ 客户端登记 scope",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "nonce",
"in": "query",
"description": "OIDC nonce,原样写入 id_token",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "prompt",
"in": "query",
"description": "`none` / `login` / `consent`",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "max_age",
"in": "query",
"description": "会话最大年龄(秒),超出就重新登录",
"required": false,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"302": {
"description": "重定向回 `redirect_uri`,带 `code` / `error` / `state` / `iss`"
},
"400": {
"description": "`invalid_request`(客户端或回调未注册)"
}
}
}
},
"/api/v1/oauth/challenge": {
"post": {
"tags": [
"auth"
],
"summary": "签发工作量证明挑战",
"description": "把挑战写进当前会话并返回。客户端需要为 `context` 找出一枚满足 `difficulty`(前导零比特数)的 nonce;`pow.v1` 算法与前端求解器一致。",
"operationId": "auth_challenge",
"responses": {
"200": {
"description": "挑战已签发并写入会话",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_ChallengeResponse"
},
"example": {
"code": 200,
"data": {
"context": "3xJk9Qp2mV7sLbT1rZa8nHc4wDf6YgU0",
"difficulty": 16,
"expires_at": 1767139500,
"issued_at": 1767139200
},
"message": "success"
}
}
}
},
"500": {
"description": "`internal`(挑战无法写入会话)/ `cache` / `session` / `serialization`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/consent": {
"get": {
"tags": [
"oauth"
],
"summary": "同意页所需的客户端与 scope 预览",
"operationId": "oauth_consent_preview",
"responses": {
"200": {
"description": "客户端名称与待授权 scope",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConsentPreview"
}
}
}
},
"400": {
"description": "`invalid_request`"
},
"401": {
"description": "`login_required`"
}
}
},
"post": {
"tags": [
"oauth"
],
"summary": "提交同意决定",
"description": "授权参数从查询串读取;`decision=allow` 落库并回 `/api/v1/oauth/authorize?...`,`deny` 回客户端并带 `error=access_denied`。",
"operationId": "oauth_consent_decide",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConsentForm"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "下一步地址",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ConsentDecision"
}
}
}
},
"400": {
"description": "`invalid_request`"
},
"401": {
"description": "`login_required`"
}
}
}
},
"/api/v1/oauth/login": {
"post": {
"tags": [
"auth"
],
"summary": "口令登录",
"description": "用口令登录。`identity` 可以是用户名、邮箱(大小写不敏感)或用户编号,`password_hash` 是客户端先算好的口令摘要,工作量证明的载荷必须是 `identity`。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`,此时会话尚未绑定,需再调 `/api/v1/oauth/login/verify`。",
"operationId": "auth_login",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserLoginRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "登录成功;`mfa_required` 为真时还需二次验证",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_UserLoginResponse"
},
"example": {
"code": 200,
"data": {
"challenge": null,
"displayname": "Ada",
"mfa_required": false,
"user_id": 1024,
"username": "ada"
},
"message": "success"
}
}
}
},
"400": {
"description": "工作量证明过期、载荷不匹配或请求不合法(`expired`、`invalid_proof`、`invalid_payload`、`malformed_request`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "expired",
"message": "challenge expired"
}
}
}
},
"401": {
"description": "身份或口令不正确(`invalid_credentials`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_credentials",
"message": "invalid credentials"
}
}
}
},
"403": {
"description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "login_forbidden",
"message": "account is banned"
}
}
}
},
"429": {
"description": "失败次数超出配额(`rate_limited`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "rate_limited",
"message": "too many attempts"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/login/code": {
"post": {
"tags": [
"auth"
],
"summary": "发送邮箱登录验证码",
"description": "向账号邮箱发送 6 位登录验证码,`expires_in_secs` 为有效期。工作量证明的载荷必须是 `email`。同一账号的发码间隔受 `email_code_rate_limit_secs` 限制。",
"operationId": "auth_login_code",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginCodeRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "验证码已发送",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_LoginCodeResponse"
},
"example": {
"code": 200,
"data": {
"expires_in_secs": 600
},
"message": "success"
}
}
}
},
"400": {
"description": "邮箱格式不合法或工作量证明过期、载荷不匹配(`invalid_email`、`expired`、`invalid_proof`、`invalid_payload`、`malformed_request`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_email",
"message": "invalid email address"
}
}
}
},
"401": {
"description": "邮箱未注册或账号不可用(`invalid_credentials`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_credentials",
"message": "invalid credentials"
}
}
}
},
"403": {
"description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "login_forbidden",
"message": "account is banned"
}
}
}
},
"429": {
"description": "发码过于频繁(`rate_limited`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "rate_limited",
"message": "too many requests"
}
}
}
},
"500": {
"description": "服务端故障,含邮件发送失败(`internal`、`database`、`cache`、`session`、`email`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/login/code/verify": {
"post": {
"tags": [
"auth"
],
"summary": "邮箱验证码换会话",
"description": "用邮箱登录验证码换会话。工作量证明的载荷必须是 `email`。验证码一旦核对通过即作废,连续输错 `max_verify_attempts` 次后需重新申请。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`。",
"operationId": "auth_login_code_verify",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginCodeVerifyRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "登录成功;`mfa_required` 为真时还需二次验证",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_UserLoginResponse"
},
"example": {
"code": 200,
"data": {
"challenge": null,
"displayname": "Ada",
"mfa_required": false,
"user_id": 1024,
"username": "ada"
},
"message": "success"
}
}
}
},
"400": {
"description": "验证码不正确或已过期,或邮箱格式、工作量证明不合法(`invalid_email_code`、`invalid_email`、`expired`、`invalid_proof`、`invalid_payload`、`malformed_request`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_email_code",
"message": "invalid email code"
}
}
}
},
"401": {
"description": "邮箱未注册或账号不可用(`invalid_credentials`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_credentials",
"message": "invalid credentials"
}
}
}
},
"403": {
"description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "login_forbidden",
"message": "account is banned"
}
}
}
},
"429": {
"description": "验证码尝试次数超限或请求过频(`email_code_attempts_exceeded`、`rate_limited`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "email_code_attempts_exceeded",
"message": "too many attempts"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/login/verify": {
"post": {
"tags": [
"auth"
],
"summary": "二次验证换会话",
"description": "用 6 位 TOTP 动态码或一枚未使用的恢复码完成二次验证并绑定会话。`challenge` 必须与 `/api/v1/oauth/login` 或 `/api/v1/oauth/login/code/verify` 返回的一致,挑战有效期 300 秒,同一动态码时间步不能重复使用,恢复码用掉即作废。",
"operationId": "auth_login_verify",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LoginVerifyRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "登录成功,会话已绑定",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_UserLoginResponse"
},
"example": {
"code": 200,
"data": {
"challenge": null,
"displayname": "Ada",
"mfa_required": false,
"user_id": 1024,
"username": "ada"
},
"message": "success"
}
}
}
},
"400": {
"description": "挑战过期或对不上、动态码错误、动态码时间步已用过、恢复码无效(`expired`、`malformed_request`、`totp_code_invalid`、`totp_step_reused`、`recovery_code_invalid`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "totp_code_invalid",
"message": "invalid totp code"
}
}
}
},
"401": {
"description": "会话里没有待验证挑战、账号不可用或多因子记录已被撤销(`unauthenticated`、`invalid_credentials`、`mfa_required`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "mfa_required",
"message": "multi-factor authentication required"
}
}
}
},
"403": {
"description": "账号被禁止登录,原因见 `message`(`login_forbidden`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "login_forbidden",
"message": "account is banned"
}
}
}
},
"429": {
"description": "尝试次数超限或恢复码已用尽(`rate_limited`、`recovery_codes_exhausted`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "rate_limited",
"message": "too many attempts"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/logout": {
"get": {
"tags": [
"oauth"
],
"summary": "单点登出(RP-Initiated Logout)",
"description": "撤销当前会话与其全客户端刷新令牌,并向 `backchannel_logout_uris` 发 `logout_token`;最后回跳已注册的 `post_logout_redirect_uri`。GET 带验证通过的 `id_token_hint`(签名有效且绑定当前会话)时免确认直接登出,否则返回确认页,确认后 POST 完成登出。",
"operationId": "oauth_logout",
"parameters": [
{
"name": "id_token_hint",
"in": "query",
"description": "之前签发的 id_token(校验签名且须绑定当前会话)",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "post_logout_redirect_uri",
"in": "query",
"description": "必须在客户端注册过",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "state",
"in": "query",
"description": "原样回传",
"required": false,
"schema": {
"type": "string"
}
},
{
"name": "client_id",
"in": "query",
"description": "无 id_token_hint 时可用",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "GET 未验证 hint 时返回确认页"
},
"302": {
"description": "回到 `post_logout_redirect_uri`,否则回站点首页"
}
}
}
},
"/api/v1/oauth/me": {
"get": {
"tags": [
"auth"
],
"summary": "当前登录用户",
"description": "通过会话 Cookie 或 Bearer 访问令牌返回用户自述信息,含头像地址。Bearer 令牌需具备 profile、email、avatar 权限,并校验账号与会话状态。结果在服务端缓存 300 秒,每第 5 次访问回源刷新;登出与改密会主动失效该缓存。",
"operationId": "auth_me",
"responses": {
"200": {
"description": "当前登录用户",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MeResponse"
},
"example": {
"code": 200,
"data": {
"avatar_url": "https://cdn.example.com/avatar/ada.png",
"created_at": "2025-11-20T02:15:00Z",
"displayname": "Ada",
"email": "ada@example.com",
"email_verified_at": "2026-01-05T08:30:00Z",
"is_admin": false,
"user_id": 1024,
"username": "ada",
"version": 3
},
"message": "success"
}
}
}
},
"401": {
"description": "会话未绑定用户,或账号已被删除(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"403": {
"description": "访问令牌权限不足(`scope_insufficient`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/password/reset": {
"post": {
"tags": [
"auth"
],
"summary": "申请密码重置",
"description": "校验工作量证明(payload = 邮箱的 UTF-8 字节)后,作废该用户其余未消费的重置令牌,签发新令牌(长度 `reset_token_bytes`,有效期 `reset_token_ttl_secs`),库内只存 `sha256_hex(token)` 且 `hash_key_id = \"sha256-v1\"`,同时把摘要写入缓存键 `auth:code:reset:{email}`,发信限流键 `auth:rate:reset:{email}`。",
"operationId": "auth_password_reset_request",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasswordResetRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "申请已受理;是否真的发信不对外披露",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_PasswordResetResponse"
},
"example": {
"code": 200,
"data": {
"expires_in_secs": 1800
},
"message": "success"
}
}
}
},
"400": {
"description": "`invalid_email` / `expired` / `invalid_payload`(payload 与邮箱不一致)/ `invalid_proof`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_email",
"message": "email is invalid"
}
}
}
},
"429": {
"description": "`rate_limited`(同一邮箱申请过于频繁)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "rate_limited",
"message": "too many requests, retry after 60s"
}
}
}
},
"500": {
"description": "`email`(投递失败)/ `database` / `cache` / `session` / `serialization` / `internal`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/password/reset/confirm": {
"post": {
"tags": [
"auth"
],
"summary": "确认密码重置",
"description": "校验工作量证明(payload = `token` 的 UTF-8 字节)与缓存键 `auth:code:reset:{email}`(尝试上限 `max_verify_attempts`,错误计入 `invalid_email_code`)后,条件消费数据库令牌行(`consumed_at` 单次占用),Argon2 重哈希新口令,更新 `password_hash`/`password_updated_at`/`password_must_change`/`security_version + 1`,作废其余令牌并记 `PasswordChange` 审计事件。",
"operationId": "auth_password_reset",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PasswordResetConfirmRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "口令已改写;旧口令与其余重置令牌失效",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_PasswordResetConfirmResponse"
},
"example": {
"code": 200,
"data": {
"user_id": 1234567
},
"message": "success"
}
}
}
},
"400": {
"description": "`invalid_reset_token`(令牌不存在/已消费/已作废/已过期/账号不可用或凭据代数不匹配)/ `invalid_email_code`(缓存内摘要不匹配或已过期)/ `invalid_password` / `expired` / `invalid_payload` / `invalid_proof`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_reset_token",
"message": "password reset token is invalid"
}
}
}
},
"429": {
"description": "`email_code_attempts_exceeded`(令牌尝试次数用尽)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "email_code_attempts_exceeded",
"message": "too many invalid email verification attempts"
}
}
}
},
"500": {
"description": "`password_hash`(口令重哈希失败)/ `database` / `cache` / `session` / `serialization` / `internal`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/register": {
"post": {
"tags": [
"auth"
],
"summary": "提交注册",
"description": "校验工作量证明(payload = 用户名的 UTF-8 字节)、用户名/展示名/出生日期/邮箱、邮箱验证码(键 `auth:code:register:{email}`,尝试上限 `max_verify_attempts`)后,Argon2 重哈希口令并创建用户与初始档案。成功后写会话(user_id、security_version、renew)并记审计事件。",
"operationId": "auth_register",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UserRegisterRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "注册成功且已登录",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_UserRegisterResponse"
},
"example": {
"code": 200,
"data": {
"displayname": "Alice",
"user_id": 1234567,
"username": "alice"
},
"message": "success"
}
}
}
},
"400": {
"description": "`invalid_username` / `invalid_displayname` / `invalid_email` / `invalid_birth_date` / `invalid_password` / `invalid_email_code`(验证码错误或已过期)/ `expired` / `invalid_payload` / `invalid_proof`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_email_code",
"message": "email verification code is invalid"
}
}
}
},
"403": {
"description": "`under_minimum_age`(未满最小年龄)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "under_minimum_age",
"message": "you must be at least 13 years old"
}
}
}
},
"409": {
"description": "`username_taken` / `email_taken`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "username_taken",
"message": "username is already taken"
}
}
}
},
"429": {
"description": "`email_code_attempts_exceeded`(验证码尝试次数用尽)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "email_code_attempts_exceeded",
"message": "too many invalid email verification attempts"
}
}
}
},
"500": {
"description": "`password_hash`(口令重哈希失败)/ `database` / `cache` / `session` / `serialization` / `internal`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/register/code": {
"post": {
"tags": [
"auth"
],
"summary": "发送注册验证码",
"description": "校验工作量证明(payload = 邮箱的 UTF-8 字节)与邮箱格式后,把 6 位验证码写入缓存并寄出。缓存键 `auth:code:register:{email}`,有效期由 `verify_code_ttl_secs` 决定,发码限流键 `auth:rate:register:{email}`。",
"operationId": "auth_register_code",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RegisterCodeRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "验证码已写入缓存并寄出",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_RegisterCodeResponse"
},
"example": {
"code": 200,
"data": {
"expires_in_secs": 600
},
"message": "success"
}
}
}
},
"400": {
"description": "`invalid_email`(邮箱格式)/ `expired`(挑战过期)/ `invalid_payload`(payload 与邮箱不一致)/ `invalid_proof`(未满足难度)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "invalid_email",
"message": "email is invalid"
}
}
}
},
"409": {
"description": "`email_taken`(邮箱已注册)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "email_taken",
"message": "email is already taken"
}
}
}
},
"429": {
"description": "`rate_limited`(同一邮箱发码过于频繁)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "rate_limited",
"message": "too many requests, retry after 60s"
}
}
}
},
"500": {
"description": "`email`(投递失败)/ `cache` / `session` / `serialization` / `internal`",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/revoke": {
"post": {
"tags": [
"oauth"
],
"summary": "令牌撤销(RFC 7009)",
"operationId": "oauth_revoke",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RevokeRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已处理(无论令牌是否存在)"
},
"401": {
"description": "`invalid_client`"
}
}
}
},
"/api/v1/oauth/session/logout": {
"post": {
"tags": [
"auth"
],
"summary": "登出",
"description": "销毁当前会话,并清掉该用户的 `/api/v1/oauth/me` 缓存。匿名调用同样成功,此时 `user_id` 为 `null`。",
"operationId": "auth_logout",
"responses": {
"200": {
"description": "会话已销毁",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_LogoutResponse"
},
"example": {
"code": 200,
"data": {
"user_id": 1024
},
"message": "success"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`cache`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/session/token": {
"post": {
"tags": [
"auth"
],
"summary": "用会话换取平台访问令牌",
"description": "认证中心用 Ed25519 私钥签发 JWT(`alg=EdDSA`),`aud` 固定为 `gitdata.ai`,`azp`(`app_id`)可选。任何服务只需 `/.well-known/jwks.json` 的公钥即可本地验签。`ttl_seconds` 取值 1 ~ 3600,不填或填 0 用默认 900。",
"operationId": "auth_token_issue",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "令牌已签发",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_TokenResponse"
}
}
}
},
"400": {
"description": "ttl 超出上限(`invalid_expiry`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"401": {
"description": "会话未绑定账号(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"404": {
"description": "app_id 不在清单里(`app_not_found`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/oauth/ssh-keys": {
"get": {
"tags": [
"auth"
],
"summary": "列示 SSH 公钥",
"description": "按创建时间倒序返回当前账号的公钥,含已吊销与已过期的记录。分页参数由 `page` / `page_size` 控制。查询串不是合法分页参数时由 actix-web 直接返回 400。",
"operationId": "auth_ssh_key_list",
"parameters": [
{
"name": "page",
"in": "query",
"description": "页码,从 1 开始;默认 1",
"required": false,
"schema": {
"type": "integer",
"format": "int64",
"minimum": 0
}
},
{
"name": "page_size",
"in": "query",
"description": "每页条数,默认 20,最多 100",
"required": false,
"schema": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
],
"responses": {
"200": {
"description": "公钥列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_SshKeySummary"
},
"example": {
"code": 200,
"data": [
{
"algorithm": "ed25519",
"created_at": "2026-01-02T03:04:05Z",
"description": "笔记本",
"expires_at": null,
"fingerprint": "SHA256:9pQ2mLk1v3sT6yZx8cV0bN4mR7wQ2eH5jK9aD1sF3gU",
"id": "018f2b1c-4d5e-7f80-9a1b-2c3d4e5f6072",
"last_used_at": null,
"name": "thinkpad",
"public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL9kQ2mXv7Tb1sYz8cV0bN4mR7wQ2eH5jK9aD1sF3gU thinkpad",
"revoked_at": null
}
],
"message": "success"
}
}
}
},
"401": {
"description": "会话未绑定账号(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
},
"post": {
"tags": [
"auth"
],
"summary": "添加 SSH 公钥",
"description": "名称 1~64 字符、备注最长 255 字符,公钥 32~8192 字节且必须是受支持的单行 OpenSSH 公钥,`expires_at` 必须晚于当前时间。重复公钥(指纹唯一)返回 `ssh_key_taken`。添加成功记 `PublicKeyAdded` 审计事件。",
"operationId": "auth_ssh_key_add",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SshKeyAddRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "公钥已登记",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_SshKeySummary"
},
"example": {
"code": 200,
"data": {
"algorithm": "ed25519",
"created_at": "2026-01-02T03:04:05Z",
"description": "笔记本",
"expires_at": null,
"fingerprint": "SHA256:9pQ2mLk1v3sT6yZx8cV0bN4mR7wQ2eH5jK9aD1sF3gU",
"id": "018f2b1c-4d5e-7f80-9a1b-2c3d4e5f6072",
"last_used_at": null,
"name": "thinkpad",
"public_key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL9kQ2mXv7Tb1sYz8cV0bN4mR7wQ2eH5jK9aD1sF3gU thinkpad",
"revoked_at": null
},
"message": "success"
}
}
}
},
"400": {
"description": "名称、备注、公钥或过期时间不合法(`ssh_key_name_invalid`、`malformed_request`、`ssh_key_invalid`、`invalid_expiry`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "ssh_key_invalid",
"message": "public key is invalid"
}
}
}
},
"401": {
"description": "会话未绑定账号,或账号已删除 / 不允许使用(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"409": {
"description": "同一把公钥已经登记过(`ssh_key_taken`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "ssh_key_taken",
"message": "public key is already registered"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/ssh-keys/{key_id}": {
"delete": {
"tags": [
"auth"
],
"summary": "吊销 SSH 公钥",
"description": "把公钥标记为已吊销,记录保留不硬删;重复调用幂等。公钥不存在或不属于当前账号返回 `ssh_key_not_found`。吊销成功记 `PublicKeyRemoved` 审计事件,并递增 `security_version` 让该账号既有的访问令牌一并失效。`key_id` 不是合法 UUID 时由 actix-web 的路径提取器直接返回 400。",
"operationId": "auth_ssh_key_delete",
"parameters": [
{
"name": "key_id",
"in": "path",
"description": "公钥编号",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已吊销;重复调用同样返回成功",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": 200,
"data": null,
"message": "success"
}
}
}
},
"401": {
"description": "会话未绑定账号(`unauthenticated`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "unauthenticated",
"message": "authentication required"
}
}
}
},
"404": {
"description": "公钥不存在或不属于当前账号(`ssh_key_not_found`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "ssh_key_not_found",
"message": "ssh key does not exist"
}
}
}
},
"500": {
"description": "服务端故障(`internal`、`database`、`session`、`serialization`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
},
"example": {
"code": "internal",
"message": "internal server error"
}
}
}
}
}
}
},
"/api/v1/oauth/token": {
"post": {
"tags": [
"oauth"
],
"summary": "令牌端点",
"description": "支持 `authorization_code`(PKCE)、`refresh_token`(轮换 + 重放检测)、`client_credentials`(机密客户端)。带 `openid` scope 时响应额外包含 `id_token`。",
"operationId": "oauth_token",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "令牌响应",
"content": {
"application/json": {
"schema": {}
}
}
},
"400": {
"description": "`invalid_grant` / `invalid_scope` / `unsupported_grant_type`"
},
"401": {
"description": "`invalid_client`"
}
}
}
},
"/api/v1/oauth/userinfo": {
"get": {
"tags": [
"oauth"
],
"summary": "OIDC userinfo",
"description": "需要 `openid` scope;`profile` 返回 `preferred_username` / `name`,`email` 返回 `email` / `email_verified`。令牌只接受 `Authorization: Bearer` 头(RFC 6750 §2.3),查询串携带一律 401。",
"operationId": "oauth_userinfo",
"responses": {
"200": {
"description": "标准 claims",
"content": {
"application/json": {
"schema": {}
}
}
},
"401": {
"description": "`invalid_token`"
},
"403": {
"description": "`insufficient_scope`"
}
}
}
},
"/api/v1/organizations": {
"get": {
"tags": [
"auth"
],
"summary": "列示我加入的组织",
"description": "默认只返回 ACTIVE 组织;`include_archived=true` 时一并返回已归档组织。",
"operationId": "auth_organization_list",
"responses": {
"200": {
"description": "组织列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_OrganizationSummary"
}
}
}
},
"401": {
"description": "会话未绑定账号",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"post": {
"tags": [
"auth"
],
"summary": "新建组织",
"description": "创建者自动成为 OWNER 并写入 owner/admin/member 三个内置角色。slug 全局唯一且只允许小写字母、数字与连字符。",
"operationId": "auth_organization_create",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateOrganizationBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "组织已创建",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_OrganizationSummary"
}
}
}
},
"401": {
"description": "会话未绑定账号",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"409": {
"description": "slug 已被占用",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/invites/redeem": {
"post": {
"tags": [
"auth"
],
"summary": "兑换邀请",
"description": "uses 递增与兑换记录写入同事务。定向邀请只能由目标用户兑换。",
"operationId": "auth_organization_invite_redeem",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RedeemInviteBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已加入",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_RedeemInviteResponse"
}
}
}
},
"403": {
"description": "定向邀请目标不匹配",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"409": {
"description": "邀请已用尽",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}": {
"get": {
"tags": [
"auth"
],
"summary": "组织详情",
"operationId": "auth_organization_get",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "组织详情",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_OrganizationSummary"
}
}
}
},
"404": {
"description": "组织不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"delete": {
"tags": [
"auth"
],
"summary": "删除组织",
"description": "仍存在活跃成员且未指定 `force=true` 时返回 409。删除会清理成员、角色与邀请。",
"operationId": "auth_organization_delete",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "force",
"in": "query",
"description": "是否连成员一并清理",
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "reason",
"in": "query",
"description": "删除原因,最长 512 字符",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "已删除",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_bool"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"409": {
"description": "仍有活跃成员",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"patch": {
"tags": [
"auth"
],
"summary": "修改组织",
"description": "需要 `org.update`。`expected_version` 与当前 version 不一致时返回 409。",
"operationId": "auth_organization_update",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateOrganizationBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_OrganizationSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"409": {
"description": "版本冲突",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/archive": {
"post": {
"tags": [
"auth"
],
"summary": "归档组织",
"description": "需要 `org.archive`。归档后全部权限判定返回 false,可恢复。",
"operationId": "auth_organization_archive",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ReasonBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已归档",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_OrganizationSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/bans": {
"get": {
"tags": [
"auth"
],
"summary": "封禁列表",
"description": "需要 `member.ban`。按封禁时间倒序。",
"operationId": "auth_organization_ban_list",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "page",
"in": "query",
"description": "页码,从 1 开始",
"required": false,
"schema": {
"type": "integer",
"format": "int64",
"minimum": 0
}
},
{
"name": "page_size",
"in": "query",
"description": "每页条数",
"required": false,
"schema": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
],
"responses": {
"200": {
"description": "封禁列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/bans/{user_id}": {
"get": {
"tags": [
"auth"
],
"summary": "封禁详情",
"description": "需要 `member.ban`。未封禁返回 404。",
"operationId": "auth_organization_ban_get",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "user_id",
"in": "path",
"description": "被封禁用户 id",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "封禁详情",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"404": {
"description": "未封禁或成员不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"delete": {
"tags": [
"auth"
],
"summary": "按用户解封",
"description": "需要 `member.ban`。等价于按会籍 id 解封,便于按用户维度操作。",
"operationId": "auth_organization_ban_delete",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "user_id",
"in": "path",
"description": "被解封用户 id",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "已解封",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"404": {
"description": "成员不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"patch": {
"tags": [
"auth"
],
"summary": "更新封禁",
"description": "需要 `member.ban`。改原因、到期时间与四个放行位;未封禁返回 404。",
"operationId": "auth_organization_ban_update",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "user_id",
"in": "path",
"description": "被封禁用户 id",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateBanBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"404": {
"description": "未封禁或成员不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/invites": {
"get": {
"tags": [
"auth"
],
"summary": "列示邀请",
"description": "需要 `invite.view`。不含 token 明文。",
"operationId": "auth_organization_invite_list",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "include_revoked",
"in": "query",
"description": "包含已撤销邀请",
"required": false,
"schema": {
"type": "boolean"
}
}
],
"responses": {
"200": {
"description": "邀请列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_InviteSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"post": {
"tags": [
"auth"
],
"summary": "创建邀请",
"description": "需要 `invite.create`。明文 token 只在创建响应里返回一次,之后只存 sha256。",
"operationId": "auth_organization_invite_create",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateInviteBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "邀请已创建",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_CreateInviteResponse"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/invites/{invite_id}": {
"delete": {
"tags": [
"auth"
],
"summary": "撤销邀请",
"description": "需要 `invite.revoke`。已撤销的邀请再次撤销返回 false。",
"operationId": "auth_organization_invite_revoke",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "invite_id",
"in": "path",
"description": "邀请 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已撤销",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_bool"
}
}
}
},
"404": {
"description": "邀请不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/leave": {
"post": {
"tags": [
"auth"
],
"summary": "退出组织",
"description": "OWNER 必须先转移所有权,否则返回 409。",
"operationId": "auth_organization_leave",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已退出",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_bool"
}
}
}
},
"409": {
"description": "OWNER 需先转移所有权",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members": {
"get": {
"tags": [
"auth"
],
"summary": "列示组织成员",
"description": "需要 `member.view`。默认只返回活跃成员。",
"operationId": "auth_organization_member_list",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "include_inactive",
"in": "query",
"description": "包含已退出成员",
"required": false,
"schema": {
"type": "boolean"
}
},
{
"name": "include_banned",
"in": "query",
"description": "包含已封禁成员",
"required": false,
"schema": {
"type": "boolean"
}
}
],
"responses": {
"200": {
"description": "成员列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"post": {
"tags": [
"auth"
],
"summary": "直接添加成员",
"description": "需要 `member.add`。已退出的会籍按复活处理,已封禁的返回 403。",
"operationId": "auth_organization_member_add",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AddMemberBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "成员已添加",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足或成员已封禁",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"404": {
"description": "用户不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members/@me": {
"patch": {
"tags": [
"auth"
],
"summary": "更新自己的会籍资料",
"description": "只允许修改自己的别名、头像与通知偏好;无需 `member.role.update`。",
"operationId": "auth_organization_member_update_self",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateMemberBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "不是活跃成员",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members/{member_id}": {
"get": {
"tags": [
"auth"
],
"summary": "成员详情",
"description": "需要 `member.view`。包含别名、通知偏好与封禁附加信息。",
"operationId": "auth_organization_member_get",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "成员详情",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"404": {
"description": "成员不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"delete": {
"tags": [
"auth"
],
"summary": "移除成员",
"description": "需要 `member.remove`。OWNER 不能移除,需先转移所有权。会籍行保留用于复活。",
"operationId": "auth_organization_member_remove",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "reason",
"in": "query",
"description": "移除原因",
"required": false,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"description": "已移除",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_bool"
}
}
}
},
"403": {
"description": "权限不足或目标是 OWNER",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"patch": {
"tags": [
"auth"
],
"summary": "更新成员资料",
"description": "需要 `member.role.update`。修改别名、头像、通知偏好与免打扰;封禁中的会籍走封禁接口。",
"operationId": "auth_organization_member_update",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateMemberBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足或目标已封禁",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"409": {
"description": "版本冲突",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members/{member_id}/ban": {
"post": {
"tags": [
"auth"
],
"summary": "封禁成员",
"description": "写 banned_at 并清空角色绑定与直挂权限。封禁优先于一切授权。",
"operationId": "auth_organization_member_ban",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/BanMemberBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已封禁",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members/{member_id}/permissions": {
"put": {
"tags": [
"auth"
],
"summary": "设置成员直挂权限",
"description": "整表替换语义。需要 `role.permission.update`,OWNER 不接受直挂覆盖。",
"operationId": "auth_organization_member_permissions",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SetRolePermissionsBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_String"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members/{member_id}/role": {
"patch": {
"tags": [
"auth"
],
"summary": "改粗粒度角色",
"description": "只接受 MEMBER 与 ADMIN。OWNER 只能通过转移所有权变更。",
"operationId": "auth_organization_member_role",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SetMemberRoleBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"409": {
"description": "版本冲突",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/members/{member_id}/unban": {
"post": {
"tags": [
"auth"
],
"summary": "解封成员",
"description": "清空 banned_at。已清空的角色不会自动恢复。",
"operationId": "auth_organization_member_unban",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "member_id",
"in": "path",
"description": "会籍 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已解封",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/permissions/check": {
"post": {
"tags": [
"auth"
],
"summary": "单权限判定",
"description": "拒绝不作为错误返回:`allowed=false` 附 `reason` 与 `matched_by`,便于调用方聚合。",
"operationId": "auth_organization_permission_check",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CheckPermissionBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "判定结果",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_PermissionCheck"
}
}
}
},
"403": {
"description": "查询他人权限但不是平台管理员",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/restore": {
"post": {
"tags": [
"auth"
],
"summary": "恢复归档组织",
"description": "仅 OWNER 或平台管理员可执行。",
"operationId": "auth_organization_restore",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已恢复",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_OrganizationSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/roles": {
"get": {
"tags": [
"auth"
],
"summary": "列示组织角色",
"description": "需要 `role.view`。含内置 owner/admin/member 三个系统角色。",
"operationId": "auth_organization_role_list",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "角色列表",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_RoleSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"post": {
"tags": [
"auth"
],
"summary": "新建角色",
"description": "需要 `role.create`。key 在组织内唯一,权限键必须在白名单内。",
"operationId": "auth_organization_role_create",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateRoleBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "角色已创建",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_RoleSummary"
}
}
}
},
"409": {
"description": "key 已占用",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/roles/assign": {
"post": {
"tags": [
"auth"
],
"summary": "绑定角色到成员",
"description": "需要 `role.assign`。重复绑定幂等。",
"operationId": "auth_organization_role_assign",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AssignRoleBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已绑定",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_String"
}
}
}
},
"404": {
"description": "成员或角色不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/roles/unassign": {
"post": {
"tags": [
"auth"
],
"summary": "解绑成员角色",
"description": "需要 `role.assign`。系统角色不可解绑。",
"operationId": "auth_organization_role_unassign",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/AssignRoleBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已解绑",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_Vec_String"
}
}
}
},
"403": {
"description": "系统角色不可解绑",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/roles/{role_id}": {
"get": {
"tags": [
"auth"
],
"summary": "角色详情",
"description": "需要 `role.view`。",
"operationId": "auth_organization_role_get",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "role_id",
"in": "path",
"description": "角色 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "角色详情",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_RoleSummary"
}
}
}
},
"404": {
"description": "角色不存在",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"delete": {
"tags": [
"auth"
],
"summary": "删除角色",
"description": "需要 `role.delete`。系统角色不可删;仍有成员绑定时返回 409。",
"operationId": "auth_organization_role_delete",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "role_id",
"in": "path",
"description": "角色 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已删除",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_bool"
}
}
}
},
"409": {
"description": "系统角色或仍被绑定",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"patch": {
"tags": [
"auth"
],
"summary": "修改角色",
"description": "需要 `role.update`。OWNER 系统角色不允许改 rank 与 default_role。",
"operationId": "auth_organization_role_update",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "role_id",
"in": "path",
"description": "角色 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateRoleBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_RoleSummary"
}
}
}
},
"409": {
"description": "版本冲突",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/roles/{role_id}/join": {
"post": {
"tags": [
"auth"
],
"summary": "自助加入角色",
"description": "只允许 `self_assignable = true` 的非内置角色。",
"operationId": "auth_organization_role_join",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "role_id",
"in": "path",
"description": "角色 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已加入",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "角色不可自助加入或不是活跃成员",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
},
"delete": {
"tags": [
"auth"
],
"summary": "自助退出角色",
"description": "只允许 `self_assignable = true` 的非内置角色;重复退出视为成功。",
"operationId": "auth_organization_role_leave",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "role_id",
"in": "path",
"description": "角色 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "已退出",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_MemberSummary"
}
}
}
},
"403": {
"description": "角色不可自助加入或不是活跃成员",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/roles/{role_id}/permissions": {
"put": {
"tags": [
"auth"
],
"summary": "设置角色权限",
"description": "整体替换语义,是角色权限的唯一写入口。需要 `role.permission.update`。",
"operationId": "auth_organization_role_permissions",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
},
{
"name": "role_id",
"in": "path",
"description": "角色 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SetRolePermissionsBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已更新",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_RoleSummary"
}
}
}
},
"403": {
"description": "权限不足或系统 OWNER 角色",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/api/v1/organizations/{organization_id}/transfer": {
"post": {
"tags": [
"auth"
],
"summary": "转移 OWNER",
"description": "目标必须是活跃成员。原 Owner 降为 ADMIN。",
"operationId": "auth_organization_transfer",
"parameters": [
{
"name": "organization_id",
"in": "path",
"description": "组织 id",
"required": true,
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TransferBody"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "已转移",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_OrganizationSummary"
}
}
}
},
"403": {
"description": "权限不足",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
},
"404": {
"description": "目标不是活跃成员",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_NoData"
}
}
}
}
}
}
},
"/health": {
"get": {
"tags": [
"health"
],
"summary": "存活探针",
"description": "只回答进程是否还在处理请求,不触碰任何外部依赖:数据库、Redis、RocketMQ 全都不可用时依然返回 200。用于区分「进程死了」和「依赖挂了」。",
"operationId": "health_live",
"responses": {
"200": {
"description": "进程存活",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_HealthResponse"
}
}
}
}
}
}
},
"/ready": {
"get": {
"tags": [
"health"
],
"summary": "就绪探针",
"description": "并发探测启动时必须连上的三个依赖——PostgreSQL、Redis、RocketMQ,全部可用返回 200,任一不可用返回 503 并在 `checks` 里标出是哪一项。单项探测上限 2 秒,失败细节只写日志,不进响应体。",
"operationId": "health_ready",
"responses": {
"200": {
"description": "全部依赖可用",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_ReadinessResponse"
}
}
}
},
"503": {
"description": "至少一个依赖不可用(`unavailable`)",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Envelope_ReadinessResponse"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"AccessTokenCreateRequest": {
"type": "object",
"required": [
"name",
"scope"
],
"properties": {
"description": {
"type": [
"string",
"null"
]
},
"expires_in_secs": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"name": {
"type": "string"
},
"scope": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"AccessTokenCreateResponse": {
"type": "object",
"required": [
"id",
"name",
"token",
"scope",
"created_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"scope": {
"type": "array",
"items": {
"type": "string"
}
},
"token": {
"type": "string"
}
}
},
"AccessTokenSummary": {
"type": "object",
"required": [
"id",
"name",
"scope",
"created_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"fingerprint": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"name": {
"type": "string"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"scope": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"AddMemberBody": {
"type": "object",
"required": [
"user_id"
],
"properties": {
"role": {
"oneOf": [
{
"$ref": "#/components/schemas/OrgMemberRole"
},
{
"type": "null"
}
]
},
"role_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"user_id": {
"type": "integer",
"format": "int64"
}
}
},
"AppTokenRequest": {
"type": "object",
"required": [
"app_id"
],
"properties": {
"app_id": {
"type": "string"
},
"ttl_seconds": {
"type": [
"integer",
"null"
],
"format": "int32",
"minimum": 0
}
}
},
"AppTokenResponse": {
"type": "object",
"required": [
"app_id",
"audience",
"key_id",
"token",
"issued_at",
"expires_at"
],
"properties": {
"app_id": {
"type": "string"
},
"audience": {
"type": "string"
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"issued_at": {
"type": "string",
"format": "date-time"
},
"key_id": {
"type": "string"
},
"token": {
"type": "string"
}
}
},
"AssignRoleBody": {
"type": "object",
"required": [
"member_id",
"role_key"
],
"properties": {
"member_id": {
"type": "string",
"format": "uuid"
},
"role_key": {
"type": "string"
}
}
},
"BanMemberBody": {
"type": "object",
"properties": {
"reason": {
"type": [
"string",
"null"
]
}
}
},
"ChallengeResponse": {
"type": "object",
"required": [
"context",
"difficulty",
"issued_at",
"expires_at"
],
"properties": {
"context": {
"type": "string"
},
"difficulty": {
"type": "integer",
"format": "int32",
"minimum": 0
},
"expires_at": {
"type": "integer",
"format": "int64",
"minimum": 0
},
"issued_at": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"CheckPermissionBody": {
"type": "object",
"required": [
"permission"
],
"properties": {
"permission": {
"type": "string"
},
"user_id": {
"type": [
"integer",
"null"
],
"format": "int64"
}
}
},
"ComponentCheck": {
"type": "object",
"required": [
"component",
"ready"
],
"properties": {
"component": {
"type": "string"
},
"ready": {
"type": "boolean"
}
}
},
"ConsentDecision": {
"type": "object",
"required": [
"redirect"
],
"properties": {
"redirect": {
"type": "string",
"description": "下一步跳转:允许则回 `/api/v1/oauth/authorize?...`,拒绝则回客户端并带 `error=access_denied`。"
}
}
},
"ConsentForm": {
"type": "object",
"description": "同意页提交体:授权参数在查询串里,请求体只带决定。",
"required": [
"decision"
],
"properties": {
"decision": {
"type": "string"
}
}
},
"ConsentPreview": {
"type": "object",
"required": [
"client_id",
"client_name",
"scopes",
"username"
],
"properties": {
"client_id": {
"type": "string"
},
"client_name": {
"type": "string"
},
"scopes": {
"type": "array",
"items": {
"type": "string"
}
},
"username": {
"type": "string"
}
}
},
"CreateInviteBody": {
"type": "object",
"properties": {
"max_uses": {
"type": "integer",
"format": "int32"
},
"role_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"target_user_id": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"ttl_secs": {
"type": [
"integer",
"null"
],
"format": "int64",
"minimum": 0
}
}
},
"CreateInviteResponse": {
"type": "object",
"required": [
"invite",
"token"
],
"properties": {
"invite": {
"$ref": "#/components/schemas/InviteSummary"
},
"token": {
"type": "string"
}
}
},
"CreateOrganizationBody": {
"type": "object",
"required": [
"slug",
"name"
],
"properties": {
"allow_invite": {
"type": [
"boolean",
"null"
]
},
"allow_join": {
"type": [
"boolean",
"null"
]
},
"allow_join_level": {
"type": [
"integer",
"null"
],
"format": "int32"
},
"avatar_url": {
"type": [
"string",
"null"
]
},
"description": {
"type": [
"string",
"null"
]
},
"join_policy": {
"oneOf": [
{
"$ref": "#/components/schemas/OrganizationJoinPolicy"
},
{
"type": "null"
}
]
},
"member_must_enable_2fa": {
"type": [
"boolean",
"null"
]
},
"name": {
"type": "string"
},
"require_email_verified": {
"type": [
"boolean",
"null"
]
},
"require_mfa": {
"type": [
"boolean",
"null"
]
},
"slug": {
"type": "string"
},
"welcome_message": {
"type": [
"string",
"null"
]
}
}
},
"CreateRoleBody": {
"type": "object",
"required": [
"key",
"name"
],
"properties": {
"default_role": {
"type": "boolean"
},
"description": {
"type": [
"string",
"null"
]
},
"key": {
"type": "string"
},
"name": {
"type": "string"
},
"permissions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PermissionGrant"
}
},
"rank": {
"type": "integer",
"format": "int32"
},
"self_assignable": {
"type": "boolean"
}
}
},
"DeleteOrgQuery": {
"type": "object",
"properties": {
"force": {
"type": "boolean"
},
"reason": {
"type": [
"string",
"null"
]
}
}
},
"Envelope_AccessTokenCreateResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"id",
"name",
"token",
"scope",
"created_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"scope": {
"type": "array",
"items": {
"type": "string"
}
},
"token": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_AppTokenResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"app_id",
"audience",
"key_id",
"token",
"issued_at",
"expires_at"
],
"properties": {
"app_id": {
"type": "string"
},
"audience": {
"type": "string"
},
"expires_at": {
"type": "string",
"format": "date-time"
},
"issued_at": {
"type": "string",
"format": "date-time"
},
"key_id": {
"type": "string"
},
"token": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_ChallengeResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"context",
"difficulty",
"issued_at",
"expires_at"
],
"properties": {
"context": {
"type": "string"
},
"difficulty": {
"type": "integer",
"format": "int32",
"minimum": 0
},
"expires_at": {
"type": "integer",
"format": "int64",
"minimum": 0
},
"issued_at": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_CreateInviteResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"invite",
"token"
],
"properties": {
"invite": {
"$ref": "#/components/schemas/InviteSummary"
},
"token": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_HealthResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"status",
"version"
],
"properties": {
"status": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_LoginCodeResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"expires_in_secs"
],
"properties": {
"expires_in_secs": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_LogoutResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"properties": {
"user_id": {
"type": [
"integer",
"null"
],
"format": "int64"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_MeResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"user_id",
"username",
"email",
"is_admin",
"created_at",
"version"
],
"properties": {
"avatar_url": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"displayname": {
"type": [
"string",
"null"
]
},
"email": {
"type": "string"
},
"email_verified_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"is_admin": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int32"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_MemberSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"id",
"organization_id",
"user_id",
"username",
"role",
"role_keys",
"permissions",
"joined_at",
"join_method",
"message_notifications",
"muted",
"mobile_push",
"suppress_everyone",
"suppress_roles",
"hide_muted_channels",
"ban_allow_agent_join",
"ban_allow_speak",
"ban_allow_push_repo",
"ban_allow_comment_any",
"version"
],
"properties": {
"alias_avatar_url": {
"type": [
"string",
"null"
]
},
"alias_name": {
"type": [
"string",
"null"
]
},
"ban_allow_agent_join": {
"type": "boolean"
},
"ban_allow_comment_any": {
"type": "boolean"
},
"ban_allow_push_repo": {
"type": "boolean"
},
"ban_allow_speak": {
"type": "boolean"
},
"ban_expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"ban_reason": {
"type": [
"string",
"null"
]
},
"banned_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"displayname": {
"type": [
"string",
"null"
]
},
"hide_muted_channels": {
"type": "boolean"
},
"id": {
"type": "string",
"format": "uuid"
},
"invited_by": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"join_method": {
"$ref": "#/components/schemas/OrgJoinMethod"
},
"joined_at": {
"type": "string",
"format": "date-time"
},
"last_active_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"left_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"message_notifications": {
"$ref": "#/components/schemas/MessageNotifications"
},
"mobile_push": {
"type": "boolean"
},
"mute_until": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"muted": {
"type": "boolean"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"role": {
"$ref": "#/components/schemas/OrgMemberRole"
},
"role_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"suppress_everyone": {
"type": "boolean"
},
"suppress_roles": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int32"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_NoData": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"default": null
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_OrganizationSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"id",
"slug",
"name",
"status",
"owner_user_id",
"member_count",
"version",
"created_at",
"updated_at",
"join_policy",
"allow_join",
"require_email_verified",
"require_mfa",
"member_must_enable_2fa",
"allow_invite",
"allow_join_level"
],
"properties": {
"allow_invite": {
"type": "boolean"
},
"allow_join": {
"type": "boolean"
},
"allow_join_level": {
"type": "integer",
"format": "int32"
},
"archived_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"avatar_url": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"join_policy": {
"$ref": "#/components/schemas/OrganizationJoinPolicy"
},
"member_count": {
"type": "integer",
"format": "int64"
},
"member_must_enable_2fa": {
"type": "boolean"
},
"my_role": {
"oneOf": [
{
"$ref": "#/components/schemas/OrgMemberRole"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"owner_user_id": {
"type": "integer",
"format": "int64"
},
"require_email_verified": {
"type": "boolean"
},
"require_mfa": {
"type": "boolean"
},
"slug": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/OrganizationStatus"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"version": {
"type": "integer",
"format": "int32"
},
"welcome_message": {
"type": [
"string",
"null"
]
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_PasswordResetConfirmResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"user_id"
],
"properties": {
"user_id": {
"type": "integer",
"format": "int64"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_PasswordResetResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"expires_in_secs"
],
"properties": {
"expires_in_secs": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_PermissionCheck": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"allowed",
"reason",
"matched_by",
"organization_version"
],
"properties": {
"allowed": {
"type": "boolean"
},
"matched_by": {
"type": "string"
},
"organization_version": {
"type": "integer",
"format": "int32"
},
"reason": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_ReadinessResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"status",
"checks"
],
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ComponentCheck"
}
},
"status": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_RedeemInviteResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"organization_id",
"member_id",
"joined"
],
"properties": {
"joined": {
"type": "boolean"
},
"member_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_RegisterCodeResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"expires_in_secs"
],
"properties": {
"expires_in_secs": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_RoleSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"id",
"organization_id",
"key",
"name",
"rank",
"system",
"default_role",
"self_assignable",
"permissions",
"member_count",
"created_at",
"updated_at",
"version",
"position"
],
"properties": {
"color": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"default_role": {
"type": "boolean"
},
"description": {
"type": [
"string",
"null"
]
},
"emoji": {
"type": [
"string",
"null"
]
},
"icon_hash": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"key": {
"type": "string"
},
"member_count": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"permissions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PermissionGrant"
}
},
"position": {
"type": "integer",
"format": "int64"
},
"rank": {
"type": "integer",
"format": "int32"
},
"self_assignable": {
"type": "boolean"
},
"system": {
"type": "boolean"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"version": {
"type": "integer",
"format": "int32"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_SshKeySummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"id",
"name",
"algorithm",
"fingerprint",
"public_key",
"created_at"
],
"properties": {
"algorithm": {
"$ref": "#/components/schemas/SshKeyAlgorithm"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"fingerprint": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"name": {
"type": "string"
},
"public_key": {
"type": "string"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_TokenResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"token",
"token_type",
"kid",
"issued_at",
"expires_at"
],
"properties": {
"expires_at": {
"type": "string",
"format": "date-time"
},
"issued_at": {
"type": "string",
"format": "date-time"
},
"kid": {
"type": "string"
},
"token": {
"type": "string"
},
"token_type": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_UserLoginResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"user_id",
"username",
"mfa_required"
],
"properties": {
"challenge": {
"type": [
"string",
"null"
]
},
"displayname": {
"type": [
"string",
"null"
]
},
"mfa_required": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_UserRegisterResponse": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "object",
"required": [
"user_id",
"username"
],
"properties": {
"displayname": {
"type": [
"string",
"null"
]
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_AccessTokenSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name",
"scope",
"created_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"fingerprint": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"name": {
"type": "string"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"scope": {
"type": "array",
"items": {
"type": "string"
}
}
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_InviteSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"organization_id",
"method",
"created_by",
"max_uses",
"uses",
"created_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"created_by": {
"type": "integer",
"format": "int64"
},
"email": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"id": {
"type": "string",
"format": "uuid"
},
"max_uses": {
"type": "integer",
"format": "int32"
},
"method": {
"$ref": "#/components/schemas/OrgJoinMethod"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"role_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"target_user_id": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"uses": {
"type": "integer",
"format": "int32"
}
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_MemberSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"organization_id",
"user_id",
"username",
"role",
"role_keys",
"permissions",
"joined_at",
"join_method",
"message_notifications",
"muted",
"mobile_push",
"suppress_everyone",
"suppress_roles",
"hide_muted_channels",
"ban_allow_agent_join",
"ban_allow_speak",
"ban_allow_push_repo",
"ban_allow_comment_any",
"version"
],
"properties": {
"alias_avatar_url": {
"type": [
"string",
"null"
]
},
"alias_name": {
"type": [
"string",
"null"
]
},
"ban_allow_agent_join": {
"type": "boolean"
},
"ban_allow_comment_any": {
"type": "boolean"
},
"ban_allow_push_repo": {
"type": "boolean"
},
"ban_allow_speak": {
"type": "boolean"
},
"ban_expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"ban_reason": {
"type": [
"string",
"null"
]
},
"banned_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"displayname": {
"type": [
"string",
"null"
]
},
"hide_muted_channels": {
"type": "boolean"
},
"id": {
"type": "string",
"format": "uuid"
},
"invited_by": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"join_method": {
"$ref": "#/components/schemas/OrgJoinMethod"
},
"joined_at": {
"type": "string",
"format": "date-time"
},
"last_active_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"left_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"message_notifications": {
"$ref": "#/components/schemas/MessageNotifications"
},
"mobile_push": {
"type": "boolean"
},
"mute_until": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"muted": {
"type": "boolean"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"role": {
"$ref": "#/components/schemas/OrgMemberRole"
},
"role_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"suppress_everyone": {
"type": "boolean"
},
"suppress_roles": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int32"
}
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_OrganizationSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"slug",
"name",
"status",
"owner_user_id",
"member_count",
"version",
"created_at",
"updated_at",
"join_policy",
"allow_join",
"require_email_verified",
"require_mfa",
"member_must_enable_2fa",
"allow_invite",
"allow_join_level"
],
"properties": {
"allow_invite": {
"type": "boolean"
},
"allow_join": {
"type": "boolean"
},
"allow_join_level": {
"type": "integer",
"format": "int32"
},
"archived_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"avatar_url": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"join_policy": {
"$ref": "#/components/schemas/OrganizationJoinPolicy"
},
"member_count": {
"type": "integer",
"format": "int64"
},
"member_must_enable_2fa": {
"type": "boolean"
},
"my_role": {
"oneOf": [
{
"$ref": "#/components/schemas/OrgMemberRole"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"owner_user_id": {
"type": "integer",
"format": "int64"
},
"require_email_verified": {
"type": "boolean"
},
"require_mfa": {
"type": "boolean"
},
"slug": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/OrganizationStatus"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"version": {
"type": "integer",
"format": "int32"
},
"welcome_message": {
"type": [
"string",
"null"
]
}
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_RoleSummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"organization_id",
"key",
"name",
"rank",
"system",
"default_role",
"self_assignable",
"permissions",
"member_count",
"created_at",
"updated_at",
"version",
"position"
],
"properties": {
"color": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"default_role": {
"type": "boolean"
},
"description": {
"type": [
"string",
"null"
]
},
"emoji": {
"type": [
"string",
"null"
]
},
"icon_hash": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"key": {
"type": "string"
},
"member_count": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"permissions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PermissionGrant"
}
},
"position": {
"type": "integer",
"format": "int64"
},
"rank": {
"type": "integer",
"format": "int32"
},
"self_assignable": {
"type": "boolean"
},
"system": {
"type": "boolean"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"version": {
"type": "integer",
"format": "int32"
}
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_SshKeySummary": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"name",
"algorithm",
"fingerprint",
"public_key",
"created_at"
],
"properties": {
"algorithm": {
"$ref": "#/components/schemas/SshKeyAlgorithm"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"fingerprint": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"name": {
"type": "string"
},
"public_key": {
"type": "string"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_Vec_String": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "array",
"items": {
"type": "string"
}
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"Envelope_bool": {
"type": "object",
"required": [
"code",
"message"
],
"properties": {
"code": {
"type": "integer",
"format": "int32"
},
"data": {
"type": "boolean"
},
"error": {
"type": [
"string",
"null"
]
},
"error_code": {
"type": [
"string",
"null"
]
},
"message": {
"type": "string"
},
"request_id": {
"type": "string"
}
}
},
"HealthResponse": {
"type": "object",
"required": [
"status",
"version"
],
"properties": {
"status": {
"type": "string"
},
"version": {
"type": "string"
}
}
},
"InviteSummary": {
"type": "object",
"required": [
"id",
"organization_id",
"method",
"created_by",
"max_uses",
"uses",
"created_at"
],
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"created_by": {
"type": "integer",
"format": "int64"
},
"email": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"id": {
"type": "string",
"format": "uuid"
},
"max_uses": {
"type": "integer",
"format": "int32"
},
"method": {
"$ref": "#/components/schemas/OrgJoinMethod"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"role_id": {
"type": [
"string",
"null"
],
"format": "uuid"
},
"target_user_id": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"uses": {
"type": "integer",
"format": "int32"
}
}
},
"LoginCodeRequest": {
"type": "object",
"required": [
"email",
"pow_payload"
],
"properties": {
"email": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
}
}
},
"LoginCodeResponse": {
"type": "object",
"required": [
"expires_in_secs"
],
"properties": {
"expires_in_secs": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"LoginCodeVerifyRequest": {
"type": "object",
"required": [
"email",
"email_code",
"pow_payload"
],
"properties": {
"email": {
"type": "string"
},
"email_code": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
}
}
},
"LoginVerifyRequest": {
"type": "object",
"required": [
"challenge",
"code"
],
"properties": {
"challenge": {
"type": "string"
},
"code": {
"type": "string"
}
}
},
"LogoutResponse": {
"type": "object",
"properties": {
"user_id": {
"type": [
"integer",
"null"
],
"format": "int64"
}
}
},
"MeResponse": {
"type": "object",
"required": [
"user_id",
"username",
"email",
"is_admin",
"created_at",
"version"
],
"properties": {
"avatar_url": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"displayname": {
"type": [
"string",
"null"
]
},
"email": {
"type": "string"
},
"email_verified_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"is_admin": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int32"
}
}
},
"MemberListQuery": {
"type": "object",
"properties": {
"include_banned": {
"type": [
"boolean",
"null"
]
},
"include_inactive": {
"type": [
"boolean",
"null"
]
},
"page": {
"type": [
"integer",
"null"
],
"format": "int64",
"minimum": 0
},
"page_size": {
"type": [
"integer",
"null"
],
"format": "int64",
"minimum": 0
}
}
},
"MemberSummary": {
"type": "object",
"required": [
"id",
"organization_id",
"user_id",
"username",
"role",
"role_keys",
"permissions",
"joined_at",
"join_method",
"message_notifications",
"muted",
"mobile_push",
"suppress_everyone",
"suppress_roles",
"hide_muted_channels",
"ban_allow_agent_join",
"ban_allow_speak",
"ban_allow_push_repo",
"ban_allow_comment_any",
"version"
],
"properties": {
"alias_avatar_url": {
"type": [
"string",
"null"
]
},
"alias_name": {
"type": [
"string",
"null"
]
},
"ban_allow_agent_join": {
"type": "boolean"
},
"ban_allow_comment_any": {
"type": "boolean"
},
"ban_allow_push_repo": {
"type": "boolean"
},
"ban_allow_speak": {
"type": "boolean"
},
"ban_expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"ban_reason": {
"type": [
"string",
"null"
]
},
"banned_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"displayname": {
"type": [
"string",
"null"
]
},
"hide_muted_channels": {
"type": "boolean"
},
"id": {
"type": "string",
"format": "uuid"
},
"invited_by": {
"type": [
"integer",
"null"
],
"format": "int64"
},
"join_method": {
"$ref": "#/components/schemas/OrgJoinMethod"
},
"joined_at": {
"type": "string",
"format": "date-time"
},
"last_active_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"left_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"message_notifications": {
"$ref": "#/components/schemas/MessageNotifications"
},
"mobile_push": {
"type": "boolean"
},
"mute_until": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"muted": {
"type": "boolean"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"permissions": {
"type": "array",
"items": {
"type": "string"
}
},
"role": {
"$ref": "#/components/schemas/OrgMemberRole"
},
"role_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"suppress_everyone": {
"type": "boolean"
},
"suppress_roles": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int32"
}
}
},
"MessageNotifications": {
"type": "string",
"description": "会籍的通知偏好,对应旧 `space_members.message_notifications`。\n旧表用 0/1/2 存,这里用字符串存,便于跨服务读写时直接透传。",
"enum": [
"all",
"mentions",
"nothing"
]
},
"NoData": {
"default": null
},
"OrgInvitePath": {
"type": "object",
"required": [
"organization_id",
"invite_id"
],
"properties": {
"invite_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
}
}
},
"OrgJoinMethod": {
"type": "string",
"enum": [
"direct",
"invite_link",
"invite_targeted",
"invite_email"
]
},
"OrgListQuery": {
"type": "object",
"properties": {
"include_archived": {
"type": [
"boolean",
"null"
]
},
"page": {
"type": [
"integer",
"null"
],
"format": "int64",
"minimum": 0
},
"page_size": {
"type": [
"integer",
"null"
],
"format": "int64",
"minimum": 0
}
}
},
"OrgMemberPath": {
"type": "object",
"required": [
"organization_id",
"member_id"
],
"properties": {
"member_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
}
}
},
"OrgMemberRole": {
"type": "string",
"enum": [
"member",
"admin",
"owner"
]
},
"OrgPath": {
"type": "object",
"required": [
"organization_id"
],
"properties": {
"organization_id": {
"type": "string",
"format": "uuid"
}
}
},
"OrgRolePath": {
"type": "object",
"required": [
"organization_id",
"role_id"
],
"properties": {
"organization_id": {
"type": "string",
"format": "uuid"
},
"role_id": {
"type": "string",
"format": "uuid"
}
}
},
"OrganizationJoinPolicy": {
"type": "string",
"enum": [
"open",
"approval",
"invite_only",
"private"
]
},
"OrganizationStatus": {
"type": "string",
"enum": [
"active",
"suspended",
"archived"
]
},
"OrganizationSummary": {
"type": "object",
"required": [
"id",
"slug",
"name",
"status",
"owner_user_id",
"member_count",
"version",
"created_at",
"updated_at",
"join_policy",
"allow_join",
"require_email_verified",
"require_mfa",
"member_must_enable_2fa",
"allow_invite",
"allow_join_level"
],
"properties": {
"allow_invite": {
"type": "boolean"
},
"allow_join": {
"type": "boolean"
},
"allow_join_level": {
"type": "integer",
"format": "int32"
},
"archived_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"avatar_url": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"join_policy": {
"$ref": "#/components/schemas/OrganizationJoinPolicy"
},
"member_count": {
"type": "integer",
"format": "int64"
},
"member_must_enable_2fa": {
"type": "boolean"
},
"my_role": {
"oneOf": [
{
"$ref": "#/components/schemas/OrgMemberRole"
},
{
"type": "null"
}
]
},
"name": {
"type": "string"
},
"owner_user_id": {
"type": "integer",
"format": "int64"
},
"require_email_verified": {
"type": "boolean"
},
"require_mfa": {
"type": "boolean"
},
"slug": {
"type": "string"
},
"status": {
"$ref": "#/components/schemas/OrganizationStatus"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"version": {
"type": "integer",
"format": "int32"
},
"welcome_message": {
"type": [
"string",
"null"
]
}
}
},
"PasswordResetConfirmRequest": {
"type": "object",
"required": [
"token",
"password_hash",
"pow_payload"
],
"properties": {
"password_hash": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
},
"token": {
"type": "string"
}
}
},
"PasswordResetConfirmResponse": {
"type": "object",
"required": [
"user_id"
],
"properties": {
"user_id": {
"type": "integer",
"format": "int64"
}
}
},
"PasswordResetRequest": {
"type": "object",
"required": [
"email",
"pow_payload"
],
"properties": {
"email": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
}
}
},
"PasswordResetResponse": {
"type": "object",
"required": [
"expires_in_secs"
],
"properties": {
"expires_in_secs": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"PermissionCheck": {
"type": "object",
"required": [
"allowed",
"reason",
"matched_by",
"organization_version"
],
"properties": {
"allowed": {
"type": "boolean"
},
"matched_by": {
"type": "string"
},
"organization_version": {
"type": "integer",
"format": "int32"
},
"reason": {
"type": "string"
}
}
},
"PermissionEffect": {
"type": "string",
"enum": [
"allow",
"deny"
]
},
"PermissionGrant": {
"type": "object",
"required": [
"permission",
"effect"
],
"properties": {
"effect": {
"$ref": "#/components/schemas/PermissionEffect"
},
"permission": {
"type": "string"
}
}
},
"PowProofRequest": {
"type": "object",
"required": [
"nonce",
"payload"
],
"properties": {
"nonce": {
"type": "integer",
"format": "int64",
"minimum": 0
},
"payload": {
"type": "array",
"items": {
"type": "integer",
"format": "int32",
"minimum": 0
}
}
}
},
"ReadinessResponse": {
"type": "object",
"required": [
"status",
"checks"
],
"properties": {
"checks": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ComponentCheck"
}
},
"status": {
"type": "string"
}
}
},
"ReasonBody": {
"type": "object",
"properties": {
"reason": {
"type": [
"string",
"null"
]
}
}
},
"RedeemInviteBody": {
"type": "object",
"required": [
"token"
],
"properties": {
"token": {
"type": "string"
}
}
},
"RedeemInviteResponse": {
"type": "object",
"required": [
"organization_id",
"member_id",
"joined"
],
"properties": {
"joined": {
"type": "boolean"
},
"member_id": {
"type": "string",
"format": "uuid"
},
"organization_id": {
"type": "string",
"format": "uuid"
}
}
},
"RegisterCodeRequest": {
"type": "object",
"required": [
"email",
"pow_payload"
],
"properties": {
"email": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
}
}
},
"RegisterCodeResponse": {
"type": "object",
"required": [
"expires_in_secs"
],
"properties": {
"expires_in_secs": {
"type": "integer",
"format": "int64",
"minimum": 0
}
}
},
"RevokeRequest": {
"type": "object",
"required": [
"token"
],
"properties": {
"client_id": {
"type": [
"string",
"null"
]
},
"client_secret": {
"type": [
"string",
"null"
]
},
"token": {
"type": "string"
}
}
},
"RoleSummary": {
"type": "object",
"required": [
"id",
"organization_id",
"key",
"name",
"rank",
"system",
"default_role",
"self_assignable",
"permissions",
"member_count",
"created_at",
"updated_at",
"version",
"position"
],
"properties": {
"color": {
"type": [
"string",
"null"
]
},
"created_at": {
"type": "string",
"format": "date-time"
},
"default_role": {
"type": "boolean"
},
"description": {
"type": [
"string",
"null"
]
},
"emoji": {
"type": [
"string",
"null"
]
},
"icon_hash": {
"type": [
"string",
"null"
]
},
"id": {
"type": "string",
"format": "uuid"
},
"key": {
"type": "string"
},
"member_count": {
"type": "integer",
"format": "int64"
},
"name": {
"type": "string"
},
"organization_id": {
"type": "string",
"format": "uuid"
},
"permissions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PermissionGrant"
}
},
"position": {
"type": "integer",
"format": "int64"
},
"rank": {
"type": "integer",
"format": "int32"
},
"self_assignable": {
"type": "boolean"
},
"system": {
"type": "boolean"
},
"updated_at": {
"type": "string",
"format": "date-time"
},
"version": {
"type": "integer",
"format": "int32"
}
}
},
"SetMemberRoleBody": {
"type": "object",
"required": [
"role"
],
"properties": {
"expected_version": {
"type": "integer",
"format": "int32"
},
"role": {
"$ref": "#/components/schemas/OrgMemberRole"
}
}
},
"SetRolePermissionsBody": {
"type": "object",
"properties": {
"permissions": {
"type": "array",
"items": {
"$ref": "#/components/schemas/PermissionGrant"
}
}
}
},
"SshKeyAddRequest": {
"type": "object",
"required": [
"name",
"public_key"
],
"properties": {
"description": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"name": {
"type": "string"
},
"public_key": {
"type": "string"
}
}
},
"SshKeyAlgorithm": {
"type": "string",
"enum": [
"rsa",
"ed25519",
"ecdsa"
]
},
"SshKeySummary": {
"type": "object",
"required": [
"id",
"name",
"algorithm",
"fingerprint",
"public_key",
"created_at"
],
"properties": {
"algorithm": {
"$ref": "#/components/schemas/SshKeyAlgorithm"
},
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": [
"string",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"fingerprint": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"last_used_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"name": {
"type": "string"
},
"public_key": {
"type": "string"
},
"revoked_at": {
"type": [
"string",
"null"
],
"format": "date-time"
}
}
},
"TokenRequest": {
"type": "object",
"required": [
"grant_type"
],
"properties": {
"client_id": {
"type": [
"string",
"null"
]
},
"client_secret": {
"type": [
"string",
"null"
]
},
"code": {
"type": [
"string",
"null"
]
},
"code_verifier": {
"type": [
"string",
"null"
]
},
"grant_type": {
"type": "string"
},
"redirect_uri": {
"type": [
"string",
"null"
]
},
"refresh_token": {
"type": [
"string",
"null"
]
},
"scope": {
"type": [
"string",
"null"
]
}
}
},
"TokenResponse": {
"type": "object",
"required": [
"token",
"token_type",
"kid",
"issued_at",
"expires_at"
],
"properties": {
"expires_at": {
"type": "string",
"format": "date-time"
},
"issued_at": {
"type": "string",
"format": "date-time"
},
"kid": {
"type": "string"
},
"token": {
"type": "string"
},
"token_type": {
"type": "string"
}
}
},
"TransferBody": {
"type": "object",
"required": [
"target_user_id"
],
"properties": {
"target_user_id": {
"type": "integer",
"format": "int64"
}
}
},
"UpdateBanBody": {
"type": "object",
"description": "封禁更新:原因、到期时间与四个放行位。缺失表示不变,null 表示清空。",
"properties": {
"allow_agent_join": {
"type": [
"boolean",
"null"
]
},
"allow_comment_any": {
"type": [
"boolean",
"null"
]
},
"allow_push_repo": {
"type": [
"boolean",
"null"
]
},
"allow_speak": {
"type": [
"boolean",
"null"
]
},
"expires_at": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"reason": {
"type": [
"string",
"null"
]
}
}
},
"UpdateMemberBody": {
"type": "object",
"description": "会籍更新:管理端可改别名、通知偏好、免打扰与封禁附加信息。\n所有字段缺失表示不变,显式 null 表示清空(仅限 Option 字段)。",
"properties": {
"alias_avatar_url": {
"type": [
"string",
"null"
]
},
"alias_name": {
"type": [
"string",
"null"
]
},
"expected_version": {
"type": "integer",
"format": "int32"
},
"hide_muted_channels": {
"type": [
"boolean",
"null"
]
},
"message_notifications": {
"oneOf": [
{
"$ref": "#/components/schemas/MessageNotifications"
},
{
"type": "null"
}
]
},
"mobile_push": {
"type": [
"boolean",
"null"
]
},
"mute_until": {
"type": [
"string",
"null"
],
"format": "date-time"
},
"muted": {
"type": [
"boolean",
"null"
]
},
"suppress_everyone": {
"type": [
"boolean",
"null"
]
},
"suppress_roles": {
"type": [
"boolean",
"null"
]
}
}
},
"UpdateOrganizationBody": {
"type": "object",
"properties": {
"allow_invite": {
"type": [
"boolean",
"null"
]
},
"allow_join": {
"type": [
"boolean",
"null"
]
},
"allow_join_level": {
"type": [
"integer",
"null"
],
"format": "int32"
},
"avatar_url": {
"type": [
"string",
"null"
]
},
"description": {
"type": [
"string",
"null"
]
},
"expected_version": {
"type": "integer",
"format": "int32"
},
"join_policy": {
"oneOf": [
{
"$ref": "#/components/schemas/OrganizationJoinPolicy"
},
{
"type": "null"
}
]
},
"member_must_enable_2fa": {
"type": [
"boolean",
"null"
]
},
"name": {
"type": [
"string",
"null"
]
},
"require_email_verified": {
"type": [
"boolean",
"null"
]
},
"require_mfa": {
"type": [
"boolean",
"null"
]
},
"welcome_message": {
"type": [
"string",
"null"
]
}
}
},
"UpdateRoleBody": {
"type": "object",
"properties": {
"default_role": {
"type": [
"boolean",
"null"
]
},
"description": {
"type": [
"string",
"null"
]
},
"expected_version": {
"type": "integer",
"format": "int32"
},
"name": {
"type": [
"string",
"null"
]
},
"rank": {
"type": [
"integer",
"null"
],
"format": "int32"
},
"self_assignable": {
"type": [
"boolean",
"null"
]
}
}
},
"UserLoginRequest": {
"type": "object",
"required": [
"identity",
"password_hash",
"pow_payload"
],
"properties": {
"identity": {
"type": "string"
},
"password_hash": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
}
}
},
"UserLoginResponse": {
"type": "object",
"required": [
"user_id",
"username",
"mfa_required"
],
"properties": {
"challenge": {
"type": [
"string",
"null"
]
},
"displayname": {
"type": [
"string",
"null"
]
},
"mfa_required": {
"type": "boolean"
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
}
}
},
"UserRegisterRequest": {
"type": "object",
"required": [
"username",
"birth_date",
"email",
"password_hash",
"email_code",
"pow_payload"
],
"properties": {
"birth_date": {
"type": "string"
},
"displayname": {
"type": [
"string",
"null"
]
},
"email": {
"type": "string"
},
"email_code": {
"type": "string"
},
"password_hash": {
"type": "string"
},
"pow_payload": {
"$ref": "#/components/schemas/PowProofRequest"
},
"username": {
"type": "string"
}
}
},
"UserRegisterResponse": {
"type": "object",
"required": [
"user_id",
"username"
],
"properties": {
"displayname": {
"type": [
"string",
"null"
]
},
"user_id": {
"type": "integer",
"format": "int64"
},
"username": {
"type": "string"
}
}
}
}
}
}