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]}