feat(api): add account workspaces and signed content events
This commit is contained in:
1 parent
937b774a93
commit
7b8d61d1ba
63 files changed
+5407
-370
No files matched your search
+455
-234
@@ -1,7 +1,7 @@
|
||||
openapi: 3.1.0
|
||||
info:
|
||||
title: WebDrop API
|
||||
version: 2.1.0
|
||||
version: 6.0.0
|
||||
servers:
|
||||
- url: /api/v1
|
||||
|
||||
@@ -15,6 +15,388 @@ tags:
|
||||
- name: account
|
||||
|
||||
paths:
|
||||
/accounts/profile:
|
||||
get:
|
||||
tags: [account]
|
||||
parameters:
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountProfile'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
patch:
|
||||
tags: [account]
|
||||
parameters:
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/AccountProfileRequest' }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountProfile'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/accounts/spaces:
|
||||
get:
|
||||
tags: [account]
|
||||
parameters:
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items: { $ref: '../contracts/api.schemas.json#/$defs/ChannelInfo' }
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/structure:
|
||||
get:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: false
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/Role'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/channels:
|
||||
post:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceChannelRequest' }
|
||||
responses:
|
||||
'201':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceChannelCreatedBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/channels/{channelId}:
|
||||
patch:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: channelId
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceNameRequest' }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/channels/{channelId}/group:
|
||||
put:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: channelId
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceGroupRequest' }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/groups:
|
||||
post:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceNameRequest' }
|
||||
responses:
|
||||
'201':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceGroupCreatedBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/groups/{groupId}:
|
||||
patch:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: groupId
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceNameRequest' }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/folders:
|
||||
post:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceFolderRequest' }
|
||||
responses:
|
||||
'201':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/folders/{folderId}:
|
||||
patch:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: folderId
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string, format: uuid }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceNameRequest' }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/spaces/{id}/locations:
|
||||
put:
|
||||
tags: [channel]
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- name: X-WD-Account
|
||||
in: header
|
||||
required: true
|
||||
schema: { type: string }
|
||||
- $ref: '#/components/parameters/RoleWriter'
|
||||
- $ref: '#/components/parameters/Endpoint'
|
||||
- name: Authorization
|
||||
in: header
|
||||
schema: { type: string }
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '../contracts/api.schemas.json#/$defs/WorkspaceMoveRequest' }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端权威数据
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/WorkspaceBody'
|
||||
'400': { $ref: '#/components/responses/Error' }
|
||||
'401': { $ref: '#/components/responses/Error' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/accounts/channels:
|
||||
get:
|
||||
tags: [account]
|
||||
@@ -244,7 +626,7 @@ paths:
|
||||
post:
|
||||
tags: [channel]
|
||||
security: [{ bearer: [], accountBearer: [] }]
|
||||
summary: 邀请已注册用户
|
||||
summary: 原子提交账号邀请及服务端授权计划要求的域密钥包
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
@@ -253,6 +635,26 @@ paths:
|
||||
responses:
|
||||
'204': { description: 已邀请 }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/channels/{id}/invitations/{username}/crypto-plan:
|
||||
get:
|
||||
tags: [channel]
|
||||
security: [{ bearer: [], accountBearer: [] }]
|
||||
summary: 获取新成员域密钥封装计划
|
||||
description: 返回由服务端历史策略和当前成员权限计算的 epoch 与收件人集合;提交时服务端会重新计算并校验。
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/ChannelId' }
|
||||
- { $ref: '#/components/parameters/RoleOwner' }
|
||||
- { name: username, in: path, required: true, schema: { type: string } }
|
||||
responses:
|
||||
'200':
|
||||
description: 服务端计算的加密授权计划
|
||||
content:
|
||||
application/json:
|
||||
schema: { $ref: '#/components/schemas/InvitationCryptoPlan' }
|
||||
'403': { $ref: '#/components/responses/Error' }
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
'409': { $ref: '#/components/responses/Error' }
|
||||
/channels/{id}/invitations/{username}:
|
||||
delete:
|
||||
tags: [channel]
|
||||
@@ -299,8 +701,8 @@ paths:
|
||||
- { $ref: '#/components/parameters/ChannelId' }
|
||||
get:
|
||||
tags: [channel]
|
||||
summary: 读取频道信息(不占席位)
|
||||
description: 任意角色可调用。用于加入前预览席位占用和核对模式。
|
||||
summary: 读取频道信息(不占成员名额)
|
||||
description: 任意角色可调用。`seats_used` 表示唯一账号成员数加匿名访客终端数,不是设备数。
|
||||
security: [{ bearer: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/Role' }
|
||||
@@ -355,11 +757,11 @@ paths:
|
||||
- { $ref: '#/components/parameters/ChannelId' }
|
||||
post:
|
||||
tags: [seat]
|
||||
summary: 加入频道(占用席位)
|
||||
summary: 登记当前设备并加入频道
|
||||
description: |
|
||||
幂等:同一终端重复调用返回同一席位,不重复占用。
|
||||
席位已满返回 403 `seats_full`。
|
||||
读取频道信息和 owner 管理接口不占席位;频道内容、席位信息/设备名等其余操作要求终端已入席,否则 403 `not_joined`。
|
||||
幂等:同一终端重复调用返回同一设备席位,不重复登记。
|
||||
同一账号的设备不限量,账号首次加入时才占一个成员名额;成员名额已满返回 403 `seats_full`。
|
||||
未登录访客每个终端单独计一个成员名额。读取频道信息和 owner 管理接口不占成员名额;频道内容、设备席位/设备名等操作要求终端已入席,否则 403 `not_joined`。
|
||||
security: [{ bearer: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/Role' }
|
||||
@@ -375,7 +777,7 @@ paths:
|
||||
'404': { $ref: '#/components/responses/Error' }
|
||||
get:
|
||||
tags: [seat]
|
||||
summary: 查看席位列表(所有者)
|
||||
summary: 查看已加入设备列表(所有者)
|
||||
description: 有效的 owner 凭据即可调用,不要求 owner 终端占用席位。
|
||||
security: [{ bearer: [] }]
|
||||
parameters:
|
||||
@@ -437,8 +839,8 @@ paths:
|
||||
/channels/{id}/seats/{endpointHash}:
|
||||
delete:
|
||||
tags: [seat]
|
||||
summary: 释放席位(所有者)
|
||||
description: 有效的 owner 凭据即可调用,不要求 owner 终端占用席位。被释放终端后续请求返回 `not_joined`;向订阅者推送 `{"t":"seats"}`。
|
||||
summary: 撤销单台设备(所有者)
|
||||
description: 有效的 owner 凭据即可调用,不要求 owner 终端占用设备席位。被释放终端后续请求返回 `not_joined`;账号成员身份及人数名额保留;向订阅者推送 `{"t":"seats"}`。
|
||||
security: [{ bearer: [] }]
|
||||
parameters:
|
||||
- { $ref: '#/components/parameters/ChannelId' }
|
||||
@@ -917,87 +1319,43 @@ components:
|
||||
|
||||
schemas:
|
||||
AccountChannel:
|
||||
type: object
|
||||
required: [channel_id, role, payload, created_at]
|
||||
properties:
|
||||
channel_id: { $ref: '#/components/schemas/Base64Url' }
|
||||
role: { type: string, enum: [owner, member] }
|
||||
payload: { type: string, minLength: 1, maxLength: 16384 }
|
||||
created_at: { type: integer, format: int64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountChannelBody'
|
||||
|
||||
AccountDevice:
|
||||
type: object
|
||||
required: [id, name, created_at, last_seen, current]
|
||||
properties:
|
||||
id: { type: string, format: uuid }
|
||||
name: { type: string, minLength: 1, maxLength: 80 }
|
||||
created_at: { type: integer, format: int64 }
|
||||
last_seen: { type: integer, format: int64 }
|
||||
current: { type: boolean }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountDeviceBody'
|
||||
|
||||
PublicKey:
|
||||
type: object
|
||||
required: [public_key]
|
||||
properties:
|
||||
public_key: { type: string, maxLength: 1024 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/PublicKeyBody'
|
||||
|
||||
ChannelInvitation:
|
||||
type: object
|
||||
required: [channel_id, username, payload, created_at]
|
||||
properties:
|
||||
channel_id: { $ref: '#/components/schemas/Base64Url' }
|
||||
username: { type: string }
|
||||
payload: { type: string, maxLength: 16384, description: 客户端加密的成员链接 }
|
||||
created_at: { type: integer, format: int64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/InvitationBody'
|
||||
|
||||
InvitationRequest:
|
||||
type: object
|
||||
required: [username, payload]
|
||||
properties:
|
||||
username: { type: string }
|
||||
payload: { type: string, maxLength: 16384 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/InvitationRequest'
|
||||
InvitationCryptoPlan:
|
||||
$ref: '../contracts/api.schemas.json#/$defs/InvitationCryptoPlan'
|
||||
|
||||
ChannelMember:
|
||||
type: object
|
||||
required: [username, role, joined_at]
|
||||
properties:
|
||||
username: { type: string }
|
||||
role: { type: string, enum: [owner, member] }
|
||||
joined_at: { type: integer, format: int64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/MemberBody'
|
||||
|
||||
AccountRegister:
|
||||
type: object
|
||||
required: [username, salt, verifier, vault, public_key]
|
||||
properties:
|
||||
username: { type: string, minLength: 3, maxLength: 32, pattern: '^[A-Za-z0-9_-]+$' }
|
||||
salt: { type: string, contentEncoding: base64, minLength: 24, maxLength: 24 }
|
||||
verifier: { type: string, contentEncoding: base64, minLength: 44, maxLength: 44 }
|
||||
vault: { type: string, contentEncoding: base64, maxLength: 1733336 }
|
||||
public_key: { type: string, maxLength: 1024, description: P-256 ECDH 公钥 JWK 的 JSON 字符串 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountRegisterRequest'
|
||||
|
||||
AccountSaltRequest:
|
||||
type: object
|
||||
required: [username]
|
||||
properties:
|
||||
username: { type: string, minLength: 3, maxLength: 32 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountSaltRequest'
|
||||
|
||||
AccountSalt:
|
||||
type: object
|
||||
required: [salt]
|
||||
properties:
|
||||
salt: { type: string, contentEncoding: base64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountSaltBody'
|
||||
|
||||
AccountSessionRequest:
|
||||
type: object
|
||||
required: [username, verifier]
|
||||
properties:
|
||||
device_id: { type: string, format: uuid }
|
||||
device_name: { type: string, minLength: 1, maxLength: 80 }
|
||||
username: { type: string }
|
||||
verifier: { type: string, contentEncoding: base64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountSessionRequest'
|
||||
|
||||
AccountSession:
|
||||
type: object
|
||||
required: [username, token]
|
||||
properties:
|
||||
username: { type: string }
|
||||
token: { type: string, contentEncoding: base64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountSessionBody'
|
||||
|
||||
AccountVault:
|
||||
type: object
|
||||
required: [revision, vault]
|
||||
properties:
|
||||
revision: { type: integer, format: int64, minimum: 0 }
|
||||
vault: { type: string, contentEncoding: base64, maxLength: 1733336 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AccountVaultBody'
|
||||
|
||||
Base64Url:
|
||||
type: string
|
||||
pattern: '^[A-Za-z0-9_-]+$'
|
||||
@@ -1043,186 +1401,49 @@ components:
|
||||
oldest_seq: { type: integer, format: int64, description: "清理水位 + 1;0 < from < oldest_seq 的续传需要从 0 全量同步" }
|
||||
|
||||
ServerInfo:
|
||||
type: object
|
||||
required: [protocol, contract_version, limits, captcha, transports]
|
||||
properties:
|
||||
protocol: { type: integer, const: 1 }
|
||||
contract_version: { type: string, example: 2.0.0, description: API 契约的 SemVer。破坏性变更递增主版本。 }
|
||||
captcha:
|
||||
type: object
|
||||
required: [provider, enabled]
|
||||
properties:
|
||||
provider: { type: string, enum: [none, cap] }
|
||||
enabled: { type: boolean }
|
||||
api_endpoint:
|
||||
type: string
|
||||
description: Cap widget 要连接的地址(data-cap-api-endpoint),仅在启用时出现
|
||||
transports:
|
||||
type: object
|
||||
properties:
|
||||
websocket: { type: boolean }
|
||||
sse: { type: boolean }
|
||||
http3: { type: boolean }
|
||||
limits:
|
||||
type: object
|
||||
properties:
|
||||
max_payload_bytes: { type: integer }
|
||||
max_frames_per_item: { type: integer }
|
||||
max_channel_bytes: { type: integer, format: int64 }
|
||||
max_seats: { type: integer }
|
||||
max_ttl_seconds: { type: integer }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ServerInfoBody'
|
||||
|
||||
ChannelMode:
|
||||
type: string
|
||||
enum: [enc, raw]
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ChannelMode'
|
||||
|
||||
DeletePolicy:
|
||||
type: string
|
||||
enum: [owner_only, own, anyone]
|
||||
$ref: '../contracts/api.schemas.json#/$defs/DeletePolicy'
|
||||
|
||||
ChannelSettings:
|
||||
type: object
|
||||
required: [seats, members_can_upload, delete_policy, ttl_seconds, max_items, file_max_downloads, ui_restrict_copy_download]
|
||||
properties:
|
||||
join_policy: { type: string, enum: [open, invite], default: open }
|
||||
allow_guests: { type: boolean, default: true }
|
||||
name: { type: string, maxLength: 48, description: "共享频道名,所有成员和服务端可见" }
|
||||
seats: { type: integer, minimum: 1, default: 2 }
|
||||
members_can_upload: { type: boolean, default: true }
|
||||
delete_policy: { $ref: '#/components/schemas/DeletePolicy' }
|
||||
ttl_seconds: { type: integer, minimum: 60, maximum: 604800, default: 86400 }
|
||||
max_items: { type: integer, minimum: 1, default: 1000 }
|
||||
file_max_downloads: { type: integer, minimum: 0, default: 10, description: "0 为不限,仅对 GATED 条目生效" }
|
||||
ui_restrict_copy_download: { type: boolean, default: false, description: "仅供前端展示,服务端不强制" }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ChannelSettings'
|
||||
|
||||
ChannelSettingsPatch:
|
||||
type: object
|
||||
description: ChannelSettings 的全部字段均可选
|
||||
properties:
|
||||
join_policy: { type: string, enum: [open, invite] }
|
||||
allow_guests: { type: boolean }
|
||||
join_password: { type: string, maxLength: 256, description: 至少 8 字符;空字符串清除;省略保持原值 }
|
||||
name: { type: string, maxLength: 48, description: "更新共享频道名;空字符串清除名称" }
|
||||
seats: { type: integer, minimum: 1 }
|
||||
members_can_upload: { type: boolean }
|
||||
delete_policy: { $ref: '#/components/schemas/DeletePolicy' }
|
||||
ttl_seconds: { type: integer, minimum: 60, maximum: 604800 }
|
||||
max_items: { type: integer, minimum: 1 }
|
||||
file_max_downloads: { type: integer, minimum: 0 }
|
||||
ui_restrict_copy_download: { type: boolean }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ChannelSettingsPatch'
|
||||
|
||||
CreateChannelRequest:
|
||||
type: object
|
||||
required: [id, mode, settings, owner_hash]
|
||||
properties:
|
||||
key_package: { type: string, minLength: 1, maxLength: 16384, description: 用创建者账号公钥封装的 owner 凭据 }
|
||||
join_password: { type: string, minLength: 8, maxLength: 256 }
|
||||
id: { $ref: '#/components/schemas/Base64Url' }
|
||||
mode: { $ref: '#/components/schemas/ChannelMode' }
|
||||
settings: { $ref: '#/components/schemas/ChannelSettings' }
|
||||
read_hash:
|
||||
$ref: '#/components/schemas/Base64Url'
|
||||
description: SHA-256(T_read),enc 模式必填,raw 模式省略
|
||||
write_hash:
|
||||
$ref: '#/components/schemas/Base64Url'
|
||||
description: SHA-256(T_write 或 W),仅在成员可上传时提供
|
||||
owner_hash:
|
||||
$ref: '#/components/schemas/Base64Url'
|
||||
description: SHA-256(T_owner)
|
||||
$ref: '../contracts/api.schemas.json#/$defs/CreateChannelRequest'
|
||||
|
||||
ShareSettings:
|
||||
type: object
|
||||
required: [ttl_seconds, max_visitors, file_max_downloads]
|
||||
properties:
|
||||
ttl_seconds: { type: integer, minimum: 60, maximum: 604800, default: 86400 }
|
||||
max_visitors: { type: integer, minimum: 0, maximum: 10000, default: 0, description: 0 为不限 }
|
||||
file_max_downloads: { type: integer, minimum: 0, default: 10, description: 0 为不限 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ShareSettings'
|
||||
|
||||
ShareSettingsPatch:
|
||||
type: object
|
||||
description: ShareSettings 的字段均可选。
|
||||
properties:
|
||||
ttl_seconds: { type: integer, minimum: 60, maximum: 604800 }
|
||||
max_visitors: { type: integer, minimum: 0, maximum: 10000 }
|
||||
file_max_downloads: { type: integer, minimum: 0 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ShareSettingsPatch'
|
||||
|
||||
CreateShareRequest:
|
||||
type: object
|
||||
required: [id, read_hash, owner_hash]
|
||||
properties:
|
||||
id: { $ref: '#/components/schemas/Base64Url' }
|
||||
read_hash: { $ref: '#/components/schemas/Base64Url', description: SHA-256(T_read) }
|
||||
owner_hash: { $ref: '#/components/schemas/Base64Url', description: SHA-256(T_owner) }
|
||||
settings: { $ref: '#/components/schemas/ShareSettings' }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/CreateShareRequest'
|
||||
|
||||
FinishShareRequest:
|
||||
type: object
|
||||
required: [manifest_item_id]
|
||||
properties:
|
||||
manifest_item_id: { $ref: '#/components/schemas/Base64Url' }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/FinishShareRequest'
|
||||
|
||||
ShareItemInfo:
|
||||
type: object
|
||||
required: [item_id, bytes, frames, max_downloads, downloads_left]
|
||||
properties:
|
||||
complete: { type: boolean }
|
||||
item_id: { $ref: '#/components/schemas/Base64Url' }
|
||||
bytes: { type: integer, format: int64 }
|
||||
frames: { type: integer }
|
||||
max_downloads: { type: integer, format: int64, description: 0 为不限 }
|
||||
downloads_left: { type: [integer, 'null'], format: int64, description: "null 表示不限" }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ShareItemInfo'
|
||||
|
||||
ShareInfo:
|
||||
type: object
|
||||
required: [id, state, expires_at, created_at, settings, items]
|
||||
properties:
|
||||
id: { $ref: '#/components/schemas/Base64Url' }
|
||||
state: { type: string, enum: [draft, sealed] }
|
||||
expires_at: { type: integer, format: int64 }
|
||||
created_at: { type: integer, format: int64 }
|
||||
sealed_at: { type: [integer, 'null'], format: int64 }
|
||||
manifest_item_id: { type: [string, 'null'], description: 清单条目 id }
|
||||
settings: { $ref: '#/components/schemas/ShareSettings' }
|
||||
items:
|
||||
type: array
|
||||
items: { $ref: '#/components/schemas/ShareItemInfo' }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ShareInfo'
|
||||
|
||||
ChannelInfo:
|
||||
type: object
|
||||
required: [id, mode, settings, seats_used, oldest_seq, last_seq, created_at, expires_at]
|
||||
properties:
|
||||
password_required: { type: boolean }
|
||||
creator_account: { type: string }
|
||||
id: { $ref: '#/components/schemas/Base64Url' }
|
||||
mode: { $ref: '#/components/schemas/ChannelMode' }
|
||||
settings: { $ref: '#/components/schemas/ChannelSettings' }
|
||||
seats_used: { type: integer }
|
||||
oldest_seq: { type: integer, format: int64 }
|
||||
last_seq: { type: integer, format: int64 }
|
||||
created_at: { type: integer, format: int64 }
|
||||
expires_at: { type: integer, format: int64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/ChannelInfo'
|
||||
|
||||
SeatJoined:
|
||||
type: object
|
||||
required: [endpoint_hash, joined_at, seats_used, seats_max]
|
||||
properties:
|
||||
endpoint_hash: { $ref: '#/components/schemas/Base64Url' }
|
||||
joined_at: { type: integer, format: int64 }
|
||||
seats_used: { type: integer }
|
||||
seats_max: { type: integer }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/SeatJoined'
|
||||
|
||||
Seat:
|
||||
type: object
|
||||
required: [endpoint_hash, joined_at]
|
||||
properties:
|
||||
endpoint_hash: { $ref: '#/components/schemas/Base64Url' }
|
||||
joined_at: { type: integer, format: int64 }
|
||||
label:
|
||||
type: [string, 'null']
|
||||
description: 加密的设备名(base64url),用 K_enc 解密;未设置为 null
|
||||
$ref: '../contracts/api.schemas.json#/$defs/SeatInfo'
|
||||
|
||||
AppendResult:
|
||||
type: object
|
||||
required: [seq]
|
||||
properties:
|
||||
seq: { type: integer, format: int64 }
|
||||
$ref: '../contracts/api.schemas.json#/$defs/AppendResult'
|
||||
Reference in new issue
Block a user