07f791d
ZhenYi
refactor: replace Preact with React imports for improved consistency across components
07f791d
{
"openapi": "3.1.0",
"info": {
"title": "auth",
"description": "认证与账号服务:工作量证明、口令与验证码登录、二次验证、注册、口令重置与 SSH 公钥。",
"license": {
"name": "MIT",
"identifier": "MIT"
},
"version": "1.0.0"
},
"paths": {
"/api/v1/auth/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/auth/login": {
"post": {
"tags": [
"auth"
],
"summary": "口令登录",
"description": "用口令登录。`identity` 可以是用户名、邮箱(大小写不敏感)或用户编号,`password_hash` 是客户端先算好的口令摘要,工作量证明的载荷必须是 `identity`。账号启用了多因子时返回 `mfa_required: true` 与 `challenge`,此时会话尚未绑定,需再调 `/api/v1/auth/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/auth/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/auth/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/auth/login/verify": {
"post": {
"tags": [
"auth"
],
"summary": "二次验证换会话",
"description": "用 6 位 TOTP 动态码或一枚未使用的恢复码完成二次验证并绑定会话。`challenge` 必须与 `/api/v1/auth/login` 或 `/api/v1/auth/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/auth/me": {
"get": {
"tags": [
"auth"
],
"summary": "当前登录用户",
"description": "通过会话 Cookie 返回用户自述信息。结果在服务端缓存 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"
}
}
}
},
"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/auth/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/auth/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/auth/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/auth/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/auth/session/logout": {
"post": {
"tags": [
"auth"
],
"summary": "登出",
"description": "销毁当前会话,并清掉该用户的 `/api/v1/auth/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/auth/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/auth/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/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"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"AddMemberBody": {
"type": "object",
"required": [
"user_id"
],
"properties": {
"role": {
"oneOf": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/OrgMemberRole"
}
]
},
"role_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"user_id": {
"type": "integer",
"format": "int64"
}
}
},
"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"
}
}
},
"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": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/OrganizationJoinPolicy"
}
]
},
"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_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_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": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/OrgMemberRole"
}
]
},
"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_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_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_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": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/OrgMemberRole"
}
]
},
"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"
}
}
},
"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": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/OrgMemberRole"
}
]
},
"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
}
}
}
},
"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
}
}
},
"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"
}
}
},
"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": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/MessageNotifications"
}
]
},
"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": [
{
"type": "null"
},
{
"$ref": "#/components/schemas/OrganizationJoinPolicy"
}
]
},
"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"
}
}
}
}
}
}