openapi: 3.1.0 info: title: photo-live version: 0.1.0 license: name: UNLICENSED identifier: UNLICENSED description: | photo-live 直播相册系统 API 契约(单一事实来源)。 - 类型经 `openapi-typescript` 生成并提交入库(`src/generated/openapi.d.ts`), 三端(services/api、apps/admin、apps/viewer)直接消费生成类型,不自行跑 gen。 - 错误响应使用稳定 `code`(见 `components.schemas.Error` 的枚举,与 `src/errors.ts` 的 `ErrorCodes` 一一对应),客户端按 code 映射多语言文案, `message` 仅供诊断。 - 列表接口统一游标分页,元信息见 `components.schemas.CursorPageMeta`。 servers: - url: /v1 tags: - name: auth description: 密码登录会话(签发、滑动续期、退出) paths: /auth/password: post: operationId: loginWithPassword tags: [auth] summary: 密码登录 description: 校验账号密码,签发会话令牌。 security: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LoginRequest' responses: '200': description: 登录成功,返回会话令牌与过期时间。 content: application/json: schema: $ref: '#/components/schemas/LoginResponse' '401': $ref: '#/components/responses/ErrorResponse' '500': $ref: '#/components/responses/ErrorResponse' /auth/refresh: post: operationId: refreshSession tags: [auth] summary: 会话滑动续期 description: 携带有效 Bearer 令牌滑动续期,返回新的过期时间。 security: - bearerAuth: [] responses: '200': description: 续期成功。 content: application/json: schema: $ref: '#/components/schemas/RefreshResponse' '401': $ref: '#/components/responses/ErrorResponse' '500': $ref: '#/components/responses/ErrorResponse' /auth/logout: post: operationId: logout tags: [auth] summary: 退出登录 description: 使当前 Bearer 令牌失效。 security: - bearerAuth: [] responses: '204': description: 已退出,无响应体。 '401': $ref: '#/components/responses/ErrorResponse' '500': $ref: '#/components/responses/ErrorResponse' components: securitySchemes: bearerAuth: type: http scheme: bearer responses: ErrorResponse: description: 错误响应(稳定 code;客户端按 code 映射文案,message 仅供诊断)。 content: application/json: schema: $ref: '#/components/schemas/Error' schemas: Error: type: object required: [code, message, requestId] properties: code: type: string readOnly: true description: 稳定错误码,与 src/errors.ts 的 ErrorCodes 一一对应。 enum: - AUTH_INVALID_CREDENTIALS - AUTH_TOKEN_EXPIRED - AUTH_FORBIDDEN - ALBUM_NOT_FOUND - ALBUM_NOT_PUBLIC - ALBUM_UPLOAD_DISABLED - MEMBER_CONFLICT - UPLOAD_SESSION_CONFLICT - UPLOAD_VERIFY_FAILED - PHOTO_NOT_FOUND - PHOTO_NOT_PUBLIC - VALIDATION_FAILED - INTERNAL_ERROR message: type: string readOnly: true description: 服务器生成的可读消息(诊断用,不作为客户端展示文案依据)。 requestId: type: string readOnly: true description: 请求追踪 ID。 CursorPageMeta: type: object required: [nextCursor, hasMore] description: 游标分页元信息;各列表响应以 allOf 内嵌本结构(条目 schema 在业务端点中定义)。 properties: nextCursor: type: [string, 'null'] readOnly: true description: 下一页游标;null 表示没有更多数据。 hasMore: type: boolean readOnly: true description: 是否还有下一页。 LoginRequest: type: object required: [account, password] properties: account: type: string description: 账号(用户名或邮箱)。 password: type: string description: 密码。 LoginResponse: type: object required: [sessionToken, expiresAt] properties: sessionToken: type: string readOnly: true description: 会话令牌(Bearer)。 expiresAt: type: string format: date-time readOnly: true description: 会话过期时间。 RefreshResponse: type: object required: [expiresAt] properties: expiresAt: type: string format: date-time readOnly: true description: 续期后的过期时间。