320 lines
11 KiB
YAML
320 lines
11 KiB
YAML
openapi: 3.0.3
|
||
info:
|
||
title: Veyra API
|
||
version: 0.2.0
|
||
description: 工程基础、开发身份和账户初始化;密码登录仅限 local/test。
|
||
servers:
|
||
- url: http://127.0.0.1:8080
|
||
paths:
|
||
/healthz:
|
||
get:
|
||
operationId: getLiveness
|
||
responses:
|
||
'200':
|
||
description: API 进程存活,与依赖是否就绪无关
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [status]
|
||
properties:
|
||
status: {type: string, enum: [alive]}
|
||
/readyz:
|
||
get:
|
||
operationId: getReadiness
|
||
responses:
|
||
'200': {$ref: '#/components/responses/Health'}
|
||
'503': {$ref: '#/components/responses/Health'}
|
||
/api/v1/system/health:
|
||
get:
|
||
operationId: getSystemHealth
|
||
responses:
|
||
'200': {$ref: '#/components/responses/Health'}
|
||
'503': {$ref: '#/components/responses/Health'}
|
||
/api/admin/v1/auth/login:
|
||
post:
|
||
operationId: adminLogin
|
||
description: 开发环境登录,要求同源 Origin;会话只在 HttpOnly Cookie 中返回。
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: {$ref: '#/components/schemas/LoginRequest'}
|
||
responses:
|
||
'200':
|
||
description: 已创建管理端会话
|
||
headers:
|
||
Set-Cookie: {schema: {type: string}, description: veyra_admin_session; HttpOnly; SameSite=Strict; Path=/api/admin}
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data: {$ref: '#/components/schemas/AdminLogin'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'403': {$ref: '#/components/responses/Error'}
|
||
'422': {$ref: '#/components/responses/Error'}
|
||
'429': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/v1/auth/login:
|
||
post:
|
||
operationId: developmentAppLogin
|
||
description: local/test 开发登录,返回 App 专用会话。正式短信登录与刷新流程待接入。
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: {$ref: '#/components/schemas/LoginRequest'}
|
||
responses:
|
||
'200':
|
||
description: 已创建 App 会话
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data: {$ref: '#/components/schemas/AppLogin'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'422': {$ref: '#/components/responses/Error'}
|
||
'429': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/admin/v1/me:
|
||
get:
|
||
operationId: getAdminIdentity
|
||
security: [{adminCookie: []}]
|
||
responses:
|
||
'200': {$ref: '#/components/responses/Identity'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/v1/me:
|
||
get:
|
||
operationId: getAppIdentity
|
||
security: [{appBearer: []}]
|
||
responses:
|
||
'200': {$ref: '#/components/responses/Identity'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/admin/v1/auth/logout:
|
||
post:
|
||
operationId: adminLogout
|
||
description: 同源 Origin 请求,撤销会话并清除管理端 Cookie。
|
||
security: [{adminCookie: []}]
|
||
responses:
|
||
'200': {$ref: '#/components/responses/Logout'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'403': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/v1/auth/logout:
|
||
post:
|
||
operationId: appLogout
|
||
security: [{appBearer: []}]
|
||
responses:
|
||
'200': {$ref: '#/components/responses/Logout'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/admin/v1/users:
|
||
get:
|
||
operationId: listAppUsers
|
||
description: 最近创建的 100 位 App 用户,不包含密码、登录名或后台权限。
|
||
security: [{adminCookie: []}]
|
||
responses:
|
||
'200':
|
||
description: App 用户列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data:
|
||
type: array
|
||
items: {$ref: '#/components/schemas/User'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/v1/accounts:
|
||
get:
|
||
operationId: listOwnAccounts
|
||
security: [{appBearer: []}]
|
||
responses:
|
||
'200':
|
||
description: 当前用户账户列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data:
|
||
type: array
|
||
items: {$ref: '#/components/schemas/AccountSummary'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
post:
|
||
operationId: createOwnAccount
|
||
description: simulation 要求 initial_cash,manual_real 必须省略;每种模式仅一个账户。
|
||
security: [{appBearer: []}]
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema: {$ref: '#/components/schemas/CreateAccount'}
|
||
responses:
|
||
'201': {$ref: '#/components/responses/AccountSummary'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'409': {$ref: '#/components/responses/Error'}
|
||
'422': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
/api/v1/accounts/{id}/summary:
|
||
get:
|
||
operationId: getOwnAccountSummary
|
||
security: [{appBearer: []}]
|
||
parameters:
|
||
- name: id
|
||
in: path
|
||
required: true
|
||
schema: {type: string, format: uuid}
|
||
responses:
|
||
'200': {$ref: '#/components/responses/AccountSummary'}
|
||
'401': {$ref: '#/components/responses/Error'}
|
||
'404': {$ref: '#/components/responses/Error'}
|
||
'503': {$ref: '#/components/responses/Error'}
|
||
components:
|
||
securitySchemes:
|
||
adminCookie: {type: apiKey, in: cookie, name: veyra_admin_session}
|
||
appBearer: {type: http, scheme: bearer}
|
||
responses:
|
||
Error:
|
||
description: 标准业务错误
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [error, meta]
|
||
properties:
|
||
error:
|
||
type: object
|
||
required: [code, message, retryable]
|
||
properties:
|
||
code: {type: string}
|
||
message: {type: string}
|
||
retryable: {type: boolean}
|
||
meta: {$ref: '#/components/schemas/Meta'}
|
||
Identity:
|
||
description: 当前身份
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data: {$ref: '#/components/schemas/User'}
|
||
Logout:
|
||
description: 会话已撤销
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data:
|
||
type: object
|
||
required: [revoked]
|
||
properties:
|
||
revoked: {type: boolean}
|
||
AccountSummary:
|
||
description: 账户与账本估算现金
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/Envelope'}
|
||
- properties:
|
||
data: {$ref: '#/components/schemas/AccountSummary'}
|
||
Health:
|
||
description: PostgreSQL 和 Redis 都正常时为 200,任一不可用或未配置时为 503
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/Health'
|
||
schemas:
|
||
Meta:
|
||
type: object
|
||
required: [request_id]
|
||
properties:
|
||
request_id: {type: string, format: uuid}
|
||
server_time: {type: string, format: date-time}
|
||
Envelope:
|
||
type: object
|
||
required: [data, meta]
|
||
properties:
|
||
data: {}
|
||
meta: {$ref: '#/components/schemas/Meta'}
|
||
User:
|
||
type: object
|
||
required: [id, display_name, status, created_at, updated_at]
|
||
properties:
|
||
id: {type: string, format: uuid}
|
||
display_name: {type: string}
|
||
status: {type: string, enum: [ACTIVE, DISABLED]}
|
||
created_at: {type: string, format: date-time}
|
||
updated_at: {type: string, format: date-time}
|
||
LoginRequest:
|
||
type: object
|
||
additionalProperties: false
|
||
required: [login_name, password]
|
||
properties:
|
||
login_name: {type: string, minLength: 3, maxLength: 64}
|
||
password: {type: string, minLength: 1, maxLength: 72, writeOnly: true}
|
||
AdminLogin:
|
||
type: object
|
||
required: [user, expires_at]
|
||
properties:
|
||
user: {$ref: '#/components/schemas/User'}
|
||
expires_at: {type: string, format: date-time}
|
||
AppLogin:
|
||
allOf:
|
||
- {$ref: '#/components/schemas/AdminLogin'}
|
||
- type: object
|
||
required: [access_token]
|
||
properties:
|
||
access_token: {type: string}
|
||
CreateAccount:
|
||
type: object
|
||
additionalProperties: false
|
||
required: [mode, name]
|
||
properties:
|
||
mode: {type: string, enum: [simulation, manual_real]}
|
||
name: {type: string, minLength: 1, maxLength: 80}
|
||
initial_cash: {type: string, description: CNY 十进制字符串,最多两位小数,范围 0 至 1000000000.00}
|
||
AccountSummary:
|
||
type: object
|
||
required: [id, user_id, mode, name, currency, ledger_status, created_at, cash_balance]
|
||
properties:
|
||
id: {type: string, format: uuid}
|
||
user_id: {type: string, format: uuid}
|
||
mode: {type: string, enum: [simulation, manual_real]}
|
||
name: {type: string}
|
||
currency: {type: string, enum: [CNY]}
|
||
ledger_status: {type: string, enum: [COMPLETE, INCOMPLETE]}
|
||
created_at: {type: string, format: date-time}
|
||
cash_balance: {type: string, nullable: true, description: CNY 十进制字符串,现金历史不完整时为 null}
|
||
Health:
|
||
type: object
|
||
required: [status, checked_at, components]
|
||
properties:
|
||
status: {type: string, enum: [ready, not_ready]}
|
||
checked_at: {type: string, format: date-time}
|
||
components:
|
||
type: object
|
||
required: [postgresql, redis]
|
||
properties:
|
||
postgresql: {$ref: '#/components/schemas/Component'}
|
||
redis: {$ref: '#/components/schemas/Component'}
|
||
Component:
|
||
type: object
|
||
required: [status]
|
||
properties:
|
||
status: {type: string, enum: [ready, unavailable, not_configured]}
|