@@ -0,0 +1,319 @@
|
||||
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]}
|
||||
Reference in New Issue
Block a user