diff --git a/design-docs/产品-02B-管理员控制台功能规格.md b/design-docs/产品-02B-管理员控制台功能规格.md index 561b1f25..58306727 100644 --- a/design-docs/产品-02B-管理员控制台功能规格.md +++ b/design-docs/产品-02B-管理员控制台功能规格.md @@ -473,7 +473,7 @@ | 权限 | 不展示或导出 New-API 系统凭据;不提供模型供应商路由配置;只能调用 New-API 已开放的用户、订阅、额度、余额和日志接口。 | | 产品接口 | 查询 New-API 网关用户、创建 New-API 网关用户、配置 New-API 订阅额度、查询 New-API 余额、查询 New-API 调用日志、归属 New-API 调用日志。 | | 埋点与审计 | 记录网关用户创建、订阅额度配置、余额查询、调用日志查询和用量归属操作。 | -| 验收要点 | 02B 不做外部网关数据复制队列;New-API 是被 Muse 后端直接调用的 LLM Gateway 管理接口;02B 只负责网关用户、余额查询和调用日志归属,作品级任务/生成用量由 `产品-02C` 展示,账户级余额、套餐、购买和总用量由 `产品-02G` 展示。 | +| 验收要点 | 02B 不做外部网关数据复制队列;New-API 是被 Muse 后端直接调用的 LLM Gateway 管理接口;02B 只负责网关用户、余额查询、调用日志归属,以及用于治理和对账的脱敏购买/用量摘要。作品级任务/生成用量由 `产品-02C` 展示,用户侧账户余额、套餐、购买和总用量完整体验由 `产品-02G` 展示。 | ### 3.20 任务治理与异常观察 @@ -1148,7 +1148,7 @@ New-API 的权威数据不在 Muse 本地同步。Muse 只保存完成业务归 8. 全局知识库授权能区分可见、可检索、可生成、可进入模型上下文。 9. 质量门控能配置、评估、观测线上效果,但不成为用户写作、保存、私人使用或市场发布的叙事质量硬门槛。 10. 市场审核和治理能处理审核、下架、召回、申诉和来源状态展示,并区分公共市场对象、用户已安装权益、作品绑定引用、来源快照、候选草稿和 Canonical。 -11. New-API 页面只通过 New-API 接口管理网关用户、订阅额度、余额查询和调用日志归属;不做外部网关数据复制队列,不管理模型供应商路由;作品级任务/生成用量由 `产品-02C` 承接,账户级权益、余额、套餐、购买和总用量展示由 `产品-02G` 承接。 +11. New-API 页面只通过 New-API 接口管理网关用户、订阅额度、余额查询、调用日志归属,以及用于治理和对账的脱敏购买/用量摘要;不做外部网关数据复制队列,不管理模型供应商路由;作品级任务/生成用量由 `产品-02C` 承接,用户侧账户权益、余额、套餐、购买和总用量完整体验由 `产品-02G` 承接。 12. 任务治理重试前必须重验授权、来源、市场状态、来源状态和幂等,不能复用失效旧上下文,不能由管理员重新生成用户写作候选。 13. 审计事件 append-only,审计查询和导出本身也必须被审计。 14. 页面、操作和产品接口在第 10 节覆盖表中闭合;新增页面或操作必须同步补接口。 diff --git a/docs/api-contracts/ai/openapi.yaml b/docs/api-contracts/ai/openapi.yaml index 4cbe803d..cd274b4b 100644 --- a/docs/api-contracts/ai/openapi.yaml +++ b/docs/api-contracts/ai/openapi.yaml @@ -1057,6 +1057,111 @@ paths: $ref: '../openapi-base.yaml#/components/responses/Unauthorized' '403': $ref: '../openapi-base.yaml#/components/responses/Forbidden' + /admin-api/muse/audit/api-logs: + get: + tags: [Admin Jobs & Events] + summary: 查询接口调用日志 + description: | + 查询系统接口调用的轻量脱敏日志,用于排障、风控和基础审计留痕。 + 响应不得包含请求体全文、响应体全文、token、secret、完整 header 或用户私有正文。 + operationId: adminListApiAccessLogs + security: + - adminBearerAuth: [] + parameters: + - $ref: '../openapi-base.yaml#/components/parameters/XApiVersion' + - $ref: '../openapi-base.yaml#/components/parameters/pageNo' + - $ref: '../openapi-base.yaml#/components/parameters/pageSize' + - name: requestId + in: query + schema: + type: string + description: 请求 ID 筛选 + - name: actor + in: query + schema: + type: string + description: 调用人摘要筛选 + - name: module + in: query + schema: + type: string + description: 业务模块筛选 + - name: status + in: query + schema: + type: string + enum: [success, failed, slow, sensitive, redacted] + description: 调用状态筛选 + - name: startTime + in: query + schema: + type: string + format: date-time + - name: endTime + in: query + schema: + type: string + format: date-time + responses: + '200': + description: 接口调用日志分页列表 + content: + application/json: + schema: + allOf: + - $ref: '../openapi-base.yaml#/components/schemas/CommonResult' + - type: object + properties: + data: + allOf: + - $ref: '../openapi-base.yaml#/components/schemas/PaginatedResult' + - type: object + properties: + list: + type: array + items: + $ref: '#/components/schemas/ApiAccessLogSummary' + '400': + $ref: '../openapi-base.yaml#/components/responses/BadRequest' + '401': + $ref: '../openapi-base.yaml#/components/responses/Unauthorized' + '403': + $ref: '../openapi-base.yaml#/components/responses/Forbidden' + /admin-api/muse/audit/api-logs/{logId}: + get: + tags: [Admin Jobs & Events] + summary: 查询接口调用日志详情 + description: | + 查询单条接口调用日志的脱敏详情。敏感详情查看本身必须写入业务审计事件。 + operationId: adminGetApiAccessLog + security: + - adminBearerAuth: [] + parameters: + - $ref: '../openapi-base.yaml#/components/parameters/XApiVersion' + - name: logId + in: path + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: 接口调用日志详情 + content: + application/json: + schema: + allOf: + - $ref: '../openapi-base.yaml#/components/schemas/CommonResult' + - type: object + properties: + data: + $ref: '#/components/schemas/ApiAccessLogDetail' + '400': + $ref: '../openapi-base.yaml#/components/responses/BadRequest' + '401': + $ref: '../openapi-base.yaml#/components/responses/Unauthorized' + '403': + $ref: '../openapi-base.yaml#/components/responses/Forbidden' /admin-api/muse/audit/business-events: get: tags: [Admin Jobs & Events] @@ -1102,17 +1207,52 @@ paths: type: array items: $ref: '#/components/schemas/BusinessAuditEventSummary' - - # ==================================================================== - # App AI 任务与候选(设计文档 4.5) - # ==================================================================== - '400': $ref: '../openapi-base.yaml#/components/responses/BadRequest' '401': $ref: '../openapi-base.yaml#/components/responses/Unauthorized' '403': $ref: '../openapi-base.yaml#/components/responses/Forbidden' + /admin-api/muse/audit/business-events/{eventId}: + get: + tags: [Admin Jobs & Events] + summary: 查询业务审计详情 + description: | + 查询高危操作、敏感读取、配置变更和治理动作的审计详情。 + before/after 快照必须为脱敏摘要,审计事件 append-only,不提供修改或删除接口。 + operationId: adminGetBusinessAuditEvent + security: + - adminBearerAuth: [] + parameters: + - $ref: '../openapi-base.yaml#/components/parameters/XApiVersion' + - name: eventId + in: path + required: true + schema: + type: integer + format: int64 + responses: + '200': + description: 业务审计详情 + content: + application/json: + schema: + allOf: + - $ref: '../openapi-base.yaml#/components/schemas/CommonResult' + - type: object + properties: + data: + $ref: '#/components/schemas/BusinessAuditEventDetail' + '400': + $ref: '../openapi-base.yaml#/components/responses/BadRequest' + '401': + $ref: '../openapi-base.yaml#/components/responses/Unauthorized' + '403': + $ref: '../openapi-base.yaml#/components/responses/Forbidden' + + # ==================================================================== + # App AI 任务与候选(设计文档 4.5) + # ==================================================================== /app-api/muse/ai/tasks: post: tags: [App AI] @@ -2352,6 +2492,76 @@ components: type: string format: date-time + ApiAccessLogSummary: + type: object + required: [logId, requestId, actor, method, pathSummary, status, statusCode, durationMs, createdAt] + properties: + logId: + type: integer + format: int64 + requestId: + type: string + description: 请求链路 ID + actor: + type: string + description: 调用人脱敏摘要 + actorType: + type: string + enum: [admin, system, user, anonymous] + module: + type: string + description: 业务模块 + method: + type: string + enum: [GET, POST, PUT, PATCH, DELETE] + pathSummary: + type: string + description: 脱敏路径摘要,不能包含敏感查询参数 + objectSummary: + type: string + description: 关联对象脱敏摘要 + clientIp: + type: string + description: 客户端 IP 脱敏摘要 + status: + type: string + enum: [success, failed, slow, sensitive, redacted] + statusCode: + type: integer + durationMs: + type: integer + description: 接口耗时毫秒数 + errorCode: + type: string + errorSummary: + type: string + createdAt: + type: string + format: date-time + + ApiAccessLogDetail: + allOf: + - $ref: '#/components/schemas/ApiAccessLogSummary' + - type: object + properties: + requestHeadersSummary: + type: object + description: 请求头脱敏摘要,不包含 token、secret、cookie 或完整 header + additionalProperties: + type: string + requestBodySummary: + type: object + description: 请求体脱敏摘要,不包含用户私有正文全文 + additionalProperties: true + responseBodySummary: + type: object + description: 响应体脱敏摘要,不包含用户私有正文全文 + additionalProperties: true + relatedAuditEventId: + type: integer + format: int64 + description: 查看敏感调用详情时写入的业务审计事件 ID + BusinessAuditEventSummary: type: object required: [eventId, eventType, operator, createdAt] @@ -2378,6 +2588,36 @@ components: type: string format: date-time + BusinessAuditEventDetail: + allOf: + - $ref: '#/components/schemas/BusinessAuditEventSummary' + - type: object + properties: + reason: + type: string + description: 操作理由 + result: + type: string + enum: [success, failed, rejected, pending_review] + description: 操作结果 + beforeSnapshot: + type: object + description: 变更前脱敏快照摘要 + additionalProperties: true + afterSnapshot: + type: object + description: 变更后脱敏快照摘要 + additionalProperties: true + impactSummary: + type: string + description: 影响范围摘要 + approvalSummary: + type: string + description: 审批或复核摘要 + immutable: + type: boolean + description: 审计事件是否 append-only + # ================================================================== # App AI Schemas # ================================================================== diff --git a/docs/api-contracts/generated/typescript/ai.ts b/docs/api-contracts/generated/typescript/ai.ts index a214ae31..4c7d9b79 100644 --- a/docs/api-contracts/generated/typescript/ai.ts +++ b/docs/api-contracts/generated/typescript/ai.ts @@ -328,6 +328,47 @@ export interface paths { patch?: never; trace?: never; }; + "/admin-api/muse/audit/api-logs": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询接口调用日志 + * @description 查询系统接口调用的轻量脱敏日志,用于排障、风控和基础审计留痕。 + * 响应不得包含请求体全文、响应体全文、token、secret、完整 header 或用户私有正文。 + */ + get: operations["adminListApiAccessLogs"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/admin-api/muse/audit/api-logs/{logId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询接口调用日志详情 + * @description 查询单条接口调用日志的脱敏详情。敏感详情查看本身必须写入业务审计事件。 + */ + get: operations["adminGetApiAccessLog"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/admin-api/muse/audit/business-events": { parameters: { query?: never; @@ -345,6 +386,27 @@ export interface paths { patch?: never; trace?: never; }; + "/admin-api/muse/audit/business-events/{eventId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 查询业务审计详情 + * @description 查询高危操作、敏感读取、配置变更和治理动作的审计详情。 + * before/after 快照必须为脱敏摘要,审计事件 append-only,不提供修改或删除接口。 + */ + get: operations["adminGetBusinessAuditEvent"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/app-api/muse/ai/tasks": { parameters: { query?: never; @@ -641,8 +703,8 @@ export interface components { updatedAt: string; }; AdminAgentSummary: { - /** Format: uuid */ - agentId: string; + /** Format: int64 */ + agentId: number; name: string; description?: string; /** @@ -659,10 +721,10 @@ export interface components { updatedAt: string; }; ToolGrantSummary: { - /** Format: uuid */ - grantId: string; - /** Format: uuid */ - agentId: string; + /** Format: int64 */ + grantId: number; + /** Format: int64 */ + agentId: number; agentName?: string; /** @description 工具类型 */ toolType: string; @@ -733,8 +795,8 @@ export interface components { dataPolicy: "no_user_content" | "redacted_user_content" | "approved_context_only"; }; AiTaskSummary: { - /** Format: uuid */ - taskId: string; + /** Format: int64 */ + taskId: number; /** * @description 任务类型 * @enum {string} @@ -745,15 +807,15 @@ export interface components { /** @description 任务所属用户 */ userId?: string; /** - * Format: uuid + * Format: int64 * @description 关联作品 ID */ - workId?: string; + workId?: number; /** - * Format: uuid + * Format: int64 * @description 使用的智能体 ID */ - agentId?: string; + agentId?: number; /** Format: date-time */ createdAt: string; /** Format: date-time */ @@ -772,8 +834,8 @@ export interface components { updatedAt: string; }; EvaluationRun: { - /** Format: uuid */ - runId: string; + /** Format: int64 */ + runId: number; policyKey: string; policyVersion?: number; datasetReference?: string; @@ -804,8 +866,8 @@ export interface components { errorMessage?: string; }; JobSummary: { - /** Format: uuid */ - jobId: string; + /** Format: int64 */ + jobId: number; /** @description 任务类型(如 knowledge_extraction, export, evaluation 等) */ type: string; /** @enum {string} */ @@ -822,8 +884,8 @@ export interface components { completedAt?: string; }; JobDetail: { - /** Format: uuid */ - jobId: string; + /** Format: int64 */ + jobId: number; type: string; /** @enum {string} */ status: "queued" | "running" | "completed" | "failed" | "cancelled"; @@ -854,15 +916,15 @@ export interface components { nextActions?: string[]; }; SourceEventSummary: { - /** Format: uuid */ - eventId: string; + /** Format: int64 */ + eventId: number; /** @description 来源对象类型 */ sourceType: string; /** - * Format: uuid + * Format: int64 * @description 来源对象 ID */ - sourceId: string; + sourceId: number; /** @enum {string} */ sourceStatus: "active" | "stale" | "revoked" | "recalled" | "delisted" | "blocked" | "owner_missing" | "unauthorized"; /** @enum {string} */ @@ -873,11 +935,11 @@ export interface components { createdAt: string; }; SourceEventDetail: { - /** Format: uuid */ - eventId: string; + /** Format: int64 */ + eventId: number; sourceType: string; - /** Format: uuid */ - sourceId: string; + /** Format: int64 */ + sourceId: number; /** @enum {string} */ sourceStatus: "active" | "stale" | "revoked" | "recalled" | "delisted" | "blocked" | "owner_missing" | "unauthorized"; /** @enum {string} */ @@ -894,17 +956,65 @@ export interface components { /** @description 传播状态 */ propagationStatus?: string; /** - * Format: uuid + * Format: int64 * @description 关联的传播任务 ID */ - jobId?: string; + jobId?: number; nextActions?: string[]; /** Format: date-time */ createdAt: string; }; + ApiAccessLogSummary: { + /** Format: int64 */ + logId: number; + /** @description 请求链路 ID */ + requestId: string; + /** @description 调用人脱敏摘要 */ + actor: string; + /** @enum {string} */ + actorType?: "admin" | "system" | "user" | "anonymous"; + /** @description 业务模块 */ + module?: string; + /** @enum {string} */ + method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE"; + /** @description 脱敏路径摘要,不能包含敏感查询参数 */ + pathSummary: string; + /** @description 关联对象脱敏摘要 */ + objectSummary?: string; + /** @description 客户端 IP 脱敏摘要 */ + clientIp?: string; + /** @enum {string} */ + status: "success" | "failed" | "slow" | "sensitive" | "redacted"; + statusCode: number; + /** @description 接口耗时毫秒数 */ + durationMs: number; + errorCode?: string; + errorSummary?: string; + /** Format: date-time */ + createdAt: string; + }; + ApiAccessLogDetail: components["schemas"]["ApiAccessLogSummary"] & { + /** @description 请求头脱敏摘要,不包含 token、secret、cookie 或完整 header */ + requestHeadersSummary?: { + [key: string]: string; + }; + /** @description 请求体脱敏摘要,不包含用户私有正文全文 */ + requestBodySummary?: { + [key: string]: unknown; + }; + /** @description 响应体脱敏摘要,不包含用户私有正文全文 */ + responseBodySummary?: { + [key: string]: unknown; + }; + /** + * Format: int64 + * @description 查看敏感调用详情时写入的业务审计事件 ID + */ + relatedAuditEventId?: number; + }; BusinessAuditEventSummary: { - /** Format: uuid */ - eventId: string; + /** Format: int64 */ + eventId: number; /** @description 审计事件类型 */ eventType: string; /** @description 操作者 */ @@ -918,6 +1028,29 @@ export interface components { /** Format: date-time */ createdAt: string; }; + BusinessAuditEventDetail: components["schemas"]["BusinessAuditEventSummary"] & { + /** @description 操作理由 */ + reason?: string; + /** + * @description 操作结果 + * @enum {string} + */ + result?: "success" | "failed" | "rejected" | "pending_review"; + /** @description 变更前脱敏快照摘要 */ + beforeSnapshot?: { + [key: string]: unknown; + }; + /** @description 变更后脱敏快照摘要 */ + afterSnapshot?: { + [key: string]: unknown; + }; + /** @description 影响范围摘要 */ + impactSummary?: string; + /** @description 审批或复核摘要 */ + approvalSummary?: string; + /** @description 审计事件是否 append-only */ + immutable?: boolean; + }; /** @description 用户本次希望 AI 编排完成的任务意图,不携带上下文事实。 */ AiTaskIntent: { /** @@ -942,20 +1075,20 @@ export interface components { */ refType: "work" | "chapter" | "block"; /** - * Format: uuid + * Format: int64 * @description 引用对象 ID;chapter/block 必须属于 workId 指向的作品。 */ - refId: string; + refId: number; /** @description 调用方看到的对象 revision,仅用于 stale 检测,不授予权限。 */ expectedRevision?: number; }; /** @description 可验证的智能体覆盖引用;服务端仍必须通过 Agent BC 和 Security facade 校验。 */ AgentOverrideRef: { /** - * Format: uuid + * Format: int64 * @description 覆盖使用的智能体 ID */ - agentId: string; + agentId: number; /** @description 覆盖使用的智能体版本 */ agentVersion: number; /** @description 覆盖默认槽位智能体的原因 */ @@ -970,20 +1103,20 @@ export interface components { commandId: string; intent: components["schemas"]["AiTaskIntent"]; /** - * Format: uuid + * Format: int64 * @description 目标作品 ID;服务端以此作为上下文和权限边界。 */ - workId?: string; + workId?: number; /** - * Format: uuid + * Format: int64 * @description 目标 Block 引用(正文生成/续写等场景必填);服务端校验其归属 workId。 */ - blockId?: string; + blockId?: number; /** - * Format: uuid + * Format: int64 * @description 目标章节引用;服务端校验其归属 workId。 */ - chapterId?: string; + chapterId?: number; /** @description 作品内智能体槽位 key,由 Agent BC 解析为具体 Agent 版本。 */ agentSlotKey?: string; agentOverrideRef?: components["schemas"]["AgentOverrideRef"]; @@ -997,26 +1130,26 @@ export interface components { contextScope: "none" | "work" | "chapter" | "block"; }; AiTaskDetail: { - /** Format: uuid */ - taskId: string; + /** Format: int64 */ + taskId: number; /** @enum {string} */ taskType: "generation" | "continuation" | "expansion" | "polish" | "detection" | "planning"; - /** Format: uuid */ - agentId: string; + /** Format: int64 */ + agentId: number; agentName?: string; - /** Format: uuid */ - workId?: string; - /** Format: uuid */ - blockId?: string; + /** Format: int64 */ + workId?: number; + /** Format: int64 */ + blockId?: number; /** @enum {string} */ status: "queued" | "running" | "streaming" | "completed" | "failed" | "cancelled"; /** - * Format: uuid + * Format: int64 * @description 任务完成后关联的候选 ID */ - suggestionId?: string; + suggestionId?: number; /** @description 来源版本 */ - sourceVersion?: number; + sourceRevision?: number; /** @description 服务端记录的来源快照 ID */ sourceSnapshotId?: string; /** @description 服务端生成的运行权限包 ID */ @@ -1032,24 +1165,24 @@ export interface components { completedAt?: string; }; SuggestionSummary: { - /** Format: uuid */ - suggestionId: string; + /** Format: int64 */ + suggestionId: number; /** - * Format: uuid + * Format: int64 * @description 关联的 AI 任务 ID */ - taskId?: string; - /** Format: uuid */ - blockId?: string; - /** Format: uuid */ - agentId?: string; + taskId?: number; + /** Format: int64 */ + blockId?: number; + /** Format: int64 */ + agentId?: number; agentName?: string; /** @enum {string} */ taskType: "generation" | "continuation" | "expansion" | "polish" | "detection" | "planning"; /** @enum {string} */ status: "pending" | "accepted" | "rejected"; /** @description 生成时的来源版本号 */ - sourceVersion?: number; + sourceRevision?: number; /** @description 变更摘要 */ diffSummary?: string; /** @description 质量门控是否通过 */ @@ -1058,14 +1191,14 @@ export interface components { createdAt: string; }; SuggestionDetail: { - /** Format: uuid */ - suggestionId: string; - /** Format: uuid */ - taskId: string; - /** Format: uuid */ - blockId?: string; - /** Format: uuid */ - agentId?: string; + /** Format: int64 */ + suggestionId: number; + /** Format: int64 */ + taskId: number; + /** Format: int64 */ + blockId?: number; + /** Format: int64 */ + agentId?: number; agentName?: string; /** @enum {string} */ taskType?: "generation" | "continuation" | "expansion" | "polish" | "detection" | "planning"; @@ -1076,7 +1209,7 @@ export interface components { /** @description 与当前 Block 正文的 diff 内容 */ diffContent?: string; /** @description 生成时的来源版本号 */ - sourceVersion: number; + sourceRevision: number; /** @description 服务端记录的来源快照 ID */ sourceSnapshotId?: string; /** @description 服务端记录的授权快照 ID;不接受客户端伪造为运行权限。 */ @@ -1095,8 +1228,8 @@ export interface components { createdAt: string; }; AgentSummary: { - /** Format: uuid */ - agentId: string; + /** Format: int64 */ + agentId: number; name: string; description?: string; /** @@ -1112,10 +1245,10 @@ export interface components { }; AgentTestRequest: { /** - * Format: uuid + * Format: int64 * @description 可选,关联作品上下文;不传时使用沙箱上下文 */ - workId?: string; + workId?: number; /** * @description 决定试用时可读取的上下文范围 * @default none @@ -1155,15 +1288,15 @@ export interface components { */ outputDestination: "preview_only" | "shadow_candidate"; /** - * Format: uuid + * Format: int64 * @description outputDestination=shadow_candidate 时关联的候选 ID */ - suggestionId?: string; + suggestionId?: number; /** - * Format: uuid + * Format: int64 * @description 若异步执行,返回任务 ID 供轮询 */ - jobId?: string; + jobId?: number; }; AgentSlotSummary: { /** @description 槽位标识 */ @@ -1175,10 +1308,10 @@ export interface components { /** @description 是否为保护节点(保护节点不可替换) */ protected: boolean; /** - * Format: uuid + * Format: int64 * @description 已绑定的智能体 ID */ - boundAgentId?: string; + boundAgentId?: number; /** @description 已绑定的智能体名称 */ boundAgentName?: string; /** @description 已绑定的智能体版本 */ @@ -1189,8 +1322,8 @@ export interface components { sourceStatus?: string; }; UserJobDetail: { - /** Format: uuid */ - jobId: string; + /** Format: int64 */ + jobId: number; type: string; /** @enum {string} */ status: "queued" | "running" | "completed" | "failed" | "cancelled"; @@ -1209,10 +1342,10 @@ export interface components { /** @description 来源对象类型 */ sourceType: string; /** - * Format: uuid + * Format: int64 * @description 来源对象 ID */ - sourceId: string; + sourceId: number; /** * @description 用途 * @enum {string} @@ -1224,12 +1357,12 @@ export interface components { */ targetOwner: "content" | "knowledge" | "ai" | "market" | "account"; /** - * Format: uuid + * Format: int64 * @description 目标对象 ID */ - targetId: string; + targetId: number; /** @description 调用方当前持有的来源版本 */ - sourceVersion?: number; + sourceRevision?: number; /** @description 调用方当前持有的授权快照 */ authorizationSnapshotId?: string; }; @@ -1267,10 +1400,79 @@ export interface components { /** @description 当前授权快照 ID */ currentAuthorizationSnapshotId?: string; /** - * Format: uuid + * Format: int64 * @description 可选,关联的异步任务 ID */ - jobId?: string; + jobId?: number; + }; + SSEChunkEvent: { + /** + * @description SSE 事件类型 + * @enum {string} + */ + event: "chunk"; + data: { + /** @description AI 生成的文本片段 */ + content: string; + /** @description 片段序号,从 1 递增 */ + sequenceNo: number; + }; + }; + SSEQualityCheckEvent: { + /** + * @description SSE 事件类型 + * @enum {string} + */ + event: "quality_check"; + data: { + /** @description 质量维度名称(如 fluency, coherence, safety) */ + dimension: string; + /** + * Format: double + * @description 质量评分(0-1) + */ + score: number; + /** @description 该维度是否通过阈值 */ + passed: boolean; + }; + }; + SSEDoneEvent: { + /** + * @description SSE 事件类型 + * @enum {string} + */ + event: "done"; + data: { + /** + * Format: int64 + * @description AI 任务 ID + */ + taskId: number; + /** + * Format: int64 + * @description 生成的候选 ID + */ + suggestionId: number; + /** @description 任务完成摘要 */ + summary?: string; + }; + }; + SSEErrorEvent: { + /** + * @description SSE 事件类型 + * @enum {string} + */ + event: "error"; + data: { + /** @description 错误码,格式 MUSE-AI-XXX-XXXX */ + code: string; + /** @description 人类可读的错误描述 */ + message: string; + /** @description 详细错误信息(仅开发环境返回) */ + detail?: string; + /** @description 是否可重试 */ + retryable?: boolean; + }; }; CommonResult: { /** @@ -1601,8 +1803,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - agentId?: string; + /** Format: int64 */ + agentId?: number; }; }; }; @@ -1624,7 +1826,7 @@ export interface operations { }; path: { /** @description 目标 Agent ID,必须为 system scope。 */ - agentId: string; + agentId: number; }; cookie?: never; }; @@ -1653,8 +1855,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - agentId?: string; + /** Format: int64 */ + agentId?: number; version?: number; }; }; @@ -1720,10 +1922,10 @@ export interface operations { content: { "application/json": { /** - * Format: uuid + * Format: int64 * @description 目标智能体 ID */ - agentId: string; + agentId: number; /** @description 工具类型(例如 web_search, file_read, api_call) */ toolType: string; scope: components["schemas"]["ToolGrantScope"]; @@ -1745,8 +1947,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - grantId?: string; + /** Format: int64 */ + grantId?: number; /** @enum {string} */ status?: "approved" | "revoked"; }; @@ -1937,10 +2139,10 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - runId?: string; - /** Format: uuid */ - jobId?: string; + /** Format: int64 */ + runId?: number; + /** Format: int64 */ + jobId?: number; }; }; }; @@ -1961,7 +2163,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - runId: string; + runId: number; }; cookie?: never; }; @@ -2035,7 +2237,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - jobId: string; + jobId: number; }; cookie?: never; }; @@ -2068,7 +2270,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - jobId: string; + jobId: number; }; cookie?: never; }; @@ -2089,8 +2291,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - jobId?: string; + /** Format: int64 */ + jobId?: number; /** @enum {string} */ status?: "queued" | "running"; }; @@ -2113,7 +2315,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - jobId: string; + jobId: number; }; cookie?: never; }; @@ -2136,8 +2338,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - jobId?: string; + /** Format: int64 */ + jobId?: number; /** @enum {string} */ status?: "cancelled"; }; @@ -2202,7 +2404,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - eventId: string; + eventId: number; }; cookie?: never; }; @@ -2235,7 +2437,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - eventId: string; + eventId: number; }; cookie?: never; }; @@ -2258,8 +2460,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - jobId?: string; + /** Format: int64 */ + jobId?: number; status?: string; }; }; @@ -2270,6 +2472,87 @@ export interface operations { 403: components["responses"]["Forbidden"]; }; }; + adminListApiAccessLogs: { + parameters: { + query?: { + /** @description 页码,从 1 开始 */ + pageNo?: components["parameters"]["pageNo"]; + /** @description 每页条数,上限 100 */ + pageSize?: components["parameters"]["pageSize"]; + /** @description 请求 ID 筛选 */ + requestId?: string; + /** @description 调用人摘要筛选 */ + actor?: string; + /** @description 业务模块筛选 */ + module?: string; + /** @description 调用状态筛选 */ + status?: "success" | "failed" | "slow" | "sensitive" | "redacted"; + startTime?: string; + endTime?: string; + }; + header: { + /** + * @description API 版本号,当前版本为 1。 + * 未传时网关可兼容最新稳定版本,但前端 SDK 和 API 客户端必须显式传递该 header。 + */ + "X-API-Version": components["parameters"]["XApiVersion"]; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 接口调用日志分页列表 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommonResult"] & { + data?: components["schemas"]["PaginatedResult"] & { + list?: components["schemas"]["ApiAccessLogSummary"][]; + }; + }; + }; + }; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 403: components["responses"]["Forbidden"]; + }; + }; + adminGetApiAccessLog: { + parameters: { + query?: never; + header: { + /** + * @description API 版本号,当前版本为 1。 + * 未传时网关可兼容最新稳定版本,但前端 SDK 和 API 客户端必须显式传递该 header。 + */ + "X-API-Version": components["parameters"]["XApiVersion"]; + }; + path: { + logId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 接口调用日志详情 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommonResult"] & { + data?: components["schemas"]["ApiAccessLogDetail"]; + }; + }; + }; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 403: components["responses"]["Forbidden"]; + }; + }; adminListBusinessAuditEvents: { parameters: { query?: { @@ -2312,6 +2595,39 @@ export interface operations { 403: components["responses"]["Forbidden"]; }; }; + adminGetBusinessAuditEvent: { + parameters: { + query?: never; + header: { + /** + * @description API 版本号,当前版本为 1。 + * 未传时网关可兼容最新稳定版本,但前端 SDK 和 API 客户端必须显式传递该 header。 + */ + "X-API-Version": components["parameters"]["XApiVersion"]; + }; + path: { + eventId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 业务审计详情 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json": components["schemas"]["CommonResult"] & { + data?: components["schemas"]["BusinessAuditEventDetail"]; + }; + }; + }; + 400: components["responses"]["BadRequest"]; + 401: components["responses"]["Unauthorized"]; + 403: components["responses"]["Forbidden"]; + }; + }; createAiTask: { parameters: { query?: never; @@ -2339,10 +2655,10 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - taskId?: string; - /** Format: uuid */ - jobId?: string; + /** Format: int64 */ + taskId?: number; + /** Format: int64 */ + jobId?: number; /** @description 轮询地址 */ pollUrl?: string; /** @description 服务端为本次任务创建或记录的来源快照 ID */ @@ -2369,7 +2685,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - taskId: string; + taskId: number; }; cookie?: never; }; @@ -2402,7 +2718,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - taskId: string; + taskId: number; }; cookie?: never; }; @@ -2414,7 +2730,7 @@ export interface operations { [name: string]: unknown; }; content: { - "text/event-stream": string; + "text/event-stream": components["schemas"]["SSEChunkEvent"] | components["schemas"]["SSEQualityCheckEvent"] | components["schemas"]["SSEDoneEvent"] | components["schemas"]["SSEErrorEvent"]; }; }; 400: components["responses"]["BadRequest"]; @@ -2428,7 +2744,7 @@ export interface operations { /** @description 按候选状态筛选 */ status?: "pending" | "accepted" | "rejected"; /** @description 按 Block 筛选 */ - blockId?: string; + blockId?: number; }; header: { /** @@ -2438,7 +2754,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - workId: string; + workId: number; }; cookie?: never; }; @@ -2471,7 +2787,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - suggestionId: string; + suggestionId: number; }; cookie?: never; }; @@ -2504,7 +2820,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - suggestionId: string; + suggestionId: number; }; cookie?: never; }; @@ -2609,8 +2925,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - agentId?: string; + /** Format: int64 */ + agentId?: number; }; }; }; @@ -2631,7 +2947,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - agentId: string; + agentId: number; }; cookie?: never; }; @@ -2658,8 +2974,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - agentId?: string; + /** Format: int64 */ + agentId?: number; version?: number; }; }; @@ -2681,7 +2997,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - agentId: string; + agentId: number; }; cookie?: never; }; @@ -2718,7 +3034,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - workId: string; + workId: number; }; cookie?: never; }; @@ -2751,7 +3067,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - workId: string; + workId: number; /** @description 槽位标识 */ slotKey: string; }; @@ -2763,10 +3079,10 @@ export interface operations { /** @description 幂等键 */ commandId: string; /** - * Format: uuid + * Format: int64 * @description 来源智能体 ID */ - sourceAgentId: string; + sourceAgentId: number; /** @description 来源智能体版本 */ sourceAgentVersion: number; /** @description 授权快照 ID */ @@ -2811,7 +3127,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - workId: string; + workId: number; /** @description 槽位标识 */ slotKey: string; }; @@ -2825,10 +3141,10 @@ export interface operations { /** @description 预检接口返回的绑定凭证,必须由 AI owner 原子消费 */ agentSlotPrecheckId: string; /** - * Format: uuid + * Format: int64 * @description 绑定来源智能体 ID */ - sourceAgentId: string; + sourceAgentId: number; /** @description 绑定来源智能体版本 */ sourceAgentVersion: number; /** @description 授权快照 ID */ @@ -2870,7 +3186,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - jobId: string; + jobId: number; }; cookie?: never; }; @@ -2903,7 +3219,7 @@ export interface operations { "X-API-Version": components["parameters"]["XApiVersion"]; }; path: { - jobId: string; + jobId: number; }; cookie?: never; }; @@ -2984,12 +3300,12 @@ export interface operations { /** @description 来源对象类型 */ sourceType: string; /** - * Format: uuid + * Format: int64 * @description 来源对象 ID */ - sourceId: string; + sourceId: number; /** @description 调用方当前持有的来源版本 */ - sourceVersion?: number; + sourceRevision?: number; /** * @description 用途 * @enum {string} @@ -3001,10 +3317,10 @@ export interface operations { */ targetOwner: "content" | "knowledge" | "ai" | "market" | "account"; /** - * Format: uuid + * Format: int64 * @description 目标对象 ID */ - targetId: string; + targetId: number; /** @description 调用方当前持有的授权快照 */ authorizationSnapshotId?: string; }; @@ -3019,8 +3335,8 @@ export interface operations { content: { "application/json": components["schemas"]["CommonResult"] & { data?: { - /** Format: uuid */ - jobId?: string; + /** Format: int64 */ + jobId?: number; pollUrl?: string; }; }; diff --git a/docs/superpowers/plans/2026-05-24-P3-muse-admin.md b/docs/superpowers/plans/2026-05-24-P3-muse-admin.md index 78382677..f7411dcc 100644 --- a/docs/superpowers/plans/2026-05-24-P3-muse-admin.md +++ b/docs/superpowers/plans/2026-05-24-P3-muse-admin.md @@ -2,7 +2,7 @@ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. -**目标:** 在 Vben Admin fork 基础上搭建 muse-admin,实现 MetaSchema 管理、系统治理、AI 配置、市场治理、全局知识管理 5 个功能域。 +**目标:** 在 Vben Admin fork 基础上搭建 muse-admin,实现 MetaSchema 管理、系统治理、AI 配置、市场治理、全局知识管理、Account/New-API、任务监控、日志审计功能域。 **架构:** Vue 3 + Vben Admin + TypeScript,Composition API + SFC script setup,defHttp API 集成,Vben 内置表格/表单组件复用。 @@ -10,6 +10,13 @@ 注: muse-admin 已 fork 完成,存在 `apps/web-antd` 和 `packages/` 结构。 +**合同校准(2026-05-24):** + +- 以 `design-docs/产品-02B-管理员控制台功能规格.md`、`docs/dev-baseline/muse-admin/CLAUDE.md` 和 `docs/api-contracts/**/openapi.yaml` 为实现依据;本文示例代码如与上述合同冲突,以上述合同为准。 +- Muse 业务页面目录使用 `apps/web-antd/src/views/muse/**`,不是根级 `src/views/{governance,ai,...}`。 +- Account/New-API 页面只实现治理和对账所需的脱敏摘要、配额调整、网关绑定、余额查询、调用日志归属;用户侧账户完整体验仍由 `产品-02G` 承接。 +- 日志审计必须包含接口调用日志和业务审计日志两个 surface;对应契约为 `/admin-api/muse/audit/api-logs`、`/admin-api/muse/audit/api-logs/{logId}`、`/admin-api/muse/audit/business-events`、`/admin-api/muse/audit/business-events/{eventId}`。 + --- ## Step 1: 工程调整 @@ -21,8 +28,8 @@ - [ ] **Step 1: 创建业务模块目录** ```bash -mkdir -p muse-admin/apps/web-antd/src/views/{governance,ai,knowledge,market,account,jobs,audit} -mkdir -p muse-admin/apps/web-antd/src/api/muse/{governance,ai,knowledge,market,account,jobs,audit} +mkdir -p muse-admin/apps/web-antd/src/views/muse/{governance,ai,knowledge,market,account,newapi,jobs,audit} +mkdir -p muse-admin/apps/web-antd/src/api/muse/{governance,ai,knowledge,market,account,newapi,jobs,audit} ``` - [ ] **Step 2: 检查现有结构** @@ -35,8 +42,8 @@ ls muse-admin/packages/@core/ - [ ] **Step 3: 提交** ```bash -git add muse-admin/apps/web-antd/src/views/governance/ muse-admin/apps/web-antd/src/api/muse/ -git commit -m "feat(struct): 建立管理端业务模块目录(governance/ai/knowledge/market/account)" +git add muse-admin/apps/web-antd/src/views/muse/ muse-admin/apps/web-antd/src/api/muse/ +git commit -m "feat(struct): 建立管理端业务模块目录" ``` ### Task 1.2: API 类型集成 @@ -239,7 +246,7 @@ git add -A && git commit -m "feat(governance): 实现 MetaSchema 列表页(Vbe | 用户权益列表 | `/account/entitlements` | 表格:用户 + 权益类型 + 上限 + 已用 + 过期时间 | | 配额调整表单 | `/account/quota-adjustments` | 弹窗:用户 + 资源类型 + 调整量 + 原因 + commandId | | New-API 绑定状态 | `/account/new-api-bindings` | 表格:用户 + 绑定状态 + 同步状态 | -| 购买/使用记录 | `/account/records` | 只读汇总表格 | +| 购买/使用记录 | `/account/records` | 只读脱敏治理摘要;不实现 `产品-02G` 的用户侧完整账户体验 | **API endpoints:** @@ -248,6 +255,8 @@ GET /admin-api/muse/account/users # 用户列表 GET /admin-api/muse/account/users/{userId}/entitlements # 用户权益 POST /admin-api/muse/account/users/{userId}/quota-adjustments # 配额调整 GET /admin-api/muse/account/new-api-bindings # New-API 绑定状态 +GET /admin-api/muse/account/usage-records # 脱敏用量摘要 +GET /admin-api/muse/account/purchase-records # 脱敏购买摘要 ``` **代码示例 — API service:** @@ -367,11 +376,16 @@ export function listSourceEvents(params: { pageNo: number; pageSize: number }) { |------|------|------| | 业务审计事件列表 | `/audit/business-events` | 表格:时间戳 + 操作者 + 操作 + 目标 + 结果 | | 审计详情 | `/audit/business-events/:eventId` | 完整 before/after 快照对比 | +| 接口调用日志 | `/audit/api-logs` | 表格:请求 ID + 调用人 + 路径摘要 + 状态码 + 耗时 | +| 接口调用详情 | `/audit/api-logs/:logId` | 只展示脱敏请求/响应摘要,不展示 token、secret、完整 header 或私有正文 | **API endpoints:** ``` +GET /admin-api/muse/audit/api-logs # 接口调用日志列表 +GET /admin-api/muse/audit/api-logs/{logId} # 接口调用日志详情 GET /admin-api/muse/audit/business-events # 业务审计事件列表 +GET /admin-api/muse/audit/business-events/{eventId} # 业务审计详情 ``` **代码示例 — API service:** @@ -419,4 +433,4 @@ export function getBusinessAuditDetail(eventId: string) { - [ ] 组件单元测试覆盖率 ≥70%(Vitest + Vue Test Utils) - [ ] E2E 测试覆盖核心管理流程(Playwright) - [ ] ESLint + Prettier + TypeScript 类型检查通过 -- [ ] Vite build 成功 \ No newline at end of file +- [ ] Vite build 成功