提交前后端架构阶段文档

This commit is contained in:
zizi 2026-05-23 23:55:00 +08:00
parent 4ba1257b7f
commit 8d7b47b468
10 changed files with 2434 additions and 2791 deletions

View File

@ -42,7 +42,7 @@
| 阶段 4 | `design-docs/流程-01A-管理员操作流程(操作视角).md` / `design-docs/流程-01B-普通用户操作流程(操作视角).md` / `design-docs/流程-02A-管理员系统处理流程(系统视角).md` / `design-docs/流程-02B-普通用户系统处理流程(系统视角).md` | 按角色拆分操作流程和系统处理流程 | 已完成并提交 |
| 阶段 5 | `design-docs/架构-01-系统全貌与边界上下文.md` / `design-docs/架构-02-核心数据结构与双轨模型.md` / `design-docs/架构-04-状态机与约束清单.md` | 承接产品与流程,调整有界上下文、核心模型、状态机和约束清单 | 已完成并提交 |
| 阶段 6 | `design-docs/专题-*` | 按需要调整 AI 编排、质量门控、竞品取舍、正文建议接受等专题合同 | 已完成并提交 |
| 阶段 7 | `design-docs/前端-*` / `design-docs/后端-*` | 承接产品、流程、架构结论,更新工程结构、Schema、API 和实现约束 | 准备开始 |
| 阶段 7 | `design-docs/前端-*` / `design-docs/后端-*` | 承接产品、流程、架构结论,更新工程结构、Schema、API 和实现约束 | review 修复完成,待复核确认 |
| 阶段 8 | `design-docs/00-文档大纲.md` / `design-docs/内容映射表.md` | 最后统一索引、文档 owner 和内容映射,清理过期引用 | 待开始 |
阶段 2 当前基线状态:
@ -100,6 +100,7 @@
| C-002 | 阶段 2.5~2.7 二轮复核 | `产品-02C` 局部冻结基线与 02F/02G 作品资产发布/使用需求 | 02F/02G 需要作品资产发布准备包和作品资产使用 owner,但当前不能跨阶段修改已冻结的 02C | 在 02F/02G 中标为后续阻断:02C 后续补齐 `work-publish-prep` 和作品资产使用预检前,作品资产不得提交发布、模板化、参考写入或进入 AI 上下文 | 待后续阶段承接 |
| C-003 | 阶段 3 review | `产品-03` 初稿与前序安全/资产边界 | 子代理 review 发现外部知识 lineage、保护节点不可开放、handoff 生命周期、知识库类型、市场授权/安装/绑定状态、管理员分权等边界需要补强 | 阶段 3 只修 `产品-03`,不反改 02 系列;将确认为流程/架构必须承接的不变式 | 已修复并确认 |
| C-004 | 阶段 4 review / 阶段 5 复核 | `产品-03` 与阶段 4 四分册 | 初次 review 认为 `产品-03` 中存在“已确认作品事实自动回滚”的旧口径残留;阶段 5 复核确认该短语位于“不能被解释为”列,不是旧口径 | 不需要跨阶段修改 `产品-03`;阶段 4 和阶段 5 均继续按“已确认事实不自动回滚,但受限来源不得继续进入新生成、新绑定、新导出许可范围或新的知识确认”处理 | 已复核,无需修改 |
| C-005 | 阶段 7 准备 | 旧 `前端-*` / `后端-*` 与当前 Muse 工程口径 | 旧前端文档把管理员后台和用户端都写成 Next.js 同一前端;旧后端文档按 `muse-*` 自研模块化单体描述,未承接 Yudao Cloud fork、Vben Admin 管理后台和独立 `muse-studio` 用户端的工程基线 | 阶段 7 已按新工程口径重写前后端架构:后端以 `yudao-cloud/` fork 为底座,管理后台走 `yudao-ui-admin-vben/apps/web-antd`,用户端单独自研 `muse-studio`;阶段 8 索引文档未修改 | 已承接,待确认 |
## 6. 决策记录
@ -146,6 +147,9 @@
| D-039 | 2026-05-23 | 阶段 6 review | 子代理严格 review 发现阶段 6 专题仍有 P0/P1 闭合缺口:Accept 对 revoked/recalled/blocked/owner_missing 等正文来源未硬阻断;市场作品资产 feature gate 和 `workAssetUsePrecheckId` 缺失;离线质量评估缺私有内容边界;接口样例过细、幂等不足、`contentOverride` 可能洗白来源;AI 编排和质量门控的候选状态、风险合并、New-API 脱敏、Source Status Event 传播和 Writing Health owner 需要统一 | 进入阶段 6 定点修复;仍只改 `专题-01/02/03/04` 和本计划,不修改产品、流程、架构、前端或后端文档 |
| D-040 | 2026-05-23 | 阶段 6 review 修复 | 按 review 结果修复专题文档:`专题-01` 收回到决策命令语义合同,补幂等、接受前置条件、作品资产预检、正文来源硬阻断、修改后合并 lineage 继承和失败矩阵;`专题-03` 补 Provisional Shadow Candidate、Tool Grant、Authorization Snapshot、检索结果合同、Candidate Decision Envelope、质量状态、New-API 脱敏和来源传播矩阵;`专题-04` 拆硬阻断/叙事关键/非关键维度,补决策优先级、离线评估私有内容边界、线上质量观测和下游承接;`专题-02` 去除旧实现态断言并改为目标取舍语言 | 阶段 6 review 修复完成,待复核确认;确认前不进入阶段 7 前端/后端文档 |
| D-041 | 2026-05-23 | 阶段 6 -> 7 | 用户要求提交阶段 6 并进入下个阶段;`专题-01/02/03/04` 和阶段计划纳入已确认基线,阶段 7 准备处理前端/后端文档 | 阶段 7 只能承接阶段 1~6 已确认的产品、流程、架构和专题结论;索引与内容映射仍属于阶段 8,不在阶段 7 顺手修改 |
| D-042 | 2026-05-23 | 阶段 7 工程基线 | 阶段 7 前后端工程口径调整为:后端使用 `YunaiV/yudao-cloud` fork,当前仓库 `yudao-cloud/` 后续可命名 `muse-cloud`;管理后台使用 `yudao-ui-admin-vben/apps/web-antd`,基于 Vue 3 + Vite + Ant Design Vue + TypeScript,接口走 `/admin-api/**`;用户端单独自研 `muse-studio`,建议 Next.js / React / TypeScript,接口走 `/app-api/**` | 阶段 7 重写 `前端-*` / `后端-*` 必须以此为工程基线;保留 `system/infra/ai/member/pay/bpm/report/mp` 等 Yudao 能力口径,已裁剪 `mall/crm/erp/mes/iot` 和空壳 `yudao-cloud/yudao-ui`;`mp` 明确保留 |
| D-043 | 2026-05-23 | 阶段 7 初稿 | 按 D-042 重写阶段 7 前后端文档:前端拆为 Vben Admin 管理后台和独立 `muse-studio` 用户端;后端拆为 Yudao 原生模块复用和 Muse `content/knowledge/ai/market/account` 业务模块;API 改为 `/admin-api/**` 与 `/app-api/**`;Schema 改为 Yudao fork 下的模块级业务 Schema,`后端-04a` 降级为旧 SQL 历史快照且禁止执行 | 阶段 7 初稿已覆盖 `前端-01/02/03`、`后端-01/02/03/04/04a/05` 和本计划;确认前不进入阶段 8,不修改 `00-文档大纲.md` 与 `内容映射表.md` |
| D-044 | 2026-05-23 | 阶段 7 review 修复 | 用户确认阶段 7 可拆分给 worker 并行修订;review 发现的 New-API owner、管理员私有内容边界、MetaSchema 投影兼容、planning owner API、用户知识库工作台依赖、Source/Authorization owner、保护节点注册表、handoff owner、Schema/API 缺口已按分册修复 | 阶段 7 review 修复已完成,待主代理复核和用户确认;阶段 8 索引与内容映射继续保持未修改,确认前不进入阶段 8 |
## 7. 阶段交付格式
@ -160,8 +164,8 @@
## 8. 当前下一步
当前进入阶段 7:`产品-01`、`产品-02`、`产品-02A~02G`、`产品-03`、四个流程分册、`架构-01/02/04` 和 `专题-01/02/03/04` 已纳入输入基线。旧流程文档已删除,`流程-01A/01B/02A/02B` 是唯一流程入口。
当前处于阶段 7 review 修复完成、待复核确认:`前端-01/02/03`、`后端-01/02/03/04/04a/05` 已按 D-042 工程基线形成初稿,并完成 review 发现的 P0/P1/P2 修复;确认前仍不能视为阶段 7 已收口。
阶段 7 只处理 `前端-*` / `后端-*` 文档,目标是承接前序产品、流程、架构和专题结论,更新工程结构、Schema、API、服务边界、前端信息架构和实现约束。阶段 8 的 `00-文档大纲.md` 与 `内容映射表.md` 仍作为最后统一索引阶段,不在阶段 7 顺手修改。
下一步是统一复核:Yudao 原生模块复用边界、`account` 与 `member` 的后续物理落地决策、Schema 与 API 的 owner 闭合、Vben Admin 与 `muse-studio` 的入口边界、MetaSchema 与 Source/Authorization 横切模型落点、以及 `后端-04a` 降级为历史 SQL 快照后是否需要在后续实现阶段重新生成模块 migration。
下一步先整理阶段 7 的目标文档清单、冲突点和重写方案,再决定按前端、后端或横切接口合同分册推进。
阶段 8 的 `00-文档大纲.md` 与 `内容映射表.md` 仍作为最后统一索引阶段,不在阶段 7 顺手修改。

View File

@ -1,138 +1,211 @@
# 前端-01:工程结构与核心依赖
- 版本:v4
- 更新日期:2026-05-13
- 目标读者:前端 / 架构 / 产品
- 阅读时间:20-35 分钟
- 边界说明:这里只讲前端信息架构、路由组织、目录边界和前端状态分层;本文件描述目标前端形态,不代表当前代码都已实现。编辑器交互看 `前端-02`,元引擎看 `前端-03`,精确接口看 `后端-05`。
- 版本:v5
- 更新日期:2026-05-23
- 目标读者:前端 / 架构 / 产品 / 后端
- 阅读时间:25-40 分钟
- 边界说明:本文件只定义阶段 7 的前端工程基线、管理后台与用户端拆分、路由组织、状态分层和接口边界。写作台交互看 `前端-02`,元引擎看 `前端-03`,精确 API 看 `后端-05`。
## 1. 技术栈与核心依赖
## 1. 前端工程基线
这里只列“类别与职责”,不在设计文档里维护依赖版本号。
Muse 前端拆为两个项目,不能再用一套 Next.js 应用同时承载管理后台和用户端。
### 1.1 核心框架
| 前端项目 | 定位 | 技术栈 | 接口前缀 |
|---|---|---|---|
| `yudao-ui-admin-vben/apps/web-antd` | 管理后台(Admin Console) | Vue 3 + Vite + Ant Design Vue + TypeScript | `/admin-api/**` |
| `muse-studio` | 用户端创作产品(User Workspace / Agent Workspace / Knowledge Workspace / Marketplace / Personal Center) | 建议 Next.js / React / TypeScript | `/app-api/**` |
- 应用框架:Next.js(前端框架) App Router / React(前端库) / TypeScript(类型脚本语言)
- 样式:Tailwind CSS(样式框架)
核心原则:
### 1.2 关键依赖(按职责)
1. 管理后台只服务管理员治理、配置、审核、观察和运营。
2. 用户端只服务普通用户创作、购买、安装、绑定、发布和个人中心。
3. 两个前端可以共享设计 token、类型生成和接口文档,但不能共享路由、权限模型或后台 layout。
4. 前端只做可见性、交互、状态恢复和用户反馈;权限、事实写入、幂等、审计和状态机必须由后端保证。
- 富文本编辑:Tiptap(富文本编辑器),基于 ProseMirror(富文本底层库),用于文本块(Block)级编辑、标注和候选合并。
- 服务器状态:TanStack Query(查询缓存库),用于缓存、变更请求(mutation)、重试和失效刷新。
- 客户端状态:Zustand(状态库),用于当前工作区 UI 状态、候选卡流选择态、编辑器局部状态和抽屉状态。
- 表单:React Hook Form(表单库),用于作品规划、管理员配置和动态字段输入。
- 校验:Zod(校验库),用于前端即时校验;最终权限、并发和跨字段事实校验仍由后端负责。
- 认证授权:前端只消费 Sa-Token 后端适配后的登录态、角色和权限摘要,不直接接触 Sa-Token 内部会话实现。
阶段 1~6 的硬约束在前端落点:
## 2. 前端信息架构
- 六个产品空间必须保持清楚:管理员控制台、用户工作区、智能体工作台、知识库工作台、市场、个人中心。
- 用户知识库是用户端一级空间,不能被写成作品工作台里的附属抽屉。
- 市场资产包括作品、智能体、知识库;购买、安装或绑定只改变授权和可用性,不自动写入作品事实。
- 输入输出合规、拆分切块、RAG 入库、语义安全围栏、静态检查、权限、审计、Shadow -> Canonical 等保护节点不可被用户替换。
- 前端必须展示或传递来源 lineage、授权快照和来源状态,但不能在本地伪造这些可信结果。
- 前端隐藏菜单、按钮或字段不是安全边界。
前端目标形态必须按角色边界拆成三个产品空间,不能把管理员页面和普通用户作品工作台混在同一组导航里。
## 2. 管理后台:Vben Admin
| 信息架构区域 | 使用角色 | 默认入口 | 前端负责什么 | 禁止混入什么 |
|---|---|---|---|---|
| 管理员控制台(Admin Console) | 管理员(Admin) | 管理后台首页 | 系统能力、元数据、智能体、指令模板、全局知识库、访问策略、用户、审计、质量评估的配置界面 | 单个作品正文写作、候选确认、作品知识取舍 |
| 用户工作区(User Workspace) | 普通用户(User) | 我的作品(My Works) | 我的作品、单作品作品工作台、写作台、作品规划台、知识与一致性、导入解析、导出交付、记录与用量 | 系统 Prompt、Agent、Pipeline、底层 MetaSchema 配置和管理员日志 |
| 个人中心(Personal Center) | 普通用户(User) | 个人资料或用量页 | 个人资料、偏好、令牌(Token)使用、配额、套餐和生成记录总览 | 单作品深层创作决策和管理员配置 |
普通用户登录后的默认入口是我的作品(My Works),不是作品工作台(Work Workspace)。用户只有打开某个作品后,才进入该作品的作品工作台;作品工作台默认落在写作台(Writing Desk)。
## 3. 路由与目录建议
路由建议按角色和产品空间组织。这里给出前端边界建议,不定义后端接口。
管理后台使用:
```text
app/
(auth)/
login/
(admin)/
admin/
page.tsx
metadata/
agents/
prompts/
global-knowledge/
users/
audit/
evaluation/
(user)/
works/
page.tsx
[workId]/
writing/
planning/
knowledge/
import/
export/
usage/
profile/
page.tsx
usage/
preferences/
yudao-ui-admin-vben/
apps/web-antd/
```
components/
admin/
workspace/
my-works/
当前保留模块:
| 模块 | 当前定位 |
|---|---|
| `system` | 用户、角色、菜单、权限等平台后台 |
| `infra` | 配置、文件、字典、任务、日志等基础后台 |
| `dashboard` | 后台首页 |
| `ai` | 代码保留,默认隐藏 |
| `member` | 代码保留,默认隐藏 |
| `pay` | 代码保留,默认隐藏 |
| `bpm` | 代码保留,默认隐藏 |
| `report` | 代码保留,默认隐藏 |
| `mp` | 代码保留,默认隐藏 |
已裁剪后台旧业务域:
- `mall`
- `crm`
- `erp`
- `iot`
- `mes`
- 对应页面、API、静态路由、store、工作台快捷入口
注意:`mp` 保留,不删。
### 2.1 后续管理后台能力
| 后台能力 | 页面方向 | 后端 owner |
|---|---|---|
| 内容管理 | 作品治理列表、章节异常摘要、版本治理摘要、导入导出记录、脱敏元信息、异常内容处理 | content |
| 知识管理 | 全局知识库治理、用户知识库治理摘要、知识来源状态、知识草稿治理摘要、检索配置 | knowledge / infra |
| AI 管理 | 模型网关绑定引用、可用模型摘要、任务调用归属摘要、Prompt、Agent、生成任务、候选、评测、质量门控、Tool Grant | ai |
| 市场管理 | 资产审核、发布申请、授权记录、申诉、治理结果、上下架 | market / bpm |
| 账户管理 | 用户资料、权益、配额、用量、购买/授权/发布记录 | account/member/pay |
| 运营配置 | 字典、配置、文件、任务、日志、菜单权限 | system / infra |
管理后台不得承载普通用户写作台、候选接受、作品知识取舍或市场购买后的使用流程。
内容管理和知识管理默认只展示治理摘要、异常摘要、脱敏元信息、任务状态、配置和审计记录;不得暗示管理员默认可查看用户私有正文全文、私有版本全文或用户知识库全文。确需查看私有内容时,必须由后续合规访问接口承接,并包含访问理由、时效、分权审批、最小范围和审计记录。
AI 管理只消费 New-API 在 Muse 侧允许展示的网关绑定引用、可用模型摘要和任务调用归属摘要。Provider 配置、路由策略、成本权威口径和原始调用日志仍归 New-API,Muse 管理后台不能把这些写成自身 owner。
### 2.2 管理后台路由、状态和权限
Vben Admin 的页面入口由后台菜单和权限点驱动。Muse 后续新增管理页面可以挂在 Vben 管理后台的菜单体系下,但只调用 `/admin-api/**`。
| 边界 | 管理后台要求 |
|---|---|
| 路由 | 使用 Vben 路由、菜单、面包屑和权限守卫;不复用 `muse-studio` 的 Next.js 路由 |
| 状态 | 使用 Vben 既有 API 请求、表格、表单、弹窗和菜单状态;不保存用户端作品编辑器状态 |
| 权限 | 使用 `system` 菜单、按钮、角色、数据范围和高危动作复核;后端仍必须校验业务 owner |
| API | 只访问 `/admin-api/**`;不从后台页面调用用户端 `/app-api/**` 完成用户创作决策 |
| 数据 | 默认展示治理摘要、异常摘要、脱敏元信息、配置、任务和审计;不默认读取用户私有正文全文、私有版本全文或用户知识库全文 |
## 3. 用户端:muse-studio
`muse-studio` 是普通用户使用的创作产品,不走 Vben。
建议技术栈:
- Next.js App Router / React / TypeScript
- Tiptap / ProseMirror:正文编辑、Block 级操作和候选合并
- TanStack Query:服务器状态、轮询、失效刷新
- Zustand 或等价轻量 store:工作台 UI 状态
- React Hook Form + Zod:用户端表单和即时校验
用户端承载:
| 产品空间 | 默认入口 | 主要能力 |
|---|---|---|
| 用户工作区 | 我的作品 | 作品列表、单作品工作台、写作、规划、知识、一致性、导入、导出、记录与用量 |
| 智能体工作台 | 智能体列表 | 用户智能体、已安装智能体、作品槽位替换、试用、发布准备 |
| 知识库工作台 | 我的知识库 | 资料管理、处理任务状态、知识库版本、发布准备、已安装知识库、作品绑定、安装管理 |
| 市场 | 市场首页 | 作品、智能体、知识库资产发现、购买、安装、绑定、发布 |
| 个人中心 | 个人资料或用量页 | 资料、偏好、权益、配额、用量、购买/授权/发布记录 |
用户端不得暴露系统 Prompt、底层 Pipeline、管理员审计日志、原始密钥、完整模型请求响应或后台配置表。
用户知识库工作台的前端依赖必须闭合到 `/app-api/**` 的资料、处理任务、版本、发布准备、安装和绑定状态接口。页面至少区分资料上传/引用、解析切块/RAG 入库任务状态、知识库版本与回滚可见状态、发布预检状态、市场安装状态、作品绑定状态和授权快照;前端只展示后端返回的任务与来源状态,不自行推断资料是否已可检索或可发布。
## 4. 用户端路由建议
```text
muse-studio/
app/
(auth)/
login/
(user)/
works/
page.tsx
[workId]/
writing/
planning/
knowledge/
agents/
import/
export/
records/
agents/
knowledge-bases/
marketplace/
profile/
components/
workspace/
writing-desk/
planning-desk/
knowledge/
import-parse/
export-delivery/
usage/
personal-center/
editor/
meta/
admin-config/
planning/
common/
lib/
api/
queries/
mutations/
store/
auth/
permissions/
types/
agents/
marketplace/
personal-center/
editor/
common/
lib/
api/
queries/
mutations/
store/
auth/
permissions/
types/
```
目录约束:
约束:
- `app/(admin)` 和 `components/admin` 只承载管理员控制台(Admin Console)界面;普通用户作品流程不能依赖管理员页面组件。
- `app/(auth)/login` 承载登录页;登录成功后按 `/auth/me` 返回的角色和默认入口跳转。
- `app/(user)/works/page.tsx` 只承载我的作品(My Works):列表、搜索、筛选、排序、新建、打开和继续写作入口。
- `app/(user)/works/[workId]/*` 才承载单个作品工作台(Work Workspace)深层流程,例如写作台、作品规划台、知识与一致性、导入解析、导出交付、记录与用量。
- `app/(user)/profile` 承载个人中心(Personal Center),不承载单作品编辑、规划或知识确认。
- `components/meta/admin-config` 可以显示 `MetaSchema`、`domain + scope + targetType` 等管理员语言;`components/meta/planning` 面向普通用户,只展示作品设定、章节大纲、世界设定、角色关系、文风检查等创作语言。
- 登录恢复和应用入口初始化调用 `/app-api/muse/me`,用于获取当前用户、权益摘要、默认入口和可见产品空间。
- `/works` 只承载我的作品列表和入口。
- `/works/[workId]/*` 才承载单作品深层创作流程。
- 智能体、知识库、市场、个人中心是用户端顶级空间,不塞进某个作品工作台内部。
- 作品工作台只展示当前作品关联的智能体、知识库和市场资产使用状态,不承载完整后台配置。
## 4. 前端状态分层
## 5. 状态分层
前端状态按来源和生命周期分层,避免把正式事实、待确认内容、历史记录和临时 UI 状态混进一个 store。
| 状态类型 | 管理后台 | 用户端 |
|---|---|---|
| 服务器事实 | Vben API store / table query | TanStack Query |
| 表单状态 | Ant Design Vue Form | React Hook Form / local form state |
| UI 临时态 | Vben route/menu/modal state | Zustand / component state |
| 权限可见性 | 后端菜单和权限点驱动 | `/app-api/muse/me` 权益摘要 + 业务接口结果 |
| 待确认内容 | 管理后台只查看、治理或异常处理 | 用户端决策:接受、修改后合并、丢弃、确认知识 |
| 状态类型 | 建议拥有者 | 内容示例 | 约束 |
|---|---|---|---|
| 服务器状态 | TanStack Query(查询缓存库) | 作品、章节、文本块、已确认设定、用户可见投影、生成历史、用量记录 | 只能通过接口刷新和变更;不能在本地伪造成正式事实 |
| 当前工作区 UI 状态 | Zustand(状态库) | 当前作品工作区、右侧面板打开状态、当前候选卡、冲突解决弹窗、生成历史抽屉 | 只影响界面,不成为事实源 |
| 编辑器局部状态 | 编辑器实例 + 局部 store | 当前文本块选择、光标、临时输入、标注高亮 | 写入正文必须经过修订号(revision)和后端确认 |
| 表单状态 | React Hook Form(表单库) | 管理员配置表单、普通用户作品规划表单、导出配置 | 提交前可即时校验;最终事实校验在后端 |
| 待确认内容视图状态 | Query + 局部 UI 状态 | AI 候选、待确认知识、解析章节待确认结果 | 用户界面使用创作语言;不能把 Shadow / Proposal / Canonical 做成普通用户默认导航 |
正式事实来自后端 Canonical,待确认内容来自 Shadow,历史来自 Archive。前端不能把本地缓存伪造成正式事实。
正式事实来自规范数据(Canonical),待确认内容来自待审层(Shadow),历史记录来自归档层(Archive)。这些底层概念可以在前端代码和调试视图中存在,但普通用户默认界面应显示为“AI 候选 / 待确认知识 / 已确认设定 / 历史记录”。
## 6. 接口边界
## 5. 权限与导航边界
- 管理后台只调用 `/admin-api/**`。
- 用户端只调用 `/app-api/**`。
- 用户端当前用户入口是 `GET /app-api/muse/me`,不使用 `/app-api/auth/me`。
- `system/infra` 的平台接口按 Yudao 约定保留。
- Muse 新业务接口由后端模块分别提供 admin/app controller。
- 前端类型可以由 OpenAPI 或等价接口契约生成,但接口 owner 是 `后端-05`。
- 前端禁止绕过接口直接访问数据库、对象存储私有地址、RAGFlow、New-API 或内部模型服务。
- 前端需要维护登录状态、刷新状态和当前用户摘要,但只把后端返回的角色/权限用于菜单展示、路由跳转和体验提示。
- 管理员控制台(Admin Console)必须由权限和路由守卫保护;普通用户不能通过 URL 直接进入管理员配置页。
- 用户工作区(User Workspace)中的作品路由必须校验当前用户对作品的访问权限。
- 普通用户在我的作品(My Works)点击“导入”或“导出”时,前端语义应跳转到某个作品的导入解析或导出交付流程,不在列表页展开完整深层操作。
- 管理员配置影响普通用户生成链路时,普通用户界面只展示可理解的能力变化、失败原因或不可用提示,不暴露系统配置对象本身。
- 前端隐藏按钮、菜单或页面入口不是安全边界;后端 Sa-Token 鉴权和 Muse 业务权限必须同时生效。
- 普通用户工作区与管理员控制台必须保持分离路由;不能用同一套后台 layout 切换权限来承载全部产品空间。
## 7. 权限与导航边界
## 6. 关联阅读
- Vben 管理后台的菜单、按钮和页面权限来自 `system` 菜单权限体系。
- `muse-studio` 的导航可见性来自用户权益、授权、作品权限和业务状态。
- 隐藏菜单不是安全边界;后端必须在 `/admin-api/**` 和 `/app-api/**` 同时做认证与业务权限校验。
- 管理员后台可以查看治理摘要、异常摘要、脱敏元信息和审计,不默认读取用户私有正文全文、私有版本全文或用户知识库全文。
- 用户端不允许通过 URL 进入管理后台配置。
- 用户端市场购买、安装、绑定成功后,只刷新授权、安装状态、可用动作和来源授权快照;不会把市场资产内容自动写入作品正文、Local KB 或规划正式事实。
- 产品边界:`产品-02-核心功能与交互边界.md`
- 普通用户操作流程:`流程-01B-普通用户操作流程(操作视角).md`
- 系统边界:`架构-01-系统全貌与边界上下文.md`
- 编辑器与作品写作台:`前端-02-编辑器与影子层交互.md`
- 元引擎与动态表单:`前端-03-元引擎与动态表单.md`
## 8. 关联阅读
- 产品定位:`产品-01-产品定位与核心价值.md`
- 功能总纲:`产品-02-核心功能与交互边界.md`
- 管理后台规格:`产品-02B-管理员控制台功能规格.md`
- 用户端规格:`产品-02C` 至 `产品-02G`
- 后端工程结构:`后端-02-工程结构与模块职责.md`
- API 契约:`后端-05-统一API契约-v1.md`

View File

@ -1,145 +1,166 @@
# 前端-02:编辑器与影子层交互
- 版本:v4
- 更新日期:2026-05-10
- 版本:v5
- 更新日期:2026-05-23
- 目标读者:前端 / 后端 / 架构 / 产品
- 阅读时间:25-40 分钟
- 边界说明:这里只讲作品写作台的前端状态拥有、交互结构、候选反馈和恢复策略;本文件描述目标前端形态,不代表当前代码都已实现。精确接口看 `后端-05`,精确状态机看 `架构-04`。
- 边界说明:本文件只定义 `muse-studio` 用户端的写作台、正文编辑、AI 候选、待确认知识和恢复策略。管理后台不承载写作台;精确 API 看 `后端-05`,状态机看 `架构-04`,Accept 语义看 `专题-01`。
## 1. 作品写作台概览
## 1. 所属前端
前端的任务不是只渲染正文编辑器和 Shadow Panel(待审面板),而是把作品写作台(Writing Desk)做成普通用户进入单个作品后的默认创作空间。
写作台属于独立用户端项目:
建议的写作台结构:
```text
muse-studio
-> /app-api/**
```
它不在 `yudao-ui-admin-vben` 中实现,不复用 Vben 管理后台 layout、菜单、表格工作台或权限页面。
写作台只调用 `/app-api/**`。当前用户、权益摘要、默认入口和可见产品空间来自 `/app-api/muse/me`;写作台不使用 `/app-api/auth/me`。
## 2. 写作台结构
写作台(Writing Desk)是用户打开某个作品后的默认入口。
| 区域 | 用户看到什么 | 前端职责 |
|---|---|---|
| 左侧 | 章节、章节摘要、情节节拍、作品设定锚点 | 帮用户理解当前章节位置,并提供到作品规划台(Planning Desk)的跳转 |
| 中间 | 当前章节正文编辑器 | 承载文本块(Block)级编辑、保存、修订号(revision)冲突处理和候选合并 |
| 右侧 | AI 候选、待确认知识、生成历史、任务反馈、参考来源摘要 | 承载候选卡流、待确认知识提醒、历史抽屉和失败反馈 |
| 下方或抽屉 | 已确认设定、作品知识、上下文命中、风险说明 | 展示解释信息和可跳转定位,不替用户自动确认 |
| 左侧 | 章节、章节摘要、章节目标、情节节拍、定位入口 | 帮用户理解当前章节位置,并跳转到规划、知识和历史 |
| 中间 | 当前章节正文编辑器 | 承载 Tiptap/ProseMirror 编辑、Block 保存、revision 冲突处理 |
| 右侧 | AI 候选、待确认知识、创作健康度、任务状态、参考来源摘要 | 承载候选卡流、知识提醒、质量解释和失败恢复 |
| 抽屉/面板 | 已确认设定、上下文命中、风险说明、历史记录 | 解释系统状态和可跳转定位,不替用户自动确认 |
普通用户默认看到的是“AI 候选 / 待确认知识 / 已确认设定 / 生成历史”,不直接看到待审层(Shadow)、提案(Proposal)、规范数据(Canonical)这些系统术语。系统术语可留在代码、调试视图或架构文档里。
普通用户默认看到“AI 候选 / 待确认知识 / 已确认设定 / 生成历史 / 创作健康度”,不直接看到 Shadow、Canonical、Archive、Pipeline、Prompt 等系统词。
## 2. 写作台与作品规划台互跳
## 3. Block 编辑
写作台(Writing Desk)和作品规划台(Planning Desk)是同一作品工作台(Work Workspace)里的两个工作区,前端必须提供清楚的互相跳转。
- 每个 Block 必须携带 `id`、`revision` 和结构化正文内容。
- 用户在编辑器里编辑的是正式正文草稿,保存成功后成为 Content Canonical。
- 写入正文必须经过 `/app-api/**` 的 expectedRevision 校验。
- 导入产生的 Block 和手动创建的 Block 使用同一编辑规则。
- 前端可以乐观更新,但服务端 revision 是唯一真相。
- 从写作台到作品规划台:用户可以从章节、情节节拍、角色设定、世界设定、文风检查或一致性问题跳转到对应规划入口。
- 从作品规划台回写作台:用户保存或确认规划后,可以回到相关章节、文本块或候选上下文继续写作。
- 跳转必须携带用户能理解的定位信息,例如章节、角色、设定项、风险问题或待确认知识;不要把 `schemaId`、`proposalId`、`pipeline` 作为普通用户默认可见线索。
- 作品规划台产生的 AI 方案仍然先进入待确认内容;用户确认后才能成为后续生成上下文的一部分。
冲突处理:
## 3. 文本块编辑与修订号保护
| 冲突 | 前端处理 |
|---|---|
| revision 不匹配 | 展示本地版本、服务端版本和可选恢复动作 |
| 本地继续编辑后服务端失败 | 禁止静默覆盖新输入,进入显式冲突态 |
| 来源或授权变化 | 拦截接受/确认动作,引导重验或重新生成 |
### 3.1 Block 级编辑
## 4. 待确认对象分组
- 每个文本块(Block)都必须携带 `id` 与修订号(revision),这是正文写入、候选合并和冲突恢复的锚点。
- 用户在写作台里编辑的是正式正文,不是待审草稿。
- 导入产生的文本块和手动创建的文本块在前端是一套规则,不允许出现“导入块走特殊编辑路径”。
### 3.2 标注与提示
- 命名实体识别(NER)预览、待确认知识、风险标记(Risk Markers)和参考来源摘要都属于解释能力。
- 这些提示不能伪装成正式事实;视觉上必须区分“待确认”和“已确认”。
- 已确认设定来自规范数据(Canonical)或用户可见投影;待确认知识来自待审层(Shadow)。
## 4. 状态拥有
### 4.1 Query Cache 与本地状态分工
- Query Cache 持有服务器事实与服务器列表:正文文本块、章节、已确认设定、用户可见投影、待确认内容列表、生成历史和用量记录。
- Zustand(状态库)或等价本地状态持有当前 UI 状态:当前候选卡、右侧面板、历史抽屉、冲突解决弹窗、乐观更新快照和跳转定位。
- 历史记录不属于当前待确认区;已接受、已丢弃、已过期或失败对象必须走独立查询和独立视图。
### 4.2 待确认对象的前端分组
前端至少要区分四类用户可见对象:
| 用户语言 | 底层来源 | 前端提交语义 |
| 用户语言 | 底层对象 | 用户动作 |
|---|---|---|
| AI 候选 | Suggestion / Shadow | 原样接受、修改后合并、丢弃当前建议 |
| 待确认知识 | Knowledge Draft / Proposal / Shadow | 确认、忽略、来源失效时重新提取 |
| 解析章节待确认结果 | Full Parse 章节聚合草稿 / Shadow | 整章确认、整章驳回、批量选择、一键确认全部可确认章节 |
| 生成历史 | Archive / Job History / Usage | 只读回看、定位来源、解释失败,不参与当前待确认提交 |
| AI 候选 | AI Suggestion / Shadow Candidate | 原样接受、修改后合并、丢弃、重生成 |
| 待确认知识 | Knowledge Draft | 确认、忽略、重验来源、重新提取 |
| 规划候选 | Planning Candidate | 接受为规划项、修改后保存、丢弃 |
| 解析章节结果 | Chapter Parse Result | 整章确认进入知识草稿处理、整章驳回 |
| 生成历史 | Archive / Job History | 只读回看、定位来源、解释失败 |
它们可以共用卡片视觉风格,但不能共用错误的提交语义。
这些对象可以共享卡片视觉,但不能共享提交语义。
## 5. 右侧候选卡流
待确认对象必须带来源 lineage、授权快照或来源状态摘要。前端只展示和传递后端返回的可信快照,不能自行判定来源仍然有效。
右侧候选卡流是写作台的关键交互面,不是后台审核列表。
规划候选的接受、修改后保存和丢弃必须走规划 owner 的 `/app-api/**` 决策接口,由后端写入或拒绝写入规划正式事实。前端不得复用 AI Suggestion 的 accept 接口,也不得把规划确认塞进动态表单的通用保存动作。
候选卡应至少表达:
## 5. AI 候选卡
- 候选文本或候选方案。
- 关联待确认知识。
- 风险标记(Risk Markers)。
- 来源快照(Source Snapshot)状态。
- 本次参考了哪些作品知识、规划项或授权全局资料的摘要。
- 可执行动作:原样接受、修改后合并、丢弃当前建议。
候选卡至少展示:
交互约束:
- 候选正文或候选方案。
- 关联智能体和来源摘要。
- 创作健康度和质量维度摘要。
- 风险标记。
- 使用和排除的来源。
- Candidate Decision Envelope 结果。
- 可用动作。
- 未接受的 AI 候选不能进入正文、已确认设定、正式检索或下一次生成事实。
- 原样接受时,前端可以展示“已合并,关联知识草稿已确认”,前提是后端返回的结果确实表示关联草稿已确认。
- 修改后合并时,前端必须清掉旧待确认知识并提示“已合并,旧知识草稿已失效,正在重新提取”。
- 丢弃当前建议只结束当前建议和关联草稿的待审生命周期,不改正文、不改已确认设定。
动作约束:
## 6. 同步与恢复策略
| 动作 | 允许写入 | 必须保持 |
|---|---|---|
| `accept_as_is` | 目标 Block 新 revision、候选归档 | 关联 Knowledge Draft 仍待确认;不写 Local KB;不自动确认规划正式事实 |
| `merge_after_edit` | 用户修改后的最终正文、候选归档 | 旧 Knowledge Draft 失效并退出当前待确认区;提交后重新提取新的 Knowledge Draft |
| `discard` | 候选归档为丢弃 | 不改正文;不改 Local KB;不改规划正式事实 |
### 6.1 乐观更新
接受候选的前端语义必须收敛为“正文决策”,不是“知识确认”。如果候选来自用户知识库、市场知识库、市场作品资产或已安装智能体,前端必须展示对应来源和授权快照;购买、安装或绑定资产成功本身不写作品正文、不写 Local KB、不写规划正式事实。
- 对正文接受可以做乐观更新,但必须以修订号(revision)为锚点。
- 失败后要么回滚到上一个稳定状态,要么进入显式冲突态;不能静默吞错。
- 如果用户在乐观更新后继续编辑了当前文本块,失败恢复时禁止直接覆盖新输入。
来源撤权、召回、下架、blocked、owner_missing 或授权快照失效时,前端只能禁用接受、提示重验或重新生成。前端不能自动确认知识,也不能自动回滚已经存在的正式正文或正式知识。
### 6.2 冲突处理
禁止文案:
前端需要明确区分两类冲突:
- “已合并,关联知识草稿已确认”
- “已合并,草稿已经进入正式知识”
- “来源已撤权,已自动回滚正式事实”
- “安装成功,已写入作品设定”
- 内容冲突:修订号(revision)不匹配,用户要看见“我的版本”和“服务器版本”的差异,并选择保留、合并或重试。
- 知识冲突:风险标记、来源失效或属性冲突,用户在待确认知识层处理,而不是当成正文冲突。
允许文案:
### 6.3 来源快照拦截
- “已合并,关联知识草稿仍待确认”
- “已合并,旧知识草稿已失效,正在重新提取”
- “引用来源已被召回,当前候选不能继续接受”
- “安装成功,可在作品中选择使用”
- 待确认知识必须带来源快照(Source Snapshot)或等价来源校验结果。
- 来源已失效时,前端必须拦截确认动作,并用用户语言说明“这条待确认内容已经和当前来源不匹配,需要重新提取”。
- 拦截后不能让用户绕过校验强行写入已确认设定。
## 6. 创作健康度展示
### 6.4 修改后合并
创作健康度是候选解释,不是作品排名。
修改后合并的前端语义是:
展示内容:
1. 用户先编辑最终要进入正文的内容。
2. 正文按修订号(revision)合并。
3. 旧待确认知识立即失效并从当前待确认区移除。
4. 系统重新提取新的待确认知识。
5. 用户稍后再确认或忽略新的待确认知识。
- 总体状态:可用、已重写后可用、高风险、已阻断、需重验。
- 关键风险:设定冲突、角色失声、来源撤权、合规阻断。
- 维度摘要:设定一致性、角色声音、场景结构、文风、节奏。
- 来源摘要:用了哪些正文、Local KB、授权知识;哪些来源被排除。
- 下一步动作:接受、修改后合并、丢弃、重生成、重验来源。
这条链路不能被简化成“接受后继续沿用旧知识草稿”。
前端不能绕过 blocked / invalidated / needs_recheck 接受候选。
## 7. 导入与全书解析 UI
用户可以选择开放槽位中的智能体或知识库,但不能替换输入输出合规、拆分切块、RAG 入库、语义安全围栏、静态检查、质量门控、权限、审计和 Shadow -> Canonical 等保护节点。写作台只展示可选项和不可用原因,不暴露底层 Pipeline 控制权。
- “开始解析”入口由导入状态和解析状态驱动,但前端不在本文件定义状态机细节。
- 解析进行中,前端要展示章节级进度与失败反馈,而不是只有一个全局加载态。
- 章节汇总页是主工作台;详情页是解释面板。
- 详情页不提供逐条接受;全书解析场景的提交动作只能在章节边界完成。
- 批量选择和“一键确认全部可确认章节”只是操作效率优化;前端文案必须避免暗示系统会做跨章节不可解释写入。
## 7. 同步与恢复
## 8. 用户可见反馈规范
服务器状态建议由 TanStack Query 管理:
- 待确认对象必须显式标识“待确认”。
- 已确认设定必须和待确认知识分区展示。
- 历史记录必须在独立区域展示,不和当前待确认内容混放。
- 成功提示要说真话:
- 原样接受:`已合并,关联知识草稿已确认`
- 修改后合并:`已合并,旧知识草稿已失效,正在重新提取`
- 不要伪造“已发现 N 条提案待审核”这类没有一致性保证的即时数字。
- Work / Chapter / Block。
- Active Suggestions。
- Knowledge Drafts。
- Candidate Quality Result。
- Job Status。
- Archive / History。
- Usage Summary。
## 9. 关联阅读
本地 UI 状态建议由 Zustand 或局部状态管理:
- 产品边界:`产品-02-核心功能与交互边界.md`
- 当前候选卡。
- 右侧面板 tab。
- 冲突弹窗。
- 乐观更新快照。
- 跳转定位。
恢复策略:
1. 成功后按服务端返回的 revision 和状态刷新。
2. 可重试失败保留用户输入和上下文。
3. 不可重试失败禁用动作并解释原因。
4. 任务型操作进入轮询或通知,不阻塞正文已成功保存的主事务。
## 8. 导入解析 UI
- 导入入口属于作品工作台,不属于作品列表深层弹窗。
- 导入正文可初始化章节和 Block。
- 全书解析必须展示章节级进度、失败原因和章节审阅入口。
- 章节审阅确认只推进到 Knowledge Draft 处理,不直接写 Local KB。
- 详情页负责解释,不提供逐条绕过章节边界的确认。
## 9. 与管理后台关系
管理后台可以查看内容异常、导入导出记录、任务失败和治理摘要,但不承载普通用户写作台。管理员不能通过后台替用户接受 AI 候选、保存正文或确认作品知识。
## 10. 关联阅读
- 用户工作区规格:`产品-02C-用户工作区与作品工作台功能规格.md`
- 普通用户操作流程:`流程-01B-普通用户操作流程(操作视角).md`
- 普通用户系统处理流程:`流程-02B-普通用户系统处理流程(系统视角).md`
- 状态机与约束:`架构-04-状态机与约束清单.md`
- Accept 收束专题:`专题-01-正文建议接受(Accept Suggestion)实现规范.md`
- 普通用户系统流程:`流程-02B-普通用户系统处理流程(系统视角).md`
- Accept 专题:`专题-01-正文建议接受(Accept Suggestion)实现规范.md`
- 质量门控专题:`专题-04-生成质量门控与创作健康度设计方案`

View File

@ -1,150 +1,206 @@
# 前端-03:元引擎与动态表单
- 版本:v4
- 更新日期:2026-05-10
- 目标读者:前端 / 架构 / 产品
- 版本:v5
- 更新日期:2026-05-23
- 目标读者:前端 / 架构 / 产品 / 后端
- 阅读时间:25-45 分钟
- 边界说明:这里只讲元引擎(Meta Engine)在前端的渲染、可见性和交互分层;本文件描述目标前端形态,不代表当前代码都已实现。元结构定义(MetaSchema)概念引用 `架构-02`,精确表结构引用 `后端-04`,精确接口引用 `后端-05`。
- 边界说明:本文件定义 MetaSchema 在两个前端中的使用方式:Vben 管理后台配置元结构,`muse-studio` 用户端消费可见投影并渲染创作表单。元结构定义看 `架构-02`,Schema 看 `后端-04`,API 看 `后端-05`。
## 1. 为什么需要元引擎
## 1. 核心定位
元引擎(Meta Engine)的目的不是“炫技动态表单”,而是把系统配置、普通用户可见内容和后续生成上下文的边界翻译成稳定 UI。
元引擎不是一个单独产品空间,而是把管理员配置、用户可见内容、AI 上下文和导出边界翻译成稳定 UI 的机制。
它要同时服务两类界面:
它服务两类前端:
- 管理员配置界面:管理员(Admin)配置 MetaSchema、字段、可见性、是否进入 AI 上下文和校验规则。
- 普通用户规划界面:普通用户(User)填写作品设定、章节大纲、世界设定、角色关系和文风检查等创作内容。
这两类界面可以复用渲染能力,但不能复用同一套用户语言。管理员可以看到系统术语,普通用户默认只看到创作语言。
## 2. 管理员配置 MetaSchema
管理员控制台(Admin Console)可以显示系统结构和配置项,包括元结构定义(MetaSchema)、领域(domain)、范围(scope)、目标类型(targetType)和字段控制项。
管理员侧输入至少需要表达:
- MetaSchema 的 `domain + scope + targetType` 三维分类。
- 字段类型、必填、枚举、引用、排序和校验规则。
- 用户可见性(uiVisible)、是否进入 AI 上下文(aiContext)、用户是否可编辑(userEditable)、用户是否可检索(userSearchable)、是否可导出(exportable)等控制语义。
- 配置版本、启停、回滚或变更记录的展示入口。
前端约束:
- 前端只消费后端已经解析好的目标 MetaSchema,不在前端自行推断 `domain`、`scope` 或 `targetType`。
- 管理员配置界面可以出现 `MetaSchema`、`domain + scope + targetType` 等系统词。
- 管理员配置界面不替普通用户填写某个作品的正文、设定或知识确认结果。
- 具体字段名、表结构和接口参数不在本文件定义。
## 3. 普通用户填写作品规划
普通用户侧的动态表单不是“Schema 表单”,而是作品规划台(Planning Desk)的一部分。前端需要把底层元数据翻译成创作语言。
普通用户默认入口建议收敛为:
| 普通用户入口 | 承载内容 | AI 辅助方式 |
| 前端 | 使用者 | 目标 |
|---|---|---|
| 作品设定 | 题材、类型、主题、读者承诺、基调、禁区、结局方向 | 生成故事前提、补全设定、整理梗概、检查偏题、给多版方向 |
| 章节大纲 | 章节顺序、章节摘要、近期目标、主线、支线、伏笔、情节节拍 | 生成章节摘要、补齐大纲、整理进度、检查章节目标、建议推进动作 |
| 世界设定 | 角色、地点、物品、组织、规则、事件、时间线、因果链 | 从正文提取、补全属性、整理时间线、检查冲突、生成关系图 |
| 角色关系 | 角色档案、目标、动机、弱点、秘密、角色弧光、关系变化 | 生成角色弧线、补全关系、检查章节推进、提示关系停滞 |
| 文风检查 | 作者声音、句式、节奏、叙事视角、张力节奏、风格漂移和质量诊断 | 分析样本、生成风格说明、整理禁用风格、检查风格偏移、给改写建议 |
| `yudao-ui-admin-vben/apps/web-antd` | 管理员 | 配置 MetaSchema、字段、可见性、AI 上下文、导出、校验和版本 |
| `muse-studio` | 普通用户 | 填写作品设定、章节大纲、世界设定、角色关系、文风检查和知识表单 |
所有规划入口都应支持:
两端可以共享接口类型和字段渲染约定,但不能共享错误的用户语言。管理员可以看到系统术语,普通用户默认只看到创作语言。
- 用户手写。
- AI 生成。
- AI 补全。
- AI 整理。
- AI 检查。
- AI 给多组选项。
- 从正文提取。
- 绑定后续生成上下文。
接口边界:
普通用户界面不应把 `Schema / Pipeline / Agent / Prompt` 做成默认导航语言。需要解释系统行为时,使用“创作规则、AI 助手、生成规则、处理记录、AI 候选、待确认知识、已确认设定”等用户语言。
- 管理后台只通过 `/admin-api/**` 配置和发布 MetaSchema。
- 用户端只通过 `/app-api/**` 消费当前用户和当前作品可见投影。
- 用户端当前用户入口是 `/app-api/muse/me`,不使用 `/app-api/auth/me`。
- 用户端动态表单只依赖后端 app 侧投影接口;字段可见性、授权、来源状态和用户语言分组都由后端返回,前端不能从管理端原始 MetaSchema、本地缓存或字段名自行推断。
## 4. 可见性与前端过滤
## 2. 管理后台 MetaSchema 配置
前端必须按元数据可见性决定普通用户能看到哪些实体、字段和关系。
管理后台归属 Vben Admin。
| 控制项 | 前端展示含义 |
|---|---|
| `uiVisible` | 是否展示给普通用户 |
| `aiContext` | 是否允许进入 AI 生成上下文;不等于用户可见 |
| `userEditable` | 普通用户是否可以编辑 |
| `userSearchable` | 普通用户是否可以检索 |
| `exportable` | 是否允许随作品导出 |
管理员可配置:
- `domain / scope / targetType`。
- 字段类型、必填、枚举、引用、排序和校验规则。
- `uiVisible`、`aiContext`、`userEditable`、`userSearchable`、`exportable`。
- 版本、启停、回滚、灰度或变更记录。
- 影响预览:哪些用户端表单、知识投影、生成上下文和导出范围会受影响。
约束:
- 管理后台只提交结构配置,不替用户填写作品内容。
- 激活配置必须进入版本化记录。
- 配置变化影响用户端时,用户端看到的是可理解的能力变化或字段变化,不看到后台字段表。
- 关闭字段可见性不能删除历史事实;只影响展示、检索、AI 上下文或导出。
- 管理后台可以配置用户知识库、市场知识库、作品资产和智能体相关结构的展示规则,但购买、安装或绑定资产不等于写入作品事实。
## 3. 用户端创作表单
用户端归属 `muse-studio`。
普通用户默认入口:
| 用户入口 | 承载内容 | AI 辅助 |
|---|---|---|
| 作品设定 | 题材、类型、主题、基调、禁区、结局方向 | 生成故事前提、补全设定、整理梗概、检查偏题 |
| 章节大纲 | 章节顺序、摘要、目标、主线、支线、伏笔、情节节拍 | 生成章节摘要、补齐大纲、检查章节目标 |
| 世界设定 | 角色、地点、物品、组织、规则、事件、时间线 | 从正文提取、补全属性、检查冲突 |
| 角色关系 | 角色档案、目标、动机、弱点、秘密、弧光、关系变化 | 生成弧线、补全关系、提示关系停滞 |
| 文风检查 | 作者声音、句式、节奏、视角、风格漂移 | 分析样本、整理禁用风格、检查偏移 |
用户端可以触发 AI 生成、补全、整理、检查和从正文提取,但结果必须先进入 Shadow 候选或 Knowledge Draft。用户确认后才成为后续生成上下文。
用户端动态表单不得暴露系统保护节点配置。开放槽位可以让用户选择可替换智能体或知识库;输入输出合规、拆分切块、RAG 入库、语义安全围栏、静态检查、质量门控、权限、审计和 Shadow -> Canonical 仍由系统固定链路保证。
## 4. 可见性合同
| 控制项 | 管理后台含义 | 用户端含义 |
|---|---|---|
| `uiVisible` | 是否允许展示给普通用户 | false 时用户端默认不展示;也不生成可见空壳 |
| `aiContext` | 是否允许进入 AI 上下文 | 不等于用户可见,也不等于可导出;前端只展示后端返回的上下文摘要 |
| `userEditable` | 普通用户是否可编辑 | false 时只能只读展示或隐藏;不能在前端强开编辑 |
| `userSearchable` | 是否允许普通用户检索 | false 时不进入用户搜索入口、筛选项或联想结果 |
| `exportable` | 是否允许随作品导出 | false 时导出预检必须排除,并显示不可导出原因 |
前端约束:
- `uiVisible=false` 的实体、字段或关系不得出现在普通用户默认 UI 中。
- `aiContext=true` 只能说明可进入上下文,不代表普通用户可以看见。
- `userEditable=false` 时,普通用户可以只读查看;是否允许展示仍由 `uiVisible` 和资源权限共同决定。
- 普通用户可见投影落后或重建失败时,前端应隐藏失效数据或提示稍后重试,不能展示已经被配置隐藏的字段。
- 管理员侧可以看到完整配置;普通用户侧只能看到当前用户和当前作品有权访问且允许展示的投影。
- 用户端只消费后端 app 侧投影接口返回的可见投影,不自行推断隐藏字段、授权状态或来源状态。
- 管理后台可以看到完整配置,用户端只能看到有权限且允许展示的字段。
- `aiContext=true` 不允许前端把隐藏字段展示给用户。
- `userEditable=false`、`userSearchable=false`、`exportable=false` 都必须同时在 UI 和提交动作上体现;前端禁用只是体验,后端仍要强制校验。
- 投影落后时,用户端必须显示重试/稍后刷新,而不能展示已被隐藏的数据。
安全边界:
- 前端隐藏字段、禁用控件或移除入口不是安全边界。
- 后端必须在可见投影、保存、检索、AI 上下文组装和导出预检中重复执行权限、来源状态和授权快照校验。
- 前端不能把 `uiVisible=false` 的字段通过搜索、导出、调试面板、错误详情或 AI 上下文摘要泄露出来。
- 来源 lineage 和授权快照由后端生成并随投影返回;前端只能展示、传递和刷新,不能伪造或覆盖。
## 5. 渲染链路
### 5.1 管理员侧链路
### 5.1 管理后台
1. 拉取或接收目标 MetaSchema。
2. 保留并展示 `domain + scope + targetType` 三维分类。
3. 渲染字段、校验规则和可见性控制项。
4. 执行前端即时校验。
5. 提交管理员配置变更。
6. 刷新配置版本或变更结果。
```text
加载 MetaSchema 列表
-> 选择 domain/scope/targetType
-> 编辑字段和可见性
-> 前端即时校验
-> /admin-api 提交
-> 后端版本化
-> 展示影响预览和激活结果
```
这条链路服务系统配置,不写普通用户作品事实。
### 5.2 用户端
### 5.2 普通用户侧链路
```text
进入作品规划台或知识表单
-> /app-api 拉取当前作品可见结构、数据和版本修订
-> 按创作语言分组渲染
-> 用户手写或触发 AI
-> AI 结果进入候选/草稿
-> 用户确认后写入对应 Canonical owner
```
1. 拉取当前作品可见的规划结构和初始值。
2. 按作品设定、章节大纲、世界设定、角色关系、文风检查分组渲染。
3. 根据 `uiVisible`、`userEditable`、`userSearchable`、`exportable` 控制展示、编辑、检索和导出入口。
4. 用户手写或触发 AI 生成、补全、整理、检查。
5. AI 产出的规划方案先作为 AI 候选或待确认内容展示。
6. 用户确认后,规划项才成为后续生成上下文的一部分。
用户确认必须走对应业务入口:规划候选进入规划正式事实,Knowledge Draft 进入 Local KB,正文候选进入正文 Block。规划候选的接受、修改后保存和丢弃必须走 planning owner 的 `/app-api/**` 决策接口,不得复用 AI Suggestion accept,也不得通过动态表单通用保存写入规划正式事实。
这条链路服务作品规划,不暴露系统后台配置。
### 5.3 版本兼容和提交合同
## 6. 组件分层建议
后端 app 侧投影接口返回动态表单时,必须带版本与修订信息:
组件命名可以随实现调整,但职责边界应保持清楚:
| 字段 | 含义 | 前端用途 |
|---|---|---|
| `schemaVersion` | 当前激活 MetaSchema 结构版本 | 判断字段结构、校验规则和枚举是否仍匹配 |
| `projectionVersion` | 当前用户、作品、授权和来源状态计算后的可见投影版本 | 判断可见性、可编辑状态和来源快照是否仍匹配 |
| `dataRevision` | 当前表单目标对象的数据修订号 | 判断用户编辑期间是否发生并发修改 |
- `MetaSchemaAdminConsole`:管理员元数据配置容器。
- `AdminSchemaForm`:管理员侧结构与字段配置表单。
- `PlanningDeskForm`:普通用户作品规划表单容器。
- `PlanningSection`:作品设定、章节大纲、世界设定、角色关系、文风检查等用户入口。
- `DynamicField`:字段渲染器,按字段类型选择输入组件。
- `AIPlanningActions`:生成、补全、整理、检查、给多组选项等动作入口。
- `VisibilityGate`:按权限和 `uiVisible` 等元数据控制显示、编辑、检索和导出。
用户端提交动态表单保存时,必须带 `expectedSchemaVersion`、`expectedProjectionVersion` 和 `expectedDataRevision`。后端只能在三者仍匹配且权限、来源状态、授权快照、字段状态都有效时写入;前端不能只靠本地 Zod 校验或禁用控件放行提交。
组件复用的底线是“能力复用,不复用错误语言”。同一个字段渲染器可以服务管理员和普通用户,但普通用户界面不显示管理员配置术语。
| 错误码 | 触发条件 | 前端处理 |
|---|---|---|
| `SCHEMA_STALE` | 激活 MetaSchema 已升级,字段结构或校验规则不再匹配 | 暂存用户未提交输入,重新拉取投影并重渲染表单,提示用户复核变更字段后再提交 |
| `FIELD_DEPRECATED` | 提交包含已废弃、隐藏或不再可编辑字段 | 标记被移除字段,不再把该字段随下一次提交发送;如有用户输入,展示为需人工处理的本地草稿 |
| `PROJECTION_STALE` | 用户权限、授权快照、来源状态或可见性投影已变化 | 重新拉取投影,刷新可见字段和不可用原因;不能继续展示或提交旧投影里的隐藏数据 |
| `DATA_REVISION_CONFLICT` | 目标对象在用户编辑期间被其他操作修改 | 拉取最新数据,展示冲突提示,由用户选择覆盖、合并或放弃本地草稿;具体策略由对应业务 owner 决定 |
## 7. 校验与错误呈现
这些错误属于动态表单兼容策略,不改变 owner:规划正式事实仍由 planning owner API 决策,知识正式事实仍由 Knowledge Draft 确认入口决策,正文正式事实仍由编辑器 Block 保存或候选接受入口决策。
### 7.1 校验策略
## 6. 组件边界
- 前端做即时可理解的校验:必填、范围、类型、格式和基础依赖。
- 后端做最终事实校验:权限、并发、跨字段规则、来源有效性和是否允许进入规范数据(Canonical)。
- AI 生成、补全、整理、检查失败时,前端应保留用户已输入内容,并说明失败原因和可重试动作。
Vben 管理后台组件示例:
### 7.2 错误呈现
- `MetaSchemaList`
- `MetaSchemaEditor`
- `MetaFieldTable`
- `VisibilityPolicyPanel`
- `SchemaImpactPreview`
- 错误要告诉用户哪里错、为什么错、怎么改。
- 管理员错误可以保留必要系统术语,例如 `domain`、`scope`、`targetType`。
- 普通用户错误要回到创作语言,例如“这个角色关系缺少目标角色”,而不是裸露底层字段名。
`muse-studio` 用户端组件示例:
- `PlanningDeskForm`
- `PlanningSection`
- `KnowledgeDraftForm`
- `DynamicField`
- `AIPlanningActions`
- `VisibilityGate`
共享只限:
- 类型定义。
- 字段渲染协议。
- 校验消息码。
- 设计 token 或基础 UI 规范。
不共享:
- 管理后台 layout。
- Vben 菜单和 store。
- 管理员系统术语文案。
- 后台配置编辑组件。
## 7. 校验和错误
前端即时校验:
- 必填。
- 类型。
- 范围。
- 枚举。
- 基础引用是否选择。
后端最终校验:
- 权限。
- revision。
- 来源状态。
- 授权快照。
- 跨字段业务规则。
- 是否允许进入 Canonical。
用户端错误必须回到创作语言。例如“这个角色关系缺少目标角色”,不要直接暴露 `target_entity_id required`。
## 8. 章节叙事规划边界
作品规划台可以使用“情节节拍 / 场景推进”这类作者语言,但当前前端文档不引入小说场景(Scene)作为独立一级模型,也不采用 `Outline / Scene` 作为并列一级导航。
用户端可以使用“情节节拍 / 场景推进”作为创作语言,但阶段 7 不新增 Scene 作为独立一级前端模型。近程叙事控制归入章节大纲、章节目标或 Narrative State 展示。
前端应把这类近程叙事控制归入章节大纲、章节叙事规划或章节目标相关界面;如果未来需要独立模型,必须先由架构决策记录(ADR)、后端表结构和接口契约确认,再同步调整前端状态和路由。
如果未来引入独立 Scene 模型,必须先由架构、后端 Schema/API 和状态机确认,再调整前端路由与状态。
## 9. 关联阅读
- 模型层 MetaSchema 边界:`架构-02-核心数据结构与双轨模型.md`
- 状态机与元数据可见性约束:`架构-04-状态机与约束清单.md`
- 产品功能边界:`产品-02-核心功能与交互边界.md`
- 普通用户操作流程:`流程-01B-普通用户操作流程(操作视角).md`
- 统一数据库 Schema:`后端-04-统一数据库Schema-v1.md`
- 统一 API 契约:`后端-05-统一API契约-v1.md`
- 前端工程结构:`前端-01-工程结构与核心依赖.md`
- 后端 Schema:`后端-04-统一数据库Schema-v1.md`
- 后端 API:`后端-05-统一API契约-v1.md`
- 架构核心模型:`架构-02-核心数据结构与双轨模型.md`
- 状态机:`架构-04-状态机与约束清单.md`

View File

@ -1,151 +1,194 @@
# 后端-01:领域模型与聚合设计
- 版本:v5
- 更新日期:2026-05-13
- 目标读者:后端/架构
- 版本:v6
- 更新日期:2026-05-23
- 目标读者:后端 / 架构 / 产品
- 阅读时间:30-45 分钟
- 边界说明:这里只讲领域模型、聚合职责和不变式;不写工程结构(去 `后端-02`),不写表结构(去 `后端-04`),不写端点契约(去 `后端-05`)。本文描述目标领域边界,不代表当前代码都已实现。
- 边界说明:本文件只定义 Muse 领域模型、聚合职责、owner module 和不变式;工程结构看 `后端-02`,流程看 `后端-03`,Schema 看 `后端-04`,API 看 `后端-05`。
## 1. 设计哲学(只留能指导实现的)
## 1. 设计原则
### 1.1 数据结构优先
1. 领域事实按业务 owner 归属,不按管理端/用户端归属。
2. `admin-api` 和 `app-api` 是入口差异,不是两套模型。
3. Yudao 的 `system/infra/pay/bpm/report/mp` 是平台能力和可复用底座,不承载 Muse 创作事实。
4. AI、市场、知识库、作品、账户权益都必须有完整入口、状态、来源、审计和失败路径,不能做孤儿模型。
5. Shadow -> Canonical 的用户主权和来源 lineage 是后端硬约束,不能依赖前端自觉。
6. Protected Node Registry 是保护节点唯一口径,开放槽位只能替换子智能体,不能绕过保护节点。
- 先把核心数据结构、领域归属和不变式写清楚,后续代码只是把它们稳定执行。
- 如果某个业务流程需要大量旁路条件才能跑通,通常是模型归属或状态边界错了。
- 产品入口可以变多,但领域模型不能按 UI 面板膨胀。
平台底座的含义必须收紧:
### 1.2 聚合根识别原则
- 有独立生命周期:可创建、停用、删除、迁移、归档或版本回滚。
- 有业务唯一性约束:能在聚合边界内检查。
- 有清晰事务边界:一次操作的原子性范围明确。
- 有明确事实归属:系统配置、用户数据、作品数据、全局资料和局域知识不能混写。
## 2. 有界上下文与数据归属
有界上下文(BC)划分与协作规则以 `架构-01-系统全貌与边界上下文.md` 为准;这里仅列领域对象归属。
| 数据层级 | 归属 | 代表对象 | 不负责什么 |
|---|---|---|---|
| 系统级配置(System-level Configuration) | Admin BC | MetaSchema、MetaField、SystemPrompt、PromptVersion、AgentConfig、NewApiPlanMapping、GlobalKnowledgeBase、GlobalKnowledgeAccessPolicy、EvaluationDataset | 不保存普通用户正文、作品事实或单作品创作取舍 |
| 用户级数据(User-level Data) | Auth / Admin / Usage | User、Role、Permission、UserRole、RolePermission、NewApiUserBinding、个人配额和绑定状态、使用记录汇总视图 | 不复制 New-API 的模型供应商、路由、限流、成本策略和消耗日志权威数据 |
| 作品级数据(Work-level Data) | Content BC | Work、Chapter、Block、导入状态、作品工作台内容能力 | 不保存系统 Prompt、Agent 或全局授权策略 |
| 全局知识库(Global Knowledge Base) | Admin BC + Knowledge BC | 管理员维护的资料集、版本、授权策略 | 不自动写入某个作品的正式事实 |
| 局域知识库(Local Knowledge Base) | Knowledge BC | 单个作品的正式知识、叙事状态、来源追溯、用户可见投影 | 不跨作品共享 Canonical(规范数据),不暴露系统内部全部知识 |
| AI 待审与任务 | AI BC | GenerationJob、ExtractionJob、Suggestion、Proposal、Risk Markers | 不拥有 Canonical(规范数据)写入权 |
| 使用与审计 | Usage / Audit | AuditLog、任务记录、普通用户可见使用记录、同步失败记录 | 不替业务上下文写事实 |
## 3. 聚合与实体(按 BC(有界上下文))
### 3.1 Content BC(内容上下文)
- 聚合根:Work(作品)
- 关键实体:Chapter(章节)、Block(文本块)
- 作品工作台需要的作品设定、章节大纲和章节叙事规划优先落到 Work / Chapter / Narrative State / MetaSchema,不为每个 UI 面板硬建孤立聚合。
- 典型不变式:
- 同一 Work(作品)内 Chapter(章节)顺序唯一。
- 同一 Chapter(章节)内 Block(文本块)顺序唯一。
- Block(文本块)的 revision 单调递增,任何正文写入都必须基于 expectedRevision。
- 用户保存正文后,正文就是 Canonical(规范数据);后续提取、校验或投影失败不得回滚正文。
### 3.2 Knowledge BC(知识上下文)
- 聚合根:KnowledgeEntity(知识实体),归属于某个 Work(作品)。
- 关键实体:KnowledgeRelation、KnowledgeEvent、KnowledgeAttributeChange、NarrativeState。
- 典型不变式:
- 同一 Work(作品)内 Entity.name 至少在同类型范围内唯一。
- Attributes 的类型、必填、范围和可见性由 MetaSchema / MetaField 约束。
- Relation / Event / NarrativeState 必须能追溯到文本块、章节确认、规划项或用户手动操作。
- 进入局域知识库(Local Knowledge Base)的正式知识必须来自用户确认、章节级确认或用户手动修正。
- 概念聚合:LocalKnowledgeBase(局域知识库)
- 这是单个作品的知识空间边界,不必默认是一张独立表。
- 当前优先用 `work_id + knowledge_entities / knowledge_relations / knowledge_events / narrative_states` 表达。
- 如果未来新增 `local_knowledge_bases`,只能作为作品级知识空间的显式配置或状态载体,不能成为第二套事实源。
- 概念聚合:KnowledgeVisibilityPolicy(知识可见性策略)
- 由 MetaSchema / MetaField 的 `ui_visible`、`ai_context`、`user_editable`、`user_searchable`、`exportable` 语义和全局知识库访问策略共同决定。
- 用户可见投影(User-visible Projection)只是读模型,不反向覆盖 Canonical。
### 3.3 Admin BC(管理上下文)
管理员控制台(Admin Console)管理系统能力,不替普通用户写单个作品。
| 聚合/对象 | 领域职责 | 建模边界 |
| Yudao 底座 | Muse 使用方式 | 禁止承载 |
|---|---|---|
| MetaSchema / MetaField | 定义作品模板、实体字段、关系字段、事件字段、叙事字段、校验和可见性 | 只定义结构和规则,不保存叙事运行态值 |
| SystemPrompt / PromptVersion | 管理系统 Prompt、任务 Prompt、体裁 Prompt、文风 Prompt 的版本、启停、灰度和回滚 | 需要版本快照;不把 Prompt 文本散落在业务代码 |
| AgentConfig | 管理生成、提取、校验、规划、检索等 Agent 的启停、超时、重试和 fallback | 只保存 Muse 侧编排策略;不承载模型供应商和成本路由 |
| NewApiUserBinding | 维护 Muse 用户与 New-API 用户、分组、配额、套餐和绑定状态的同步关系 | 同步必须幂等、可重试、可审计;不复制 New-API 消耗日志权威来源 |
| NewApiPlanMapping | 映射 Muse 套餐/用户组到 New-API 分组、配额和套餐策略 | 只管生命周期与配置入口,不实现 New-API 模型路由 |
| Role / Permission | 管理 Sa-Token 使用的最小 RBAC 角色和权限点 | 只表达接口和后台能力授权,不表达作品事实确认 |
| UserRole / RolePermission | 维护用户、角色和权限点的多对多关系 | 不替代作品级权限和全局知识库访问策略 |
| SystemServiceIdentity | 管理系统任务(System Job)服务身份、启停、权限范围和审计名称 | 不允许伪装成普通用户确认正文、知识草稿或 AI 候选 |
| GlobalKnowledgeBase | 管理系统级资料集、版本、启停、索引状态和来源 | 全局资料不自动写入作品局域知识库 |
| GlobalKnowledgeAccessPolicy | 管理用户/用户组/作品对全局知识库的可见、可检索、可用于生成、默认绑定和解绑边界 | 默认不可越权使用;策略变更不改写作品事实 |
| EvaluationDataset | 管理固定评测场景、固定数据集和评分标准 | 首次用于正式评测后应锁定或保留版本 |
| EvaluationRun | 记录一次评测执行、模型评审、算法汇总评分、置信度和风险结论 | 评测结论用于系统改进,不替代用户确认正文或知识 |
| `yudao-gateway` | 统一入口、鉴权透传、路由 `/admin-api/**` 与 `/app-api/**` | 领域判断、候选确认、知识确认 |
| `yudao-dependencies` / `yudao-framework` | 依赖、Web、安全、Redis、MQ、Job、日志等基础能力 | 任何 Muse 业务事实 |
| `yudao-server` | 聚合启动入口和模块装配 | 业务规则、事务脚本、跨模块事实写入 |
| `yudao-module-system` | 用户、角色、权限、菜单、登录日志、操作日志 | 作品正文、知识、市场授权、AI 候选 |
| `yudao-module-infra` | 文件、配置、字典、任务、API 日志、监控 | 创作事实、权益账本、市场事实 |
| `yudao-module-pay` | 支付、充值、退款和交易基础能力 | 市场资产 owner、授权快照、作品事实 |
| `yudao-module-bpm` | 复杂审核、申诉、合规流程编排 | 简单业务状态机的唯一事实源 |
| `yudao-module-report` | 报表、大屏、运营分析 | 业务事实写入 |
| `yudao-module-mp` | 公众号分发、订阅通知、运营触达 | 创作、知识、市场或账户事实 |
这些对象先定义领域职责,不代表每一项都必须新增独立表;精确表结构以 `后端-04-统一数据库Schema-v1.md` 为准。
## 2. BC 到 Yudao 模块映射
Sa-Token 是认证授权基础设施,不是新的产品架构。领域层只承认三类访问主体:
本映射是逻辑 owner 到 Yudao fork 模块的目标落点。若落地阶段临时折叠到现有模块,也必须保留逻辑 owner,不允许两个模块同时写同一个事实。
- 管理员(Admin):通过 RBAC 获得管理员控制台能力,但不能替普通用户确认单个作品事实。
- 普通用户(User):通过登录态访问自己的作品、个人中心和被授权全局知识库,作品级权限仍由 Muse 业务规则校验。
- 系统任务(System Job):通过明确服务身份执行投影、索引、同步、评测或清理任务,不复用普通用户权限绕过业务确认。
| BC | owner module | 主要对象 | Admin/App 入口 | 不负责 |
|---|---|---|---|---|
| Auth / Permission | `yudao-module-system` | 用户、角色、权限、权限组、菜单、登录日志、操作日志 | Yudao 原生 admin/app 认证与权限接口 | 作品级事实确认、知识确认、市场授权事实 |
| Infra | `yudao-module-infra` | 文件、配置、字典、定时任务、API 日志、监控 | Yudao 原生 infra 接口 | Muse 业务领域事实 |
| Content BC | `yudao-module-content` | Work、Chapter、Block、正文版本、Planning Canonical、MetaSchema、Block Source Attribution、导入导出任务、作品设置 | `/admin-api/muse/content/**`、`/app-api/muse/works/**` | Prompt、Agent、知识确认、市场交易 |
| Knowledge BC | `yudao-module-knowledge` | User KB、Local KB、Knowledge Draft、Knowledge Entity/Relation/Event、Knowledge Source Binding、投影状态 | `/admin-api/muse/knowledge/**`、`/app-api/muse/knowledge-*/**` | 正文写入、市场资产授权、模型路由 |
| AI Orchestration BC | `yudao-module-ai` 二开 | Prompt、Agent、Agent Slot、Tool Grant、AI Task、Suggestion、Planning Candidate、Quality Result、Evaluation Dataset/Run | `/admin-api/muse/ai/**`、`/app-api/muse/ai/**`、`/app-api/muse/suggestions/**` | New-API 模型 Provider/供应商路由、分组限流、成本策略、原始调用日志 authority、用户权益账本、正文 Canonical |
| Marketplace/Asset BC | `yudao-module-market` | Marketplace Asset、Listing、License、Authorization、Install、Publish Request、Appeal、Governance Result、Handoff、Precheck、Source Status Event | `/admin-api/muse/market/**`、`/app-api/muse/marketplace/**` | 正文事实、知识正式确认、Agent Slot Binding、Knowledge Source Binding、Block Source Attribution、支付清结算底层 |
| Account / Entitlement BC | 逻辑 `account`,物理为 `yudao-module-account` 或 `member` 二开二选一 | Profile、Entitlement、Quota、Usage Summary、Purchase/Auth/Publish Summary、Personal Center Summary | `/admin-api/muse/account/**`、`/app-api/muse/account/**`、`/app-api/muse/me` | 作品事实、市场 asset owner、New-API 原始调用日志或成本账本 authority |
| Source / Authorization Context | 来源对象 owner + outbox 协作 | Source Snapshot、Authorization Snapshot、Source Status Event、Source Propagation Target | 通过 Content / Knowledge / AI / Market / Account 的 owner API 和 `/admin-api/muse/source-events/**` 暴露 | 业务 Canonical 写入、支付清结算、权限菜单 |
| Payment BC | `yudao-module-pay` | 充值、支付、交易流水、退款基础能力 | Yudao 原生 pay 接口,Muse 只引用交易结果 | 市场资产 owner、作品事实 |
| Workflow BC | `yudao-module-bpm` | 复杂审核、申诉、合规流程 | Yudao 原生 bpm 接口或 Muse 流程回调 | 简单资产状态机的唯一 owner |
### 3.4 AI BC(人工智能上下文)
`account` 的逻辑 owner 必须固定:如果后续选择在 `member` 内二开,也只能由 `member` 内的 Muse account 包写 Profile、Entitlement、Quota 和个人中心聚合;不能再并行新增另一个 `account` 模块写同一批事实。
- 聚合根:GenerationJob(生成任务)、ExtractionJob(提取任务)。
- 关键对象:Suggestion(建议)、Proposal(提案)、RiskMarkers(风险标记)、配置快照。
- 典型不变式:
- AI 只能写 Shadow(待审层),不能直接写 Canonical(规范数据)。
- 外部 AI 调用、提取、校验、检索失败不得破坏已保存正文和正式知识。
- 任务启动时必须读取 PromptVersion、AgentConfig、上下文策略、NewApiUserBinding 和全局知识授权的可追溯快照。
- 运行中的任务不能中途切换到混合配置。
## 3. 核心聚合
`muse-ai` 负责编排和状态,不拥有模型供应商、模型路由、用户分组限流、Token 成本策略和 New-API 消耗日志权威数据。
### 3.1 Content
### 3.5 Usage / Audit BC(使用与审计上下文)
| 聚合/实体 | 说明 | 不变式 |
|---|---|---|
| Work | 单个创作项目,也是市场作品资产的来源对象 | owner 用户不可丢;发布到市场不转移作品私有事实 owner |
| Chapter | 作品结构单元 | 同一 Work 内排序唯一;章节审阅不直接写正式知识 |
| Block | 正文最小编辑单元 | revision 单调递增;任何正文写入必须基于 expectedRevision |
| Block Source Attribution | 正文 revision 的来源归因 | 候选使用 AI、市场、外部或授权知识来源时必须写入 lineage、授权快照和召回状态 |
| Import / Export Task | 导入解析和导出交付任务 | 外部文件处理异步化;导出前必须重验权限、来源和许可 |
| Planning Canonical | 用户确认或手动保存后的正式规划项 | 规划候选不能自动进入正式规划;进入 AI 上下文前必须校验来源、版本和可见性 |
| MetaSchema | 作品和知识表达结构的系统级版本 | 管理员发布版本;影响后续写入和展示,不改写历史 Canonical |
- 普通用户可见使用记录是领域能力,不落独立 `usage_logs` 本地明细表或本地汇总表。
- 用户可见记录从 generation_jobs、extraction_jobs、audit_logs、New-API 汇总或同步结果、以及必要任务级 usage 摘要生成。
- 管理员审计和普通用户使用记录可以引用同一底层事件,但入口、字段和权限必须隔离。
- New-API 的模型消耗日志仍以 New-API 为准;Muse 只保留与自身用户、作品、任务、授权和失败恢复相关的记录、引用或摘要。
Content 只拥有正文和作品结构。知识、AI 候选、市场授权都通过公开接口或事件协作。
## 4. 不变式与一致性(必须明确)
### 3.2 Knowledge
| 聚合/实体 | 说明 | 不变式 |
|---|---|---|
| User Knowledge Base | 用户自己的可复用知识库,可绑定作品、可发布市场 | 不自动写入任一作品 Local KB |
| Local Knowledge Base | 单作品正式知识空间 | 只归属当前 Work,不跨作品共享 Canonical |
| Knowledge Draft | 待确认知识变更 | 必须有来源快照、授权快照、风险标记和确认入口 |
| Knowledge Source Binding | 知识来源和授权绑定 | 来源 revoked/recalled/blocked 时禁止新确认、新绑定或受限导出 |
| Projection State | PG 到检索/图查询的投影状态 | 投影不是事实源,失败可重试,不反写 Canonical |
知识草稿进入 Local KB 的唯一入口是用户在知识确认入口显式确认。接受正文候选不自动确认知识草稿。
全局知识库由管理员治理策略和 Knowledge 处理能力共同承接:管理员决定可见性、授权范围和启停策略,Knowledge 负责资料处理、索引、投影和绑定状态。全局知识不能因为被授权、安装或绑定而自动成为作品事实。
### 3.3 AI Orchestration
| 聚合/实体 | 说明 | 不变式 |
|---|---|---|
| Agent | 配置型或工作流型智能体 | 只能替换开放槽位,不能替换保护节点 |
| Agent Slot Binding | 作品级智能体槽位绑定 | 必须绑定版本、授权、来源状态和预检快照 |
| Tool Grant | 工具授权 | 逐工具约束动作、目的、输入来源、输出位置、副作用和审计 |
| Agent Runtime Permission Envelope | 智能体运行时权限包 | 由服务端生成;智能体和前端不能自报可读上下文、工具或预算 |
| AI Task | 生成、解析、检测、评估任务 | 任务启动时固化权限包、上下文快照、配置快照和幂等键 |
| AI Suggestion | 正文候选 | 只能进入 Shadow,不能直接写正文 |
| Planning Candidate | 规划候选 | 只能进入 Shadow,必须经用户确认或手动保存后才成为正式规划 |
| Candidate Quality Result | 候选质量结果 | 质量结果不单独决定可接受性,最终由 Candidate Decision Envelope 合并 |
| Evaluation Dataset / Run | 质量评估集和评估运行 | 默认不得使用用户私有正文、私人候选全文、完整 Prompt/Response 或完整上下文 |
AI 模块负责 Muse 侧编排、智能体、任务和待审对象。Yudao 原生 `ai` 能力只是可复用底座;一旦二开为 Muse AI owner,仍不得拥有 New-API 模型 Provider、供应商路由、分组限流、成本策略、原始调用日志 authority 或正文/知识 Canonical。
### 3.4 Marketplace
| 聚合/实体 | 说明 | 不变式 |
|---|---|---|
| Marketplace Asset | 作品、智能体、知识库市场对象 | 市场上架不改变原 owner,也不自动写入购买者作品事实 |
| Listing | 上架记录 | 必须经过发布检查、授权快照和治理状态 |
| License | 授权规则 | 阅读、安装、绑定、生成上下文、导出、商用必须按用途分开授权 |
| Authorization / Install | 授权和安装状态 | 只记录市场授权、安装和可展示状态;不写目标对象绑定事实 |
| Handoff / Precheck | 跨空间预检和跳转包 | `agentSlotPrecheckId`、`kbBindPrecheckId`、`workAssetUsePrecheckId` 等必须一次性消费和可审计 |
| Source Status Event | 来源状态事件 | 撤权、下架、召回、owner 缺失、版本变化、处理失败和需重验必须可幂等传播 |
| Appeal / Governance Result | 申诉和治理结果 | 召回、下架、blocked 必须通过 Source Status Event 传播 |
市场 owner 只拥有市场资产、Authorization、Install、Handoff、Precheck 状态和治理结果。目标写入必须回到目标 owner:Agent Slot Binding 由 AI 写,Knowledge Source Binding 由 Knowledge 写,作品正文或 Block Source Attribution 由 Content 写,账户聚合由 Account 写。市场展示状态只能通过目标 owner 的事件或状态回执刷新,不能直接写目标事实。
### 3.5 Account / Entitlement
账户模块是用户可见的权益和记录总览,不是所有消费账本的事实源。
| 对象 | 说明 |
|---|---|
| Profile | 普通用户资料和偏好 |
| Entitlement / Quota | 套餐、配额、能力开关和用量限制 |
| Usage Summary | 任务级用量摘要、New-API 引用和用户可见解释 |
| Purchase/Auth/Publish Summary | 购买、授权、发布记录总览 |
New-API 的模型 Provider、供应商路由、分组限流、成本策略和原始调用日志仍以 New-API 为准;Muse 只保留与自身任务、作品、权益和失败恢复相关的网关绑定引用、任务级摘要、调用归属、错误分类、幂等键和补偿状态。
### 3.6 Source / Authorization Context
Source / Authorization Context 是横切上下文,不是 Knowledge 单模块能力。来源对象由各自 owner 管理,授权快照和来源状态通过 outbox 传播。
| 对象 | owner | 不变式 |
|---|---|---|
| Source Snapshot | 来源对象 owner,例如 Content、Knowledge、AI、Market | 只描述来源对象、版本和 owner,不写目标 Canonical |
| Authorization Snapshot | 授权签发 owner | 固化授权用途、范围、有效期、许可限制和撤销状态 |
| Source Status Event | 来源对象 owner | 撤权、召回、blocked、owner 缺失、版本变化、处理失败必须幂等发布 |
| Source Propagation Target | 受影响对象 owner | Content、Knowledge、AI、Market、Account 幂等消费事件并更新自己的状态、禁用新使用或要求重验 |
### 3.7 Protected Node Registry
Protected Node Registry 是系统保护节点唯一口径,至少包含以下 registry ID;任何开放槽位、市场智能体或工作流智能体都只能挂在保护节点之后,不能替换这些节点:
| Registry ID | 保护节点 | owner / 落点 | 约束 |
|---|---|---|---|
| `input_compliance` / `output_compliance` / `semantic_guardrail` | 输入合规、输出合规、语义安全围栏 | AI application + 系统策略 | 用户智能体和市场智能体不能替换或关闭 |
| `permission_filter` / `audit` | 权限过滤、审计 | 各业务 owner + Yudao system/infra 基础能力 | 前端、智能体或批任务不能自报权限或跳过审计 |
| `chunking` / `rag_ingest` | 拆分切块、入 RAG | Knowledge pipeline | 只能处理已授权资料和正式事实投影,失败可重试但不能反写 Canonical |
| `static_check` / `quality_gate` | 静态检查、质量门控 | AI application | 可以阻断或标记风险,不能替用户确认正文、知识或规划 |
| `source_status_check` | 来源状态校验 | 来源 owner + 目标 owner | revoked/recalled/blocked/owner_missing/unauthorized 默认禁止新使用 |
| `shadow_to_canonical` | Shadow -> Canonical | Content、Knowledge、AI 对应 owner | 只能由用户确认或明确批量确认触发,不能被工作流智能体替代 |
## 4. 全局不变式
### 4.1 写入边界
- AI/自动化不能写 Canonical(规范数据),只能产出 Shadow(待审层)对象,例如 Suggestion(建议) / Proposal(提案) / Knowledge Draft(知识草稿)。
- 进入 Canonical(规范数据)的入口只有用户确认、用户保存正文、章节级确认或用户手动修正。
- 全书解析(Full Parse)必须保留 `parse_job_id + chapter_id` 的章节级确认边界;可以批量选择或一键确认全部可确认章节,但落库仍按章节隔离。
- 修改后合并必须让旧知识草稿失效,并基于最终正文重新提取。
- 用户保存正文写 Content Canonical。
- AI 只能写 Shadow 对象,例如 AI Suggestion、Knowledge Draft、Planning Candidate、Risk Marker。
- Accept Suggestion 只写正文、候选归档、Block Source Attribution 和必要 outbox;不写 Local KB。
- Knowledge Draft 必须经知识确认入口进入 Local KB。
- 全书解析章节确认只允许产生或推进章节范围内的 Knowledge Draft,不写正式知识。
### 4.2 权限与配置边界
关键流程 owner 和状态边界:
- Sa-Token 负责登录认证(Authentication)、RBAC(角色权限)、接口鉴权、会话与 Token 生命周期、当前用户上下文和基础审计上下文。
- 普通用户不能访问管理员接口,不能修改 MetaSchema、PromptVersion、AgentConfig、GlobalKnowledgeAccessPolicy、EvaluationDataset 等系统配置。
- 管理员配置影响生成链路时,后端必须使用可追溯配置快照,不允许用“当前最新配置”覆盖已启动任务。
- 全局知识库(Global Knowledge Base)没有 active 授权时,不得展示、检索或进入生成上下文。
- 局域知识库(Local Knowledge Base)只归属单个作品,不跨作品共享正式事实。
- Sa-Token 的管理员角色、用户角色或服务身份只提供接口准入;作品正文、规划项、知识草稿和 AI 候选是否进入 Canonical(规范数据),仍必须走 Muse 的业务用例和 Shadow -> Canonical 规则。
| 流程 | owner 边界 | 错误 / 幂等 / 状态边界 |
|---|---|---|
| 规划 | AI 只写 Planning Candidate;Content 只写用户确认后的 Planning Canonical | 候选过期、来源失效、版本冲突时不写 Canonical;确认按 `workId + candidateId + decisionId` 幂等 |
| 全书解析 | Content 拥有导入任务、解析任务和章节解析状态;Knowledge 只在确认链路中拥有 Knowledge Draft / KB Canonical | 章节级失败可重试;章节确认只推进 Knowledge Draft,不写正式知识;知识确认按 `workId + chapterId + draftId + decisionId` 幂等 |
| 知识库 | Knowledge 拥有 KB、Knowledge Draft、Knowledge Source Binding 和投影状态 | 来源失效禁用新确认、新绑定和受限导出;投影失败可重试,不反写 Canonical |
| 市场资产使用 | Market 只写 Authorization、Install、Handoff、Precheck 状态;目标事实由 Content / Knowledge / AI owner 写 | token 过期、已消费、来源变化或目标 owner 缺失时拒绝写入;消费按 precheck 幂等;market 只通过事件刷新展示状态 |
| New-API 用量 | AI Task 记录网关调用引用和调用归属;Account 只汇总用户可见摘要;New-API 保持 Provider、路由、成本和原始调用日志 authority | 超时、限流、回调失败按 task/request 幂等重试;Muse 只保存错误分类、幂等键和补偿状态 |
### 4.3 冲突处理
### 4.2 权限边界
- 内容冲突:revision 不匹配就是冲突,禁止静默覆盖。
- 知识冲突:不同来源给出不同属性值,必须以 Knowledge Draft / Proposal 或风险标记呈现给用户决定。
- 投影冲突:用户可见投影不是事实源;投影落后时,读路径和上下文组装必须使用水位标记、覆盖层或等价策略补齐。
- Yudao system 负责登录、角色、菜单、权限和基础审计。
- Muse 业务模块负责作品访问权、知识库授权、市场授权、Agent 槽位授权和导出许可。
- 管理员权限不等于可以替用户确认正文、知识草稿或 AI 候选。
- 系统任务必须使用服务身份,不得复用普通用户身份绕过 Shadow -> Canonical。
### 4.4 章节叙事规划与 Scene 边界
### 4.3 来源和授权边界
- 产品语言可以写“情节节拍 / 场景推进”,但当前模型不引入小说场景(Scene)作为独立一级模型。
- 近程叙事控制归入章节叙事规划,由 Chapter、Block 上下文和 NarrativeState(chapter)承载。
- 未来如果需要独立 Scene 模型,必须先补 ADR,并同步后端表结构、API、状态机和前端状态。
- 外部或授权来源进入上下文时必须有 Authorization Snapshot 和 Source Status。
- revoked、recalled、blocked、owner_missing、unauthorized 来源不得进入新生成、新确认、新绑定或受限导出。
- 修改后合并默认继承上游 lineage、授权快照、许可限制和召回状态;不能靠改写文本洗白来源。
### 4.4 配置快照
- Prompt、Agent、Tool Grant、Quality Policy、MetaSchema、授权策略都必须版本化。
- 已启动任务使用启动时配置快照,中途不能混用新旧配置。
- 管理员回滚只影响后续任务,不改写历史候选和质量结果。
## 5. 关联阅读
- 模型定义与规则:`架构-02-核心数据结构与双轨模型.md`
- 模块职责:`后端-02-工程结构与模块职责.md`
- 表结构:`后端-04-统一数据库Schema-v1.md`
- 接口契约:`后端-05-统一API契约-v1.md`
- 工程结构:`后端-02-工程结构与模块职责.md`
- 关键流程:`后端-03-关键流程实现与接口契约.md`
- Schema:`后端-04-统一数据库Schema-v1.md`
- API:`后端-05-统一API契约-v1.md`
- 核心数据结构:`架构-02-核心数据结构与双轨模型.md`
- 状态机:`架构-04-状态机与约束清单.md`

View File

@ -1,116 +1,205 @@
# 后端-02:工程结构与模块职责
- 版本:v5
- 更新日期:2026-05-13
- 目标读者:后端/架构/平台
- 阅读时间:20-35 分钟
- 边界说明:这里只讲工程结构、模块职责、依赖组织和公开协作边界;领域模型去 `后端-01`,流程去 `后端-03`,表结构去 `后端-04`,接口契约去 `后端-05`。本文描述目标模块边界,不代表当前代码都已实现。
- 版本:v6
- 更新日期:2026-05-23
- 目标读者:后端 / 架构 / 平台 / 测试
- 阅读时间:25-40 分钟
- 边界说明:本文件只定义后端工程基线、Yudao Cloud fork 保留/裁剪模块、Muse 业务模块职责和模块协作边界。领域模型看 `后端-01`,关键流程看 `后端-03`,Schema 看 `后端-04`,API 契约看 `后端-05`。本文描述目标工程形态,不代表当前仓库所有模块都已实现。
## 1. 模块化结构(多模块/单体)
## 1. 工程基线
后端采用模块化单体:单进程部署,但模块边界必须像服务边界一样严肃。管理员控制台(Admin Console)、用户工作区(User Workspace)和个人中心(Personal Center)可以共享后端进程,但不能共享错误的职责。
### 1.1 模块职责(按 BC(有界上下文) 对齐)
| 模块 | 职责 | 禁止承载 |
|---|---|---|
| `muse-shared` | 基础类型、通用错误、领域事件、分页模型、审计上下文、权限上下文(Permission Context)、Sa-Token 适配接口、当前用户/服务身份载体 | 具体业务用例、Repository 实现、外部服务调用 |
| `muse-content` | 作品(Work)、章节(Chapter)、文本块(Block)、导入导出、作品工作台(Work Workspace)所需内容能力、正文 revision 与冲突保护 | Prompt / Agent 配置、全局知识授权、模型供应商路由 |
| `muse-knowledge` | 全局知识库(Global Knowledge Base)读边界、局域知识库(Local Knowledge Base)、正式作品知识、用户可见投影(User-visible Projection)、来源追溯、知识检索边界、一致性检查输入 | 直接写正文、绕过授权读取全局资料、把投影当事实源 |
| `muse-ai` | 上下文组装、生成/提取/校验/规划/检索编排、Agent 调用适配、风险标记(Risk Markers)、GenerationJob / ExtractionJob 状态、Shadow(待审层)对象生成 | 模型供应商管理、模型路由、用户分组限流、Token 成本策略和 New-API 消耗日志权威存储 |
| `muse-admin` | 管理员控制台、元数据(MetaSchema / MetaField)、Prompt / Agent 配置、全局知识库授权、用户、角色、权限、服务身份、New-API 同步、NewApiPlanMapping、评测集(EvaluationDataset)和评测运行(EvaluationRun)、系统日志入口 | 普通用户单个作品正文写作、候选确认、作品知识取舍 |
| `muse-bootstrap` | 应用组装、配置装配、Sa-Token 配置装配、模块启动、HTTP 入口挂载 | 业务逻辑、跨模块旁路调用、临时补丁 |
### 1.2 New-API 职责边界
New-API 继续负责:
- 模型供应商。
- 模型路由。
- 用户分组限流。
- Token 成本策略。
- 模型消耗日志记录。
Muse 只负责和自身用户生命周期相关的同步动作,以及必要的分组、配额、套餐和绑定状态调整入口。Muse 可以保存任务级使用摘要、失败原因和同步状态,但不把 New-API 的成本日志复制成新的权威来源。
## 2. 依赖方向(硬约束)
模块依赖方向以公开接口为准,不以数据库表或 Repository 为准。
Muse 后端使用 `YunaiV/yudao-cloud` 的 fork,当前仓库命名为:
```text
muse-shared
↑
Content / Knowledge / Admin / AI
↑
muse-bootstrap
yudao-cloud/ # 后续可命名为 muse-cloud
```
运行时协作方向:
定位:Yudao Cloud 做后端微服务/单体聚合底座,先继承它的网关、权限、基础设施、配置、日志、文件、任务等平台能力,再补 Muse 自己的业务模块。
- `muse-admin` 提供系统配置、权限结果、Prompt / Agent / 全局知识授权和 New-API 绑定快照。
- `muse-content` 提供作品、章节、文本块和正文 revision 事实。
- `muse-knowledge` 依赖作品边界和来源锚点,提供正式作品知识、授权全局资料、用户可见投影和检索结果。
- `muse-ai` 读取 Admin + Content + Knowledge 的公开 Facade 组装上下文,只写任务状态和待审对象,不直接写 Canonical(规范数据)。
- Usage / Audit 能订阅事件和记录行为,但不能替业务模块写事实。
核心原则:
禁止事项:
1. 后端按领域能力拆模块,不按管理端/用户端拆模块。
2. `/admin-api/**` 和 `/app-api/**` 只是入口不同,不是两套领域事实。
3. 同一个领域事实只能有一个 owner module。
4. 优先复用 Yudao 的 system、infra、framework、gateway、job、log、file、config、dict 等平台能力。
5. Muse 业务模块只补创作系统需要的 content、knowledge、ai、market、account 能力。
6. `yudao-server` 只负责启动装配、配置聚合和模块引入,不放 use case、领域规则、mapper 拼装或跨模块写入脚本。
- 跨模块直接注入对方 Repository。
- 让 `muse-bootstrap` 变成通用业务服务容器。
- 让管理员控制台绕过 Facade 直接改普通用户作品事实。
- 让普通用户接口穿透到 Admin Repository 修改系统配置。
## 2. 当前保留模块
## 3. 目录结构与包规范
### 3.1 标准四层
每个业务模块统一四层:
- `api/`:HTTP 输入输出、参数校验、响应转换、权限入口。
- `application/`:用例编排、事务边界、跨模块 Facade 调用。
- `domain/`:领域模型、值对象、不变式、领域事件。
- `infrastructure/`:DB、缓存、外部服务适配、Repository 实现。
### 3.2 包访问控制
原则:
- `domain` 暴露领域对象、值对象、领域服务和仓储接口。
- `application` 暴露模块 Facade、命令(Command)和查询(Query)模型。
- `infrastructure` 只实现接口,不反向污染 `domain`。
- 跨 BC(有界上下文)调用走公开接口 / Facade / DTO;编译期约束优先于“团队自觉”。
建议公开接口:
| 模块 | 对外 Facade 示例 | 用途 |
| 模块 | 定位 | 阶段 7 处理 |
|---|---|---|
| `muse-admin` | `AdminConfigFacade`、`NewApiSyncFacade`、`GlobalKnowledgePolicyFacade` | 提供配置快照、授权判断、New-API 同步状态 |
| `muse-content` | `WorkContentFacade`、`BlockRevisionFacade` | 提供作品、章节、文本块读取和 revision 写入 |
| `muse-knowledge` | `KnowledgeQueryFacade`、`KnowledgeCommitFacade`、`ProjectionFacade` | 提供正式知识、授权资料、投影和确认写入 |
| `muse-ai` | `GenerationFacade`、`ExtractionFacade`、`RiskCheckFacade` | 提供生成、提取、校验编排入口 |
| `yudao-gateway` | 统一入口、路由、认证透传、接口聚合 | 保留,承接 `/admin-api/**` 与 `/app-api/**` 路由 |
| `yudao-dependencies` | 依赖版本管理 | 保留,不复制依赖版本到 Muse 模块 |
| `yudao-framework` | Web、安全、Redis、MQ、Job、日志、通用能力 | 保留,Muse 模块按 Yudao 方式接入 |
| `yudao-server` | 当前聚合启动入口,默认启用 `system`、`infra` | 保留,作为本阶段聚合启动入口;禁止承载业务逻辑 |
| `yudao-module-system` | 用户、角色、权限、菜单、登录日志、操作日志 | 保留并作为后台权限、菜单和用户基础能力 owner |
| `yudao-module-infra` | 文件、字典、配置、定时任务、API 日志、监控 | 保留并作为基础设施能力 owner |
| `yudao-module-ai` | Yudao AI 基础能力 | 保留,默认隐藏;后续二开为 Muse AI/Agent 能力载体 |
| `yudao-module-member` | 会员/账户基础能力 | 保留,默认隐藏;后续评估改造成账户/权益或被 `account` 替代 |
| `yudao-module-pay` | 支付、充值、交易基础能力 | 保留,默认隐藏;市场交易、套餐、充值时启用 |
| `yudao-module-bpm` | 工作流审批 | 保留,默认隐藏;审核、申诉、合规流程复杂后启用 |
| `yudao-module-report` | 报表大屏 | 保留,默认隐藏;运营报表、质量大屏时启用 |
| `yudao-module-mp` | 公众号能力 | 保留,默认隐藏;公众号分发、订阅通知、运营需要时启用 |
## 4. 关键依赖与运行形态
已清理模块:
- 外部 Agent 服务:负责生成、提取、校验、规划、检索等 AI 能力执行;不得绕过 Muse 写 Canonical(规范数据)。
- New-API:模型网关,负责模型供应商、路由、分组限流、成本策略和消耗日志;Muse 只同步用户、分组、配额、套餐和绑定状态。
- PostgreSQL:业务事实源,保存 Canonical、Shadow、Archive、配置、审计和必要投影事件。
- RAGFlow / Graph Query Provider:读取 PostgreSQL 投影,不是事实源;投影失败可重试,不回滚已确认事实。
- `mall`
- `crm`
- `erp`
- `mes`
- `iot`
- 空壳 `yudao-cloud/yudao-ui`
Shadow(待审层)存储必须有 TTL(过期时间)、归档和清理策略;Canonical(规范数据)写入必须可事务化、可并发保护。
注意:`mp` 明确保留,不删除。
## 5. 权限与入口边界
保留模块分层:
- Sa-Token 负责登录认证(Authentication)、RBAC(角色权限)、接口鉴权、会话与 Token 生命周期、当前用户上下文和基础审计上下文。
- 现有自研 Bearer Token 能力必须逐步收敛为 Sa-Token 适配层;业务模块继续依赖 `CurrentUserProvider` 或等价接口,不直接解析请求头。
- 管理员接口只能由具备管理员权限的用户访问。
- 普通用户接口必须校验当前用户对作品、章节、文本块、局域知识和授权全局知识的访问权限。
- 个人中心(Personal Center)只访问当前用户个人信息、Token 使用、生成记录总览、配额和套餐摘要,不承载系统配置。
- 系统任务(System Job)必须使用明确服务身份和审计上下文,不复用普通用户身份绕过确认。
- 前端隐藏入口只是体验优化;后端必须在接口层强制权限。
- `gateway/dependencies/framework/server` 是工程底座。
- `system/infra/member/pay/bpm/report/mp` 是 Yudao 平台和可选业务底座。
- `content/knowledge/ai/market/account` 是 Muse 创作业务 owner。
- `pay/bpm/report/mp` 在阶段 7 可以默认隐藏,但不能因为隐藏就删除依赖、菜单扩展点或后续接入边界。
## 6. 关联阅读
## 3. Muse 核心业务模块
### 3.1 模块清单
| Muse 模块 | 职责 | 不负责 |
|---|---|---|
| `yudao-module-content` | 作品、章节、文本块、正文版本、作品设置、MetaSchema、导入导出、Block Source Attribution | Prompt、Agent、市场授权、知识确认 |
| `yudao-module-knowledge` | 用户知识库、局域知识、知识草稿确认、知识来源、投影、检索来源、知识库绑定 | 正文写入、市场交易、模型调用 |
| `yudao-module-ai` 二开 | Prompt、Agent、槽位、运行时权限包、生成任务、候选、质量门控、评测、Tool Grant、Context Assembly、Candidate Decision Envelope | New-API 模型 Provider/供应商路由、成本策略、原始调用日志 authority、正文或知识 Canonical |
| `yudao-module-market` | 市场资产、授权、安装、Handoff、Precheck、发布申请、申诉、治理结果 | 作品正文事实、知识正式确认、Agent Slot Binding、Knowledge Source Binding、Block Source Attribution、支付清结算底层 |
| `yudao-module-account` 或改造 `member` | 个人资料、权益、配额、用量、购买/授权/发布记录总览 | 作品事实、市场资产 owner、New-API 原始调用日志或成本账本 authority |
建议决策:业务语义上使用 `account` 承载权益、配额、用量、授权和发布记录;`member` 先作为 Yudao 可复用底座保留隐藏。是否物理新增 `yudao-module-account`,还是在 `member` 内二开,需要在后端落地前单独确认。
物理落地约束:`account` 与 `member` 只能二选一承载 Muse 账户权益事实。选择前,文档和 API 使用逻辑名 `account`;选择后,另一个模块只能作为依赖或适配层,不得并行写 Profile、Entitlement、Quota、Usage Summary 或 Personal Center Summary。
### 3.2 标准模块结构
Muse 新模块继续按 Yudao 风格组织:
```text
yudao-module-xxx/
yudao-module-xxx-api/
admin/
app/
event/
yudao-module-xxx-server/
controller/admin/
controller/app/
application/
domain/
infrastructure/
```
约束:
- `yudao-module-xxx-api/admin` 与 `yudao-module-xxx-server/controller/admin` 服务管理后台,接口前缀归入 `/admin-api/**`。
- `yudao-module-xxx-api/app` 与 `yudao-module-xxx-server/controller/app` 服务用户端 `muse-studio`,接口前缀归入 `/app-api/**`。
- `yudao-module-xxx-api/event` 承载跨模块事件、outbox 消息、回调 DTO 和 facade DTO,不放领域事实。
- `domain` 持有聚合、不变式、领域服务和状态机判断,不能依赖 controller、Yudao Web DTO 或外部 API DTO。
- `application` 编排用例、事务、幂等、权限摘要、跨模块 facade 和 outbox。
- `infrastructure` 接数据库、Redis、MQ、文件、外部服务、Yudao 基础设施和 mapper。
- Controller 只做参数校验、权限入口和响应转换,不直接拼业务规则。
示例:
```text
yudao-module-content/
yudao-module-content-api/
admin/
app/
event/
yudao-module-content-server/
controller/admin/
controller/app/
application/
domain/
infrastructure/
```
禁止出现 `yudao-server/src/main/java/.../muse/...` 这类承载业务用例的过渡目录;如果为了启动聚合需要配置 Bean,只能在 `yudao-server` 做模块装配。
## 4. 模块边界
### 4.1 owner 边界
| 领域事实 | owner module | 可读协作者 |
|---|---|---|
| 用户、角色、权限、菜单 | `yudao-module-system` | 全部模块通过权限摘要或用户上下文读取 |
| 文件、配置、字典、任务、API 日志 | `yudao-module-infra` | 全部模块按 Yudao 基础设施方式调用 |
| 作品、章节、Block、正文版本、MetaSchema | `yudao-module-content` | knowledge、ai、market、account |
| 用户知识库、局域知识、知识草稿、来源绑定 | `yudao-module-knowledge` | content、ai、market |
| Prompt、Agent、任务、候选、质量门控、评测 | `yudao-module-ai` | content、knowledge、market、account |
| 市场资产、授权、安装、发布、申诉、治理、Handoff、Precheck 状态 | `yudao-module-market` | content、knowledge、ai、account |
| 权益、配额、用量、购买/授权/发布记录总览 | `yudao-module-account` 或 `member` | market、ai、personal center read model |
| Source Snapshot、Authorization Snapshot、Source Status Event、Source Propagation Target | 来源对象 owner + 授权签发 owner;横切表级 owner 跟随来源 owner,不归入 Knowledge 单模块 | content、knowledge、ai、market、account |
Source / Authorization Context 是横切上下文:来源 owner 负责发布 Source Status Event,受影响对象 owner 负责幂等消费、禁用新使用、标记需重验或刷新自己的读模型。Knowledge 只拥有知识来源绑定和知识投影,不拥有所有来源授权事实。
### 4.2 跨模块调用规则
| 场景 | 允许方式 | 禁止方式 |
|---|---|---|
| 查询摘要 | 通过 `api` facade、只读 query service 或事件投影读取 | 直接跨模块读写对方表并推断状态 |
| 写入事实 | 回到 owner module 的 application use case | 在调用方 mapper 里直接写对方事实 |
| 异步协作 | outbox event + 幂等 consumer + 可重试任务 | MQ 消费端无幂等直接改 Canonical |
| Handoff | market 只写 Authorization / Install / Handoff / Precheck 状态,目标 owner 消费预检并写自己的事实 | 市场模块直接写槽位、知识绑定、正文归因或作品正文 |
| Source Status Event | 来源 owner 发布事件,影响对象 owner 幂等处理 | 查询时临时拼状态但不落传播结果 |
### 4.3 禁止事项
- 不按 `admin` 和 `app` 复制两套领域服务。
- 不让管理后台 controller 直接写用户作品正文、知识事实或候选确认结果。
- 不让用户端 controller 直接修改 MetaSchema、系统 Prompt、系统 Agent、质量策略或市场治理结果。
- 不让 `yudao-server` 聚合层承载业务逻辑。
- 不让 `infra`、`system` 成为 Muse 业务事实的万能容器。
- 不把 New-API 的模型 Provider、供应商路由、分组限流、成本策略和原始调用日志复制成 Muse 本地 authority。
## 5. 外部集成边界
| 集成 | 后端定位 | 约束 |
|---|---|---|
| New-API | 外部模型网关 authority | Muse 只保存网关绑定引用、任务级摘要、调用归属、错误分类、幂等键和补偿状态;不保存密钥明文、完整 Prompt/Response、模型 Provider/供应商路由、成本策略或原始调用日志 authority |
| RAGFlow / GraphRAG | 检索和投影消费方 | 只能消费 Muse owner 模块中的正式事实或授权资料投影;不能反向决定作品事实 |
| 文件存储 | 走 Yudao infra 文件能力 | 导入、导出、市场素材、知识库资料都必须有 owner、权限、来源和清理策略 |
| Job / MQ | 走 Yudao framework/infra 能力 | AI 任务、投影、导出、评估、来源传播必须幂等、可重试、可审计 |
| Pay | 走 `yudao-module-pay` | 市场交易、套餐、充值启用时再接入;交易事实不混入 market asset owner |
| BPM | 走 `yudao-module-bpm` | 审核、申诉、合规流程复杂后启用;简单状态机先由对应领域 owner module 承载 |
## 6. 运行形态
阶段 7 默认采用 Yudao Cloud 聚合启动形态:
```text
yudao-gateway
-> yudao-server
-> yudao-module-system
-> yudao-module-infra
-> yudao-module-content
-> yudao-module-knowledge
-> yudao-module-ai
-> yudao-module-market
-> yudao-module-account/member
```
可以按模块边界演进到微服务,但阶段 7 文档不要求立即拆成多进程。无论单体聚合还是微服务,领域 owner、API 前缀、权限边界和事件合同保持不变。
## 7. 权限与入口
- 管理后台入口:`/admin-api/**`,由 Vben Admin 调用。
- 用户端入口:`/app-api/**`,由 `muse-studio` 调用。
- 网关和服务端均必须校验认证、权限、租户/用户上下文、作品访问权和业务前置条件。
- 前端隐藏菜单、默认隐藏模块或路由守卫只是体验边界,不是安全边界。
- 系统任务必须使用明确服务身份、权限范围和审计上下文,不得伪装成普通用户确认正文、知识或候选。
## 8. 关联阅读
- 领域模型:`后端-01-领域模型与聚合设计.md`
- 流程与事务边界:`后端-03-关键流程实现与接口契约.md`
- 表结构:`后端-04-统一数据库Schema-v1.md`
- 接口契约:`后端-05-统一API契约-v1.md`
- 关键流程:`后端-03-关键流程实现与接口契约.md`
- Schema:`后端-04-统一数据库Schema-v1.md`
- API:`后端-05-统一API契约-v1.md`
- 系统边界:`架构-01-系统全貌与边界上下文.md`
- AI 编排专题:`专题-03-AI编排上下文与质量评测实现规范.md`

View File

@ -1,202 +1,276 @@
# 后端-03:关键流程实现与接口契约
- 版本:v6
- 更新日期:2026-05-13
- 目标读者:后端/前端/架构
- 版本:v7
- 更新日期:2026-05-23
- 目标读者:后端 / 前端 / 架构 / 测试
- 阅读时间:30-50 分钟
- 边界说明:这里只讲关键链路、事务边界、失败模式和后端职责归属;精确 API(接口)路径、请求/响应字段、错误码与异步轮询契约统一以 `后端-05-统一API契约-v1.md` 为准。本文件描述目标后端行为,不代表当前代码都已实现。
- 边界说明:本文件只讲关键链路、事务边界、失败模式和后端职责归属;精确路径、请求响应和错误码看 `后端-05`,状态机看 `架构-04`,工程模块看 `后端-02`。
## 1. 契约归属(别再两边各写一份)
## 1. 契约归属
后端文档分工如下:
阶段 7 后端文档分工:
| 文档 | 负责内容 |
|---|---|
| `架构-02` | 模型级不变式:双轨、Revision、Meta-driven(元结构驱动)、全局/局域知识边界、用户可见投影 |
| `流程-02A/02B` | 系统链路、事件触发关系、同步/异步边界 |
| `架构-04` | 精确状态机、表级约束、端点前后置条件 |
| `后端-04` | 精确 Schema(结构定义)、表结构职责、索引和待确认表 |
| `后端-05` | 精确 API(接口)分组、路径、请求/响应字段、错误码、轮询协议 |
| `后端-01` | 领域模型、聚合、owner module、不变式 |
| `后端-02` | Yudao Cloud fork 工程结构、保留/裁剪模块、Muse 模块职责 |
| `后端-03` | 关键流程、事务边界、异步边界、失败恢复 |
| `后端-04` | Muse 业务模块目标 Schema;Yudao 基础表只引用不重定义 |
| `后端-05` | `/admin-api/**` 与 `/app-api/**` API 契约 |
| `架构-04` | 状态机、前后置条件、硬约束 |
本文件只保留“为什么事务边界要这么切”和“哪类接口应该存在”的后端视角总结。
### 1.1 v1 接口面归纳
- Admin APIs:元数据、Prompt、Agent、全局知识库、访问策略、New-API 用户同步、评测集、用户、系统日志。
- User Workspace APIs:作品、章节、文本块、写作、作品规划、局域知识库、全局知识库授权检索、导入解析、导出交付、生成候选。
- Personal Center APIs:个人信息、Token 使用、生成记录总览、配额、套餐和授权摘要。
普通用户不能访问 Admin APIs;管理员配置接口也不能替普通用户写单个作品事实。精确路径、字段与错误结构统一看 `后端-05-统一API契约-v1.md`。
## 2. 导入事务边界(分阶段提交,方案 C)
导入是一次性动作,但必须允许部分失败可恢复,因此不要把导入做成一个巨型事务。
- 提交策略:先创建空 Work(作品),再逐章写入 Chapter(章节) / Block(文本块),每章独立提交。
- 失败处理:任一阶段失败,保留 Work 与已成功提交的章节/Block,并记录导入失败原因。用户可删除 Work 后重试。
- 不做:不覆盖、不追加、不续传、不从中断处继续。
导入正文可以初始化 Canonical(规范数据)正文;导入后的全书解析(Full Parse)结果仍必须进入 Shadow(待审层),等待章节级确认。
## 3. 待审对象与知识草稿
后端不引入 RawExtraction 一类对普通用户不可解释的长期概念。Active(活跃层) Shadow 与 Archive(归档层)的精确表结构统一看 `后端-04-统一数据库Schema-v1.md`。
- Suggestion(建议):对正文的候选内容。
- Proposal(提案) / Knowledge Draft(知识草稿):对知识、叙事状态或规划项的候选变更。
- Risk Markers(风险标记):冲突、过期、重复、来源失效、质量风险等说明。
知识草稿进入 Canonical 的最小条件:
- 有明确来源快照(Source Snapshot)。
- 未过期、未被替代、未被丢弃。
- 通过来源校验和必要冲突校验。
- 用户确认,或在原样接受建议时由后端按绑定关系同步确认且满足状态机约束。
## 4. 系统链路的后端职责
后端职责是让每阶段输出变成可恢复、可追溯的结果。
| 链路 | 后端职责 | 不允许 |
|---|---|---|
| 元数据与配置 | 保存 MetaSchema、MetaField、PromptVersion、AgentConfig、全局知识库授权、New-API 绑定、评测集等配置版本或变更记录 | 把配置散落在业务代码或普通用户作品数据里 |
| 上下文组装 | 从 Canonical 正文、正式作品知识、规划项、授权全局知识和配置快照组装 Context(上下文) | 把未确认草稿、未授权全局资料或过期投影当作事实 |
| 创作生成 | 创建 GenerationJob,调用外部 Agent 服务,成功后写 Suggestion 和必要知识草稿到 Shadow | 外部 AI 调用进入正文合并主事务 |
| 解析提取 | 以 ExtractionJob 从正文、候选、导入内容或规划项中提取知识草稿 | 提取失败回滚已保存正文 |
| 校验确认 | 做来源、冲突、去重和风险校验,最终仍以用户确认进入 Canonical | 后台绕过用户确认写正式作品知识 |
| 投影与记录 | 写 outbox、审计、任务记录和用户可见使用记录 | 投影失败反向覆盖事实源 |
补充硬约束:
- Accept Suggestion(接受建议)的事务语义分两条:
- 原样 Accept:Canonical 正文合并、待审对象迁 Archive、关联且未 stale 的知识草稿可同步确认入库、写审计和 outbox。
- 修改后合并:Canonical 正文合并、待审对象迁 Archive、旧 Draft 作废、写审计;新的知识草稿在事务提交后重新提取。
- `AFTER_COMMIT` 只负责触发异步消费,不负责补建主事务内必须完成的事实。
- 外部 AI、NER(命名实体识别)、提取、校验、投影或导出不得塞进 Canonical 合并主事务。
- `/ai/ner` 只是预览接口,不参与持久化写入。
- Stale draft 校验:Accept / 确认前校验 source snapshot,不匹配则拒绝确认。
- “修改后合并”不新增 Active 状态;旧 Draft 不得继续沿用。
## 5. 管理员配置变更如何影响生成链路
管理员(Admin)通过管理员控制台(Admin Console)修改系统能力时,后端必须把变更转成可追溯配置,而不是让运行链路读一堆可变全局变量。
## 2. API 入口分流
```text
管理员修改配置
-> 写入配置版本或变更记录
-> 激活或停用配置
-> 普通用户触发生成/提取/校验/规划
-> 权限校验
-> 读取配置快照
-> 组装上下文
-> 调用 Agent / New-API
-> 写任务状态、待审对象、审计和使用记录
Vben Admin -> /admin-api/** -> yudao-gateway -> yudao-server -> module controller/admin
muse-studio -> /app-api/** -> yudao-gateway -> yudao-server -> module controller/app
```
配置影响面:
约束:
| 配置 | 影响生成链路的位置 | 后端要求 |
- 管理后台只调用 `/admin-api/**`。
- 用户端只调用 `/app-api/**`。
- 两类入口可以调用同一个 application use case,但不能复制两套领域事实。
- 后端必须在 controller、application 和领域用例中做权限、owner、来源和状态校验。
## 3. 横切硬约束
阶段 7 后端实现必须先守住这些横切不变式,再拆具体接口:
| 约束 | 后端落点 | 不允许 |
|---|---|---|
| MetaSchema / MetaField | 规划表单、提取结构、校验规则、用户可见投影、上下文注入 | 可见性字段变化要触发投影重建或失效 |
| PromptVersion | 生成、提取、校验、规划和检索提示 | 任务记录必须能追溯使用的版本 |
| AgentConfig | Agent 启停、超时、重试、fallback 和能力路由 | 失败必须可恢复,不能直接污染正文或知识 |
| GlobalKnowledgeAccessPolicy | 全局知识库能否展示、检索或用于生成 | 默认不可越权使用;来源必须可区分 |
| NewApiUserBinding / NewApiPlanMapping | 用户是否可调用模型、分组、配额、套餐、绑定状态 | 同步必须幂等、可重试、可审计;模型供应商和成本日志仍以 New-API 为准 |
| EvaluationDataset / EvaluationRun | 系统质量评估和回归对比 | 评测结论不替代用户对正文和作品知识的确认 |
| 用户主权 | Content / Knowledge / AI application use case 强制校验用户决策 | AI、市场、管理员或系统任务替用户确认作品事实 |
| Shadow -> Canonical | AI 候选、知识草稿、规划候选先落 Shadow,再经用户决策进入 Canonical | 候选生成成功后直接写正文、正式知识或正式规划 |
| 保护节点 | Protected Node Registry 是唯一口径,至少包含 `input_compliance`、`output_compliance`、`permission_filter`、`audit`、`chunking`、`rag_ingest`、`semantic_guardrail`、`static_check`、`quality_gate`、`source_status_check`、`shadow_to_canonical` | 用户智能体、市场智能体或工作流智能体替换保护节点 |
| Handoff | market 只写 Authorization / Install / Handoff / Precheck 状态,目标 owner 消费预检后写自己的事实 | 市场安装/绑定直接写作品、知识、槽位或正文事实 |
| Source Status Event | 来源 owner 发布,受影响 owner 幂等处理 | 撤权、召回、blocked 后仍允许新生成、新确认、新绑定或受限导出 |
| Account read model | account 聚合权益、用量、授权和发布记录摘要 | account 反写作品、知识、智能体或市场事实 |
| New-API 边界 | Muse 只保存网关绑定引用、任务级摘要、调用归属、错误分类、幂等键和补偿状态 | Muse 成为模型 Provider、供应商路由、成本策略或原始调用日志 authority |
已启动任务必须使用启动时读取到的配置快照,中途不能混用新旧配置。配置回滚影响后续任务,不改写历史任务解释。
同步写入只覆盖用户确认、正文保存、知识确认、槽位绑定、知识绑定、Handoff/Precheck 消费等必须立即给出结果的 owner 事实。AI 调用、投影、索引、导出、评估、来源传播、New-API 归属和通知走异步任务,异步失败不得回滚已提交 Canonical。
## 6. 用户作品工作台所需后台能力
### 3.1 关键流程 owner / 幂等 / 状态边界
作品工作台(Work Workspace)不是单个编辑器接口,它需要一组后台能力共同支撑。
| 流程 | owner 边界 | 幂等键 | 状态边界 |
|---|---|---|---|
| 规划 | AI 只写 Planning Candidate;Content 只写用户确认后的 Planning Canonical | `workId + candidateId + decisionId` | candidate 过期、来源失效、版本冲突或质量门控 blocked 时不写 Canonical |
| 全书解析 | Content 拥有导入任务、解析任务和章节解析状态;Knowledge 只接收章节确认后的 Knowledge Draft | `workId + parseJobId + chapterId + reviewDecisionId` | 章节级失败可重试;章节确认不写 Local KB Canonical,只推进 Draft |
| 知识库 | Knowledge 拥有 KB、Knowledge Draft、Knowledge Source Binding 和投影状态 | `kbId + draftId + decisionId` 或 `kbId + sourceId + bindDecisionId` | 来源 revoked/recalled/blocked/owner_missing/unauthorized 时禁用新确认、新绑定和受限导出 |
| 市场资产使用 | Market 只写 Authorization、Install、Handoff、Precheck 状态;Content / Knowledge / AI 写目标事实 | `precheckId + targetOwner + targetId + action` | token 过期、已消费、来源变化、目标 owner 缺失或 feature gate 关闭时拒绝写入;market 通过事件刷新展示状态 |
| New-API 用量 | AI Task 记录网关调用引用和调用归属;Account 只做用户可见汇总;New-API 保持原始 authority | `aiTaskId + gatewayRequestId` | 超时、限流、余额不足、回调失败按任务重试或补偿;Muse 不补写 Provider、路由、成本和原始调用日志 |
### 6.1 作品规划数据保存
## 4. Accept Suggestion
- 作品设定、章节大纲、世界设定、角色关系、文风检查和章节叙事规划优先复用 MetaSchema、narrative_states、knowledge_entities、knowledge_relations 和 Work / Chapter 字段。
- 不为“作品设定 / 章节大纲 / 世界设定 / 角色关系 / 文风检查”每个 UI 面板新建孤立表。
- 规划项确认后才可作为后续生成上下文;来源和用户取舍必须可追溯。
Accept Suggestion 是正文候选进入正文 Canonical 的唯一合法入口。
### 6.2 AI 辅助规划生成
主事务必须完成:
- AI 生成、补全、整理、检查、给多组选项或从正文提取规划内容时,输出先进入 Shadow。
- 用户确认后,规划项才能写入对应 Canonical 载体或成为正式上下文。
- 章节叙事规划使用“情节节拍 / 场景推进”这类产品语言,但模型归入章节叙事规划,不引入小说场景(Scene)独立模型。
1. 校验用户对 Work / Chapter / Block / Suggestion 的权限。
2. 校验 Suggestion 仍处于 Active Shadow,未过期、未失效、未 blocked。
3. 校验 expectedRevision。
4. 校验 Candidate Decision Envelope,包含来源、授权、合规、质量、静态检查和市场作品资产 feature gate。
5. 写 Block 新 revision。
6. 写 Block Source Attribution。
7. 将 Suggestion 迁入 Archive。
8. 写审计、change log、outbox。
### 6.3 全局知识库授权检索
原样接受:
- 每次检索或生成前都必须校验 GlobalKnowledgeAccessPolicy。
- 返回结果必须标明来源是当前作品的局域知识库,还是被授权全局知识库。
- 全局知识库参与生成不等于写入局域知识库,除非用户后续确认成作品事实。
- 只写正文和候选归档。
- 关联 Knowledge Draft 继续保持待确认。
- 不自动写 Local KB。
- 不自动确认规划候选、知识草稿或来源绑定。
### 6.4 局域知识库自动维护
修改后合并:
- 触发源:正文保存、候选确认、规划确认、导入解析章节确认、手动知识修正。
- 自动提取结果仍是知识草稿;用户确认后才进入正式作品知识。
- 修改后合并、来源快照失效或章节确认失败时,不得把旧草稿写入局域知识库。
- 写用户最终正文。
- 旧 Knowledge Draft 立即失效。
- AFTER_COMMIT 触发重新提取。
- 上游 lineage、授权快照、许可限制和召回状态默认继承,不能被 `contentOverride` 洗白。
### 6.5 用户可见投影生成
失败边界:
- 用户可见投影(User-visible Projection)只展示元数据允许展示、编辑、检索、导出的实体、关系、字段和摘要。
- 投影不是事实源,不能反向覆盖 Canonical。
- 投影落后时,读路径需要水位标记、覆盖层或等价策略;投影失败必须可重试、可观察、可审计。
- 来源 revoked / recalled / blocked / owner_missing / unauthorized:候选 blocked 或 invalidated,不写正文。
- 市场作品资产缺 `workAssetUsePrecheckId` 或 feature gate:不写正文。
- revision 冲突:返回可恢复冲突信息,不静默覆盖。
- outbox 或投影失败:不得回滚已成功的正文主事务,但必须可重试、可观察、可审计。
### 6.6 用户使用日志
## 5. Knowledge Draft 确认
- 普通用户看到的是生成记录、任务记录、失败原因、Token 使用和成本提示。
- 管理员看到的是系统审计、任务失败、同步失败和运行观察。
- New-API 的模型消耗日志是权威来源;Muse 只保存与自身用户、作品、任务和授权相关的摘要或引用。
- 是否新增 `usage_logs` 独立表待 `后端-04` 确认;不能在 API 文档里先假定已经存在。
知识草稿确认由 `yudao-module-knowledge` owner 执行。
## 7. 外部集成边界
最小条件:
### 7.1 LLM(大语言模型)/模型网关与 Agent 服务
- 草稿仍 active,未过期、未失效。
- 来源快照、授权快照、source hash、目标版本仍有效。
- Source Status 不为 revoked、recalled、blocked、owner_missing、unauthorized。
- 用户对目标 Work / Local KB 有确认权限。
- 风险标记和冲突处理已完成或被用户显式处理。
调用链路:Muse 后端 → Agent 服务 → New-API → LLM。
确认结果:
- Muse 后端负责权限、配置快照、上下文组装、Agent Dispatcher 调用、结果消费、待审对象写入和任务状态。
- Agent 服务承载生成、提取、校验、规划、检索等能力执行。
- New-API 负责模型供应商、模型路由、用户分组限流、成本策略和消耗日志。
- 业务代码不直接依赖具体 LLM 厂商。
- 外部失败必须以可恢复错误暴露,不能吞错。
- 如果保留直连 New-API fallback,也只能作为 Agent 服务不可用时的降级路径,不改变 New-API 作为模型网关的职责。
- 写 Knowledge Canonical。
- 写 Knowledge Source Binding。
- 写知识变更历史。
- 写投影 outbox。
安全边界:
幂等与状态:
- Agent 服务和 Muse 后端部署在受信任后端边界内,不暴露公网。
- 如需传递用户级 New-API token,日志必须脱敏,不得持久化 token,不得把 token 传给除 New-API 以外的第三方。
- request_id / trace_id / user_id / work_id 全链路透传。
- Muse 记录任务级 usage summary、失败原因和同步状态;模型消耗明细以 New-API 为准。
- 确认按 `kbId + draftId + decisionId` 幂等;重复提交只能返回同一确认结果或当前状态。
- Draft 进入 confirmed、invalidated、blocked、superseded 后不得再次确认。
- 投影、索引或检索侧失败只改变 Projection State,不回写 Knowledge Canonical。
### 7.2 任务编排/检索(可选)
禁止:
如果引入 RAGFlow、Graph Query Provider 或任务编排工具:
- Accept Suggestion 自动确认知识草稿。
- 全书解析章节确认直接写正式知识。
- 管理员替用户确认单作品知识事实。
- 市场知识库安装、绑定或授权记录直接写 Local KB。
- 仍视为外部依赖,不可成为系统事实源。
- 任务编排工具只用于后台任务调度或检索链路编排,不引入通用工作流平台能力。
- 输入必须来自 Canonical 正文、正式作品知识、授权全局资料和可追溯配置快照。
- 失败模式必须明确:超时、限流、配额不足、不可用、投影落后。
- 投影失败不阻塞主事务,但必须可重试、可观察、可审计。
## 6. 导入解析与全书解析
## 8. 安全边界
导入正文:
### 8.1 API Key(接口密钥)管理
- 允许初始化 Work、Chapter、Block 的 Canonical 正文。
- 文件处理、章节拆分、失败记录可异步。
- 部分失败时保留已成功的章节和失败摘要,用户可删除后重试。
- 用户密钥必须以可撤销、可轮换为前提设计。
- 任何日志与错误返回中禁止泄露密钥。
- New-API 绑定状态、分组、配额、套餐同步失败要可重试、可审计。
全书解析:
### 8.2 用户隔离
```text
Import / Existing Blocks
-> Parse Job
-> Chapter Parse Result
-> Chapter Review
-> Knowledge Draft
-> 用户知识确认
-> Local KB Canonical
```
- 所有资源访问都必须绑定用户、角色、作品和授权上下文。
- 普通用户不能访问管理员接口。
- 后端必须拒绝跨作品访问,不能靠前端隐藏按钮保证安全。
- 管理员不通过后台接口替普通用户确认候选、写正文或决定作品知识取舍。
约束:
## 9. 关联阅读
- Chapter Review 只表示章节解析结果进入后续知识草稿处理。
- 章节审阅不写 Local KB,不写 Narrative State。
- 拆分切块、静态检查、入 RAG 是保护节点,用户智能体不可替换。
- 批量选择和一键确认全部可确认章节只是操作效率,不允许跨章节半提交污染事实。
- 章节确认成功只产生或推进章节范围内的 Knowledge Draft;正式知识仍必须由用户在知识确认入口逐项确认或按明确批量确认规则确认。
- Content 记录 parse job、chapter result、review status 和失败摘要;Knowledge 只在章节确认后接收 draft 写入请求。
- 解析任务按 `workId + parseJobId + chapterId` 幂等;章节审阅按 `workId + parseJobId + chapterId + reviewDecisionId` 幂等。
## 7. AI 生成、解析和质量门控
AI 链路由 `yudao-module-ai` 二开承载。
```text
用户意图
-> 输入合规
-> 权限和来源预检
-> Agent Runtime Permission Envelope
-> Context Assembly
-> 开放槽位子智能体
-> Provisional Shadow Candidate
-> 静态检查 / 来源状态校验
-> Quality Gate
-> Output Compliance
-> Candidate Decision Envelope
-> 用户决策
```
后端职责:
- 固化 actor、work、agent version、slot、tool grant、context scope、budget、authorization snapshot。
- 只写 AI Task、Suggestion、Knowledge Draft、Planning Candidate、Risk Marker、Quality Result。
- 不直接写正文、正式规划或 Local KB。
- New-API 只作为外部模型网关;Muse 不保存密钥明文、完整 Prompt/Response、私有正文全文、模型 Provider、供应商路由、成本策略或原始调用日志 authority。
- Muse 侧只保存网关绑定引用、任务级摘要、调用归属、错误分类、幂等键和补偿状态。
- Agent Runtime Permission Envelope 必须由服务端生成和校验,不能接受前端或智能体自报权限。
- 质量门控可以阻断、标记风险或触发 Shadow 内有限重写,但不能替用户做接受、知识确认或规划确认。
## 8. 市场资产使用
市场资产使用必须走 handoff。
| 场景 | 预检 | 消费方 |
|---|---|---|
| 市场智能体关联作品槽位 | `agentSlotPrecheckId` | `yudao-module-ai` / Agent Slot Binding |
| 市场知识库绑定作品 | `kbBindPrecheckId` | `yudao-module-knowledge` |
| 市场作品资产作为参考或上下文 | `workAssetUsePrecheckId` | `yudao-module-content` / `yudao-module-ai` |
| 发布市场资产 | `marketPublishCheckId` | `yudao-module-market` |
阶段 7 默认:作品资产 feature gate 未开启前,只允许阅读、收藏和授权记录,不允许模板化、参考写入或进入 AI 上下文。
市场安装不等于绑定,绑定不等于写入作品事实。
handoff 处理规则:
1. 市场模块校验资产、许可、版本、治理状态和发起人后,只写 Authorization、Install、Handoff、Precheck 状态,并生成一次性 handoff token 或预检请求。
2. 目标 owner 模块重新校验 actor、owner、目标对象、动作、授权快照、来源状态、返回点和幂等键。
3. 目标 owner 完成用户确认后原子消费预检,并写自己的事实:Agent Slot Binding、Knowledge Source Binding、Block Source Attribution 或目标 owner 的使用状态。
4. token 缺失、已消费、过期、来源状态变化、目标 owner 不存在或 feature gate 关闭时拒绝写入,并返回 market 刷新状态。
5. market 只能通过目标 owner 事件或状态回执更新展示状态,不能补写目标事实。
## 9. 导出交付
导出由 Content / Knowledge / Market / Account 协作完成。
导出前必须重验:
- 用户对作品的权限。
- 导出范围。
- Block Source Attribution。
- Knowledge Source Binding。
- 市场资产授权和许可限制。
- 来源 revoked / recalled / blocked / owner_missing。
- 下载凭证有效期和访问主体。
导出任务异步执行,下载凭证短期有效。来源状态变化必须传播到导出任务和下载凭证,必要时禁用下载或要求重验。
## 10. 账户、权益和用量
Account/Member 只提供用户可见权益和汇总,不替代业务 owner。
- 配额和权益用于 AI 任务、市场安装、导出等前置检查。
- 用量记录来自 AI Task、New-API 网关调用引用、调用归属、市场交易、导出任务和审计摘要。
- New-API 的模型 Provider、供应商路由、成本策略和原始调用日志仍以 New-API 为准。
- AI Task 失败、超时、限流或回调失败时,Muse 只更新错误分类、幂等重试和补偿状态;Account 只刷新用户可见摘要。
- 个人中心只展示 read model 和跳转入口,不拥有作品、知识、市场资产事实。
## 11. Source Status Event
来源变化必须通过事件传播:
- AI Suggestion / Planning Candidate
- Knowledge Draft
- Chapter Parse Result
- Knowledge Source Binding
- Agent Slot Binding
- Installed Agent / Installed KB
- Running Task
- Export Task / Download Credential
- Personal Center Summary
- Marketplace / Publisher Record
传播失败时,新使用 fail-default 禁用,并提供治理重试入口。
事件最小合同:
| 字段 | 说明 |
|---|---|
| `eventId` | 幂等事件 ID |
| `sourceType` / `sourceId` / `sourceVersion` | 来源对象和版本 |
| `eventType` | `revoked` / `recalled` / `blocked` / `owner_missing` / `needs_recheck` / `delisted` 等 |
| `reasonCode` | 治理、授权、版本、权利、合规或处理失败原因 |
| `affectedScopes` | 候选、草稿、绑定、安装、运行任务、导出、下载、个人中心记录等影响范围 |
| `occurredAt` | 来源事件发生时间 |
| `idempotencyKey` | 来源 owner 生成的幂等键 |
处理结果不得改写已确认 Canonical。允许的动作是禁用新使用、标记需重验、作废未确认对象、取消或阻断运行中任务、失效下载凭证、刷新个人中心摘要和写审计。
## 12. 关联阅读
- 管理员系统流程:`流程-02A-管理员系统处理流程(系统视角).md`
- 普通用户系统流程:`流程-02B-普通用户系统处理流程(系统视角).md`
- 状态机与约束:`架构-04-状态机与约束清单.md`
- 统一数据库 Schema(结构定义):`后端-04-统一数据库Schema-v1.md`
- 统一 API(接口)契约:`后端-05-统一API契约-v1.md`
- Accept(接受)专题收束:`专题-01-正文建议接受(Accept Suggestion)实现规范.md`
- 状态机:`架构-04-状态机与约束清单.md`
- Accept 专题:`专题-01-正文建议接受(Accept Suggestion)实现规范.md`
- AI 编排专题:`专题-03-AI编排上下文与质量评测实现规范.md`
- 质量门控专题:`专题-04-生成质量门控与创作健康度设计方案`

File diff suppressed because it is too large Load Diff

View File

@ -1,671 +1,35 @@
-- ============================================================
-- Muse 完整数据库 Schema(当前实际状态,V1-V18 合并,S0-ID 前快照)
-- 生成日期:2026-04-22
-- 来源:services/muse-engine/.../db/migration/V1-V18
-- 说明:本文件合并所有 Flyway migration 的最终状态,
-- 包含完整字段注释和枚举值定义。
-- 仅反映已落地的表结构,不含 spec v7 待实现的新表/字段。
-- 本文件保留当前代码事实中的 UUID/BIGSERIAL/BIGINT ID。
-- 目标态业务 ID 已改为自定义字符串 ID,见 后端-04 的 S0-ID 决策。
-- Muse 后端-04a:完整建表 SQL(历史快照说明)
-- 更新日期:2026-05-23
-- 状态:阶段 7 已废弃为目标建表 SQL,禁止直接执行
-- ============================================================
CREATE EXTENSION IF NOT EXISTS pgcrypto;
-- 通用触发器函数:自动更新 updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- ============================================================
-- 1. Auth 域
-- ============================================================
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
status VARCHAR(32) NOT NULL DEFAULT 'active',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE users IS '用户主表';
COMMENT ON COLUMN users.id IS '用户 ID(UUID,应用层生成)';
COMMENT ON COLUMN users.email IS '登录邮箱,应用层统一 lower-case,全局唯一';
COMMENT ON COLUMN users.status IS '用户状态 ── active: 活跃 | pending_deletion: 待删除缓冲期';
COMMENT ON COLUMN users.deleted IS '软删除标记';
CREATE TRIGGER update_users_updated_at
BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE user_settings (
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
ai_settings JSONB NOT NULL DEFAULT '{}'::jsonb,
theme VARCHAR(16) NOT NULL DEFAULT 'light',
font_size INTEGER NOT NULL DEFAULT 15,
line_height DOUBLE PRECISION NOT NULL DEFAULT 1.85,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE user_settings IS '用户个性化设置';
COMMENT ON COLUMN user_settings.user_id IS '用户 ID,主键兼外键 → users.id';
COMMENT ON COLUMN user_settings.ai_settings IS 'AI 相关设置(JSONB):模型偏好、生成参数等,结构由前端定义';
COMMENT ON COLUMN user_settings.theme IS '界面主题 ── light: 浅色 | dark: 深色';
COMMENT ON COLUMN user_settings.font_size IS '编辑器字体大小(px),默认 15';
COMMENT ON COLUMN user_settings.line_height IS '编辑器行高倍数,默认 1.85';
-- ============================================================
-- 2. Content 域(创作容器)
-- ============================================================
CREATE TABLE works (
id BIGSERIAL PRIMARY KEY,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
title VARCHAR(255) NOT NULL,
description TEXT,
author VARCHAR(100),
genre VARCHAR(50),
status VARCHAR(20) NOT NULL DEFAULT 'DRAFT',
work_schema_id UUID,
imported_at TIMESTAMP,
import_error TEXT,
parse_status VARCHAR(20) NOT NULL DEFAULT 'NOT_PARSED',
parse_progress INTEGER,
parse_error TEXT,
parsed_at TIMESTAMP,
parse_job_id UUID,
parse_current_chapter VARCHAR(255),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE works IS '作品主表:一个用户可拥有多部作品';
COMMENT ON COLUMN works.id IS '作品 ID(BIGSERIAL 自增)';
COMMENT ON COLUMN works.user_id IS '所属用户 → users.id,RESTRICT 删除';
COMMENT ON COLUMN works.title IS '作品标题';
COMMENT ON COLUMN works.description IS '作品简介(可选)';
COMMENT ON COLUMN works.author IS '作者名(可选,用于导入场景)';
COMMENT ON COLUMN works.genre IS '题材/类型,如 玄幻、都市、科幻';
COMMENT ON COLUMN works.status IS '作品状态 ── DRAFT: 草稿 | IN_PROGRESS: 创作中 | COMPLETED: 已完成 | PUBLISHED: 已发布';
COMMENT ON COLUMN works.work_schema_id IS '绑定的作品级 MetaSchema ID → meta_schemas.id(scope=work)';
COMMENT ON COLUMN works.imported_at IS '导入完成时间;write-once 字段,只能从 NULL 写一次';
COMMENT ON COLUMN works.import_error IS '导入失败原因';
COMMENT ON COLUMN works.parse_status IS '全书解析状态 ── NOT_PARSED: 未解析 | QUEUED: 排队中 | PARSING: 解析中 | RETRYING: 重试中 | PARSED: 已完成 | PARSE_FAILED: 解析失败 | CANCELED: 已取消';
COMMENT ON COLUMN works.parse_progress IS '解析进度百分比(0-100),仅 PARSING 状态有意义';
COMMENT ON COLUMN works.parse_error IS '解析失败原因';
COMMENT ON COLUMN works.parsed_at IS '解析成功完成时间,仅 parse_status=PARSED 时非空';
COMMENT ON COLUMN works.parse_job_id IS '当前解析任务 ID(运行时状态)';
COMMENT ON COLUMN works.parse_current_chapter IS '当前正在解析的章节标识(运行时状态)';
CREATE INDEX idx_works_user_id ON works(user_id);
CREATE INDEX idx_works_deleted ON works(deleted);
CREATE INDEX idx_works_user_deleted_created ON works(user_id, created_at DESC) WHERE deleted = FALSE;
CREATE TRIGGER update_works_updated_at
BEFORE UPDATE ON works FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE chapters (
id BIGSERIAL PRIMARY KEY,
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
title VARCHAR(255) NOT NULL,
order_index INTEGER NOT NULL,
status VARCHAR(20) NOT NULL DEFAULT 'DRAFT',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE chapters IS '章节表:作品下的有序章节';
COMMENT ON COLUMN chapters.id IS '章节 ID(BIGSERIAL 自增)';
COMMENT ON COLUMN chapters.work_id IS '所属作品 → works.id,CASCADE 删除';
COMMENT ON COLUMN chapters.title IS '章节标题';
COMMENT ON COLUMN chapters.order_index IS '作品内排序序号(同 work_id 下唯一)';
COMMENT ON COLUMN chapters.status IS '章节状态 ── DRAFT: 草稿 | IN_PROGRESS: 创作中 | COMPLETED: 已完成';
CREATE INDEX idx_chapters_work_id ON chapters(work_id);
CREATE INDEX idx_chapters_order ON chapters(work_id, order_index);
CREATE TRIGGER update_chapters_updated_at
BEFORE UPDATE ON chapters FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE blocks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
chapter_id BIGINT NOT NULL REFERENCES chapters(id) ON DELETE CASCADE,
revision INTEGER NOT NULL DEFAULT 1,
content JSONB NOT NULL,
order_index INTEGER NOT NULL,
word_count INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE blocks IS '文本块表:章节内的最小编辑单元,正文唯一 Canonical 载体';
COMMENT ON COLUMN blocks.id IS 'Block ID(UUID)';
COMMENT ON COLUMN blocks.chapter_id IS '所属章节 → chapters.id,CASCADE 删除';
COMMENT ON COLUMN blocks.revision IS '乐观锁版本号,任何正文写操作必须基于此值,从 1 开始递增';
COMMENT ON COLUMN blocks.content IS '结构化文档内容(JSONB),Tiptap/ProseMirror 格式';
COMMENT ON COLUMN blocks.order_index IS '章节内排序序号';
COMMENT ON COLUMN blocks.word_count IS '当前 Block 字数';
CREATE INDEX idx_blocks_chapter_id ON blocks(chapter_id);
CREATE INDEX idx_blocks_order ON blocks(chapter_id, order_index);
CREATE INDEX idx_blocks_revision ON blocks(chapter_id, revision);
CREATE TRIGGER update_blocks_updated_at
BEFORE UPDATE ON blocks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 3. Knowledge 域(世界模型)
-- ============================================================
CREATE TABLE knowledge_entities (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
entity_type VARCHAR(32) NOT NULL,
entity_schema_id UUID,
attributes JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMP NOT NULL DEFAULT now(),
updated_at TIMESTAMP NOT NULL DEFAULT now(),
deleted BOOLEAN NOT NULL DEFAULT FALSE,
UNIQUE (work_id, name, entity_type)
);
COMMENT ON TABLE knowledge_entities IS '知识实体表:作品世界观中的角色、地点、物品等';
COMMENT ON COLUMN knowledge_entities.id IS '实体 ID(UUID)';
COMMENT ON COLUMN knowledge_entities.work_id IS '所属作品 → works.id,CASCADE 删除';
COMMENT ON COLUMN knowledge_entities.name IS '实体名称,同作品+类型下唯一';
COMMENT ON COLUMN knowledge_entities.entity_type IS '实体类型,如 character(角色)、location(地点)、item(物品)、功法、宗门 等,由 MetaSchema 定义';
COMMENT ON COLUMN knowledge_entities.entity_schema_id IS '绑定的实体 MetaSchema ID → meta_schemas.id(scope=entity)';
COMMENT ON COLUMN knowledge_entities.attributes IS '当前 Canonical 属性快照(JSONB),字段结构由绑定的 MetaSchema 约束';
CREATE INDEX idx_knowledge_entities_work_id ON knowledge_entities(work_id);
CREATE INDEX idx_knowledge_entities_type ON knowledge_entities(work_id, entity_type);
CREATE TABLE knowledge_relations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
source_entity_id UUID NOT NULL REFERENCES knowledge_entities(id) ON DELETE CASCADE,
target_entity_id UUID NOT NULL REFERENCES knowledge_entities(id) ON DELETE CASCADE,
relation_type VARCHAR(128) NOT NULL,
description TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
UNIQUE (work_id, source_entity_id, target_entity_id, relation_type),
CHECK (source_entity_id <> target_entity_id)
);
COMMENT ON TABLE knowledge_relations IS '知识关系表:实体之间的有向关系';
COMMENT ON COLUMN knowledge_relations.id IS '关系 ID(UUID)';
COMMENT ON COLUMN knowledge_relations.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN knowledge_relations.source_entity_id IS '起点实体 → knowledge_entities.id';
COMMENT ON COLUMN knowledge_relations.target_entity_id IS '终点实体 → knowledge_entities.id,不可与起点相同';
COMMENT ON COLUMN knowledge_relations.relation_type IS '关系类型,如 师徒、敌对、从属、位于 等,由 MetaSchema(scope=relation) 定义';
COMMENT ON COLUMN knowledge_relations.description IS '关系描述(可选)';
CREATE INDEX idx_knowledge_relations_work_id ON knowledge_relations(work_id);
CREATE INDEX idx_knowledge_relations_source ON knowledge_relations(work_id, source_entity_id);
CREATE TABLE knowledge_attribute_changes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
entity_id UUID NOT NULL,
attribute_key VARCHAR(128) NOT NULL,
old_value TEXT,
new_value TEXT NOT NULL,
source VARCHAR(64) NOT NULL,
changed_by UUID REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
COMMENT ON TABLE knowledge_attribute_changes IS '知识属性变更日志:记录实体属性的每次变更,不可变追加表';
COMMENT ON COLUMN knowledge_attribute_changes.id IS '变更记录 ID(UUID)';
COMMENT ON COLUMN knowledge_attribute_changes.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN knowledge_attribute_changes.entity_id IS '目标实体 ID → knowledge_entities.id(无外键约束,允许实体删除后保留日志)';
COMMENT ON COLUMN knowledge_attribute_changes.attribute_key IS '变更的属性键名';
COMMENT ON COLUMN knowledge_attribute_changes.old_value IS '变更前的值(首次设置时为 NULL)';
COMMENT ON COLUMN knowledge_attribute_changes.new_value IS '变更后的值';
COMMENT ON COLUMN knowledge_attribute_changes.source IS '变更来源 ── proposal_accept: 接受提案 | manual_edit: 手动编辑 | import: 导入';
COMMENT ON COLUMN knowledge_attribute_changes.changed_by IS '操作者 → users.id,系统操作时为 NULL';
CREATE INDEX idx_kac_entity_created ON knowledge_attribute_changes(entity_id, created_at DESC);
CREATE INDEX idx_kac_work_created ON knowledge_attribute_changes(work_id, created_at DESC);
-- ============================================================
-- 4. Meta 域(元数据管理)
-- ============================================================
CREATE TABLE meta_schemas (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT REFERENCES works(id) ON DELETE CASCADE,
schema_key VARCHAR(128) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
description TEXT,
scope VARCHAR(32) NOT NULL,
target_type VARCHAR(64) NOT NULL,
parent_schema_id UUID REFERENCES meta_schemas(id) ON DELETE SET NULL,
is_builtin BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE meta_schemas IS 'MetaSchema 定义表:定义作品/实体的属性字段结构,支持继承';
COMMENT ON COLUMN meta_schemas.id IS 'Schema ID(UUID)';
COMMENT ON COLUMN meta_schemas.work_id IS '所属作品 → works.id;NULL 表示系统内置或体裁模板(跨作品共享)';
COMMENT ON COLUMN meta_schemas.schema_key IS '稳定标识符,全局唯一,如 builtin_work_base、builtin_character_base';
COMMENT ON COLUMN meta_schemas.name IS '展示名称,如 作品模板、人物模板';
COMMENT ON COLUMN meta_schemas.description IS '描述(可选)';
COMMENT ON COLUMN meta_schemas.scope IS '作用域 ── work: 作品级 Schema | entity: 实体级 Schema';
COMMENT ON COLUMN meta_schemas.target_type IS '目标类型 ── scope=work 时: novel/short_story 等作品类型;scope=entity 时: character/location/item 等实体类型';
COMMENT ON COLUMN meta_schemas.parent_schema_id IS '父 Schema → meta_schemas.id,用于三层继承(系统内置 → 体裁模板 → 用户自定义)';
COMMENT ON COLUMN meta_schemas.is_builtin IS '是否系统内置模板(内置模板不可删除)';
CREATE INDEX idx_meta_schemas_work_id ON meta_schemas(work_id);
CREATE INDEX idx_meta_schemas_scope_target ON meta_schemas(scope, target_type);
CREATE TABLE meta_fields (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
schema_id UUID NOT NULL REFERENCES meta_schemas(id) ON DELETE CASCADE,
field_key VARCHAR(128) NOT NULL,
field_label VARCHAR(255) NOT NULL,
field_type VARCHAR(32) NOT NULL,
group_name VARCHAR(128) NOT NULL,
is_required BOOLEAN NOT NULL DEFAULT FALSE,
ai_context BOOLEAN NOT NULL DEFAULT FALSE,
enum_options JSONB,
order_index INTEGER NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE,
UNIQUE (schema_id, field_key),
UNIQUE (schema_id, order_index)
);
COMMENT ON TABLE meta_fields IS 'MetaSchema 字段定义表:Schema 下的具体属性字段';
COMMENT ON COLUMN meta_fields.id IS '字段 ID(UUID)';
COMMENT ON COLUMN meta_fields.schema_id IS '所属 Schema → meta_schemas.id';
COMMENT ON COLUMN meta_fields.field_key IS '字段键名,同 Schema 下唯一,如 name、gender、realm';
COMMENT ON COLUMN meta_fields.field_label IS '字段显示名,如 姓名、性别、境界';
COMMENT ON COLUMN meta_fields.field_type IS '字段类型 ── short_text: 短文本 | long_text: 长文本 | number: 数字 | enum: 单选枚举 | multi_select: 多选 | boolean: 布尔';
COMMENT ON COLUMN meta_fields.group_name IS '字段分组名,用于前端分组展示,如 基本信息、性格设定、能力设定';
COMMENT ON COLUMN meta_fields.is_required IS '是否必填';
COMMENT ON COLUMN meta_fields.ai_context IS '是否纳入 AI 上下文(true 时该字段值会注入生成 prompt)';
COMMENT ON COLUMN meta_fields.enum_options IS '枚举选项(JSONB 数组),仅 field_type=enum 或 multi_select 时有效,如 ["男","女","未知"]';
COMMENT ON COLUMN meta_fields.order_index IS '字段排序序号,同 Schema 下唯一';
CREATE INDEX idx_meta_fields_schema_id ON meta_fields(schema_id);
-- ============================================================
-- 5. AI 域:Job(异步任务)
-- ============================================================
CREATE TABLE generation_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
requested_by UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
target_block_id UUID NOT NULL REFERENCES blocks(id) ON DELETE CASCADE,
suggestion_type VARCHAR(32) NOT NULL,
context_block_ids JSONB NOT NULL DEFAULT '[]'::jsonb,
status VARCHAR(16) NOT NULL DEFAULT 'QUEUED',
pipeline_step VARCHAR(32),
suggestion_id UUID,
retry_count INTEGER NOT NULL DEFAULT 0,
error_code VARCHAR(64),
error_message TEXT,
started_at TIMESTAMPTZ,
finished_at TIMESTAMPTZ,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE generation_jobs IS '生成任务表:AI 文本生成的异步作业';
COMMENT ON COLUMN generation_jobs.id IS '任务 ID(UUID)';
COMMENT ON COLUMN generation_jobs.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN generation_jobs.requested_by IS '触发用户 → users.id';
COMMENT ON COLUMN generation_jobs.target_block_id IS '目标 Block → blocks.id';
COMMENT ON COLUMN generation_jobs.suggestion_type IS '建议类型 ── CONTINUATION: 续写 | REWRITE: 改写 | EXPAND: 扩写';
COMMENT ON COLUMN generation_jobs.context_block_ids IS '上下文 Block ID 列表(JSONB 数组)';
COMMENT ON COLUMN generation_jobs.status IS '作业状态 ── QUEUED: 排队中 | RUNNING: 执行中 | RETRYING: 重试中 | SUCCEEDED: 成功 | FAILED: 失败 | CANCELED: 已取消';
COMMENT ON COLUMN generation_jobs.pipeline_step IS 'Pipeline 内部步骤追踪(仅 status=RUNNING 时有意义,外部 API 不暴露)── generating: 生成中 | extracting: 提取中 | validating: 校验中 | risk_routing: 风险路由 | regenerating: 重新生成';
COMMENT ON COLUMN generation_jobs.suggestion_id IS '生成成功后关联的 Suggestion ID → suggestions.id';
COMMENT ON COLUMN generation_jobs.retry_count IS '已重试次数';
COMMENT ON COLUMN generation_jobs.error_code IS '失败错误代码';
COMMENT ON COLUMN generation_jobs.error_message IS '失败错误信息';
COMMENT ON COLUMN generation_jobs.started_at IS '开始执行时间';
COMMENT ON COLUMN generation_jobs.finished_at IS '完成时间(成功或失败)';
CREATE INDEX idx_generation_jobs_work_status ON generation_jobs(work_id, status, created_at DESC);
CREATE INDEX idx_generation_jobs_requested_by_created ON generation_jobs(requested_by, created_at DESC) WHERE deleted = FALSE;
CREATE INDEX idx_generation_jobs_work_created ON generation_jobs(work_id, created_at DESC) WHERE deleted = FALSE;
CREATE TABLE extraction_jobs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
source_suggestion_archive_id UUID UNIQUE REFERENCES suggestion_archive(id) ON DELETE CASCADE,
requested_by UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
status VARCHAR(16) NOT NULL,
error_message TEXT,
retry_count INTEGER NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE extraction_jobs IS '提取任务表:知识提取的异步作业';
COMMENT ON COLUMN extraction_jobs.id IS '任务 ID(UUID)';
COMMENT ON COLUMN extraction_jobs.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN extraction_jobs.source_suggestion_archive_id IS '来源建议归档 → suggestion_archive.id(Accept 后触发提取)';
COMMENT ON COLUMN extraction_jobs.requested_by IS '发起用户 → users.id';
COMMENT ON COLUMN extraction_jobs.status IS '作业状态 ── QUEUED: 排队中 | RUNNING: 执行中 | RETRYING: 重试中 | SUCCEEDED: 成功 | FAILED: 失败 | CANCELED: 已取消';
COMMENT ON COLUMN extraction_jobs.error_message IS '失败错误信息';
COMMENT ON COLUMN extraction_jobs.retry_count IS '已重试次数';
CREATE INDEX idx_extraction_jobs_work_status ON extraction_jobs(work_id, status, created_at DESC);
CREATE TRIGGER update_extraction_jobs_updated_at
BEFORE UPDATE ON extraction_jobs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 6. AI 域:Shadow Active(待审层)
-- ============================================================
CREATE TABLE suggestions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
target_block_id UUID NOT NULL REFERENCES blocks(id) ON DELETE CASCADE,
generation_job_id UUID REFERENCES generation_jobs(id) ON DELETE CASCADE,
suggestion_type VARCHAR(32) NOT NULL,
base_block_revision INTEGER NOT NULL,
content JSONB NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE suggestions IS '建议表(Shadow Active):AI 生成的待审文本建议,行存在即 pending_review';
COMMENT ON COLUMN suggestions.id IS '建议 ID(UUID)';
COMMENT ON COLUMN suggestions.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN suggestions.target_block_id IS '目标 Block → blocks.id';
COMMENT ON COLUMN suggestions.generation_job_id IS '来源生成任务 → generation_jobs.id(唯一索引,1:1 关系)';
COMMENT ON COLUMN suggestions.suggestion_type IS '建议类型 ── CONTINUATION: 续写 | REWRITE: 改写 | EXPAND: 扩写';
COMMENT ON COLUMN suggestions.base_block_revision IS '生成时绑定的 Block revision,用于乐观锁冲突检测';
COMMENT ON COLUMN suggestions.content IS '建议内容(JSONB),结构与 blocks.content 同型';
COMMENT ON COLUMN suggestions.expires_at IS '过期时间,过期后自动归档';
CREATE INDEX idx_suggestions_work_block ON suggestions(work_id, target_block_id, created_at DESC);
CREATE INDEX idx_suggestions_work_pending_created ON suggestions(work_id, expires_at, created_at DESC) WHERE deleted = FALSE;
CREATE UNIQUE INDEX uq_suggestions_generation_job_id ON suggestions(generation_job_id) WHERE generation_job_id IS NOT NULL;
CREATE TRIGGER update_suggestions_updated_at
BEFORE UPDATE ON suggestions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE proposals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
extraction_job_id UUID REFERENCES extraction_jobs(id) ON DELETE CASCADE,
parse_job_id UUID,
source_block_id UUID REFERENCES blocks(id) ON DELETE SET NULL,
suggestion_id UUID,
stage VARCHAR(16) NOT NULL DEFAULT 'raw',
proposed_data JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE proposals IS '知识提案表(Shadow Active):AI 提取的待审知识变更,终态迁入 proposal_archive';
COMMENT ON COLUMN proposals.id IS '提案 ID(UUID)';
COMMENT ON COLUMN proposals.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN proposals.extraction_job_id IS '来源提取任务 → extraction_jobs.id(可为 NULL,全书解析场景走 parse_job_id)';
COMMENT ON COLUMN proposals.parse_job_id IS '来源全书解析任务 ID(全书解析链路)';
COMMENT ON COLUMN proposals.source_block_id IS '来源 Block → blocks.id(编辑链路)';
COMMENT ON COLUMN proposals.suggestion_id IS '关联的 Suggestion ID(生成链路,Knowledge Draft 数据合同)';
COMMENT ON COLUMN proposals.stage IS '内部校验阶段 ── raw: 原始提取 | validated: 已校验';
COMMENT ON COLUMN proposals.proposed_data IS '提议写入的数据(JSONB),包含 proposal_type 和具体数据。proposal_type 值:create_entity(创建实体)| update_attribute(更新属性)| add_relation(添加关系)';
CREATE INDEX idx_proposals_work_created ON proposals(work_id, created_at DESC);
CREATE INDEX idx_proposals_work_stage_created ON proposals(work_id, stage, created_at DESC) WHERE deleted = FALSE;
CREATE INDEX idx_proposals_work_parse_job ON proposals(work_id, parse_job_id);
CREATE INDEX idx_proposals_suggestion_id ON proposals(suggestion_id) WHERE suggestion_id IS NOT NULL;
CREATE TRIGGER update_proposals_updated_at
BEFORE UPDATE ON proposals FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 7. AI 域:Archive(归档层)
-- ============================================================
CREATE TABLE suggestion_archive (
id UUID PRIMARY KEY,
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
target_block_id UUID NOT NULL,
suggestion_type VARCHAR(32) NOT NULL,
base_block_revision INTEGER NOT NULL,
original_content JSONB NOT NULL,
final_content JSONB,
disposition VARCHAR(16) NOT NULL,
archived_by UUID REFERENCES users(id) ON DELETE SET NULL,
archived_at TIMESTAMPTZ NOT NULL,
merged_block_id UUID,
merged_block_revision INTEGER,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE suggestion_archive IS '建议归档表:已完成审核的建议历史记录';
COMMENT ON COLUMN suggestion_archive.id IS '沿用原 Suggestion ID';
COMMENT ON COLUMN suggestion_archive.work_id IS '所属作品';
COMMENT ON COLUMN suggestion_archive.target_block_id IS '原目标 Block ID(快照,不设外键)';
COMMENT ON COLUMN suggestion_archive.suggestion_type IS '建议类型 ── CONTINUATION | REWRITE | EXPAND';
COMMENT ON COLUMN suggestion_archive.base_block_revision IS '生成时的 Block revision';
COMMENT ON COLUMN suggestion_archive.original_content IS '原始建议内容';
COMMENT ON COLUMN suggestion_archive.final_content IS '用户修改 Block 后合并时写入正文的最终内容快照(直接接受时为 NULL,仅用于归档/审计)';
COMMENT ON COLUMN suggestion_archive.disposition IS '终态 ── accepted: 已接受 | rejected: 已拒绝 | expired: 已过期';
COMMENT ON COLUMN suggestion_archive.archived_by IS '审核人 → users.id;系统过期时为 NULL';
COMMENT ON COLUMN suggestion_archive.archived_at IS '归档时间';
COMMENT ON COLUMN suggestion_archive.merged_block_id IS '接受后写入的 Block ID';
COMMENT ON COLUMN suggestion_archive.merged_block_revision IS '接受后 Block 的 revision';
CREATE INDEX idx_suggestion_archive_work ON suggestion_archive(work_id, archived_at DESC);
CREATE TABLE proposal_archive (
id UUID PRIMARY KEY,
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
extraction_job_id UUID,
parse_job_id UUID,
source_block_id UUID,
suggestion_id UUID,
stage VARCHAR(16) NOT NULL,
proposed_data JSONB NOT NULL DEFAULT '{}'::jsonb,
disposition VARCHAR(16) NOT NULL,
archived_by UUID REFERENCES users(id) ON DELETE SET NULL,
archived_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP NOT NULL,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE proposal_archive IS '提案归档表:已完成审核的知识提案历史记录';
COMMENT ON COLUMN proposal_archive.id IS '沿用原 Proposal ID';
COMMENT ON COLUMN proposal_archive.work_id IS '所属作品';
COMMENT ON COLUMN proposal_archive.extraction_job_id IS '来源提取任务 ID(快照)';
COMMENT ON COLUMN proposal_archive.parse_job_id IS '来源全书解析任务 ID(快照)';
COMMENT ON COLUMN proposal_archive.source_block_id IS '来源 Block ID(快照)';
COMMENT ON COLUMN proposal_archive.suggestion_id IS '关联的 Suggestion ID(快照)';
COMMENT ON COLUMN proposal_archive.stage IS '归档前的校验阶段 ── raw | validated';
COMMENT ON COLUMN proposal_archive.proposed_data IS '提议数据(JSONB 快照)';
COMMENT ON COLUMN proposal_archive.disposition IS '终态 ── accepted: 已接受 | rejected: 已拒绝 | expired: 已过期';
COMMENT ON COLUMN proposal_archive.archived_by IS '审核人 → users.id;系统过期时为 NULL';
COMMENT ON COLUMN proposal_archive.archived_at IS '归档时间';
CREATE INDEX idx_proposal_archive_work_archived ON proposal_archive(work_id, archived_at DESC);
CREATE INDEX idx_proposal_archive_work_disposition ON proposal_archive(work_id, disposition) WHERE deleted = FALSE;
-- ============================================================
-- 8. AI 域:Quota / Audit(配额与审计)
-- ============================================================
CREATE TABLE user_ai_quotas (
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
request_limit_per_24h INTEGER NOT NULL,
token_limit_per_24h BIGINT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE user_ai_quotas IS '用户级 AI 配额表';
COMMENT ON COLUMN user_ai_quotas.user_id IS '用户 ID → users.id';
COMMENT ON COLUMN user_ai_quotas.request_limit_per_24h IS '24 小时内最大请求次数';
COMMENT ON COLUMN user_ai_quotas.token_limit_per_24h IS '24 小时内最大 token 消耗量';
CREATE TRIGGER update_user_ai_quotas_updated_at
BEFORE UPDATE ON user_ai_quotas FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE work_ai_quotas (
work_id BIGINT PRIMARY KEY REFERENCES works(id) ON DELETE CASCADE,
request_limit_per_24h INTEGER NOT NULL,
token_limit_per_24h BIGINT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE work_ai_quotas IS '作品级 AI 配额表';
COMMENT ON COLUMN work_ai_quotas.work_id IS '作品 ID → works.id';
COMMENT ON COLUMN work_ai_quotas.request_limit_per_24h IS '24 小时内最大请求次数';
COMMENT ON COLUMN work_ai_quotas.token_limit_per_24h IS '24 小时内最大 token 消耗量';
CREATE TRIGGER update_work_ai_quotas_updated_at
BEFORE UPDATE ON work_ai_quotas FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TABLE model_call_audits (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
generation_job_id UUID NOT NULL REFERENCES generation_jobs(id) ON DELETE CASCADE,
requested_by UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
provider VARCHAR(32) NOT NULL,
model VARCHAR(128) NOT NULL,
operation VARCHAR(64) NOT NULL,
attempt_number INTEGER NOT NULL,
status VARCHAR(16) NOT NULL,
prompt_tokens INTEGER NOT NULL DEFAULT 0,
completion_tokens INTEGER NOT NULL DEFAULT 0,
total_tokens INTEGER NOT NULL DEFAULT 0,
latency_ms BIGINT NOT NULL DEFAULT 0,
estimated_cost NUMERIC(12,6) NOT NULL DEFAULT 0,
error_message TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE model_call_audits IS 'LLM 调用审计表:记录每次模型调用的详细信息';
COMMENT ON COLUMN model_call_audits.id IS '审计记录 ID(UUID)';
COMMENT ON COLUMN model_call_audits.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN model_call_audits.generation_job_id IS '关联生成任务 → generation_jobs.id';
COMMENT ON COLUMN model_call_audits.requested_by IS '触发用户 → users.id';
COMMENT ON COLUMN model_call_audits.provider IS '模型提供商,如 openai、anthropic';
COMMENT ON COLUMN model_call_audits.model IS '模型标识,如 gpt-4、claude-3-opus';
COMMENT ON COLUMN model_call_audits.operation IS '操作类型,如 generate_suggestion';
COMMENT ON COLUMN model_call_audits.attempt_number IS '本次调用是第几次尝试(从 1 开始)';
COMMENT ON COLUMN model_call_audits.status IS '调用结果 ── SUCCESS: 成功 | FAILED: 失败';
COMMENT ON COLUMN model_call_audits.prompt_tokens IS 'Prompt token 消耗量';
COMMENT ON COLUMN model_call_audits.completion_tokens IS 'Completion token 消耗量';
COMMENT ON COLUMN model_call_audits.total_tokens IS '总 token 消耗量';
COMMENT ON COLUMN model_call_audits.latency_ms IS '调用延迟(毫秒)';
COMMENT ON COLUMN model_call_audits.estimated_cost IS '估算费用(美元,6 位小数)';
COMMENT ON COLUMN model_call_audits.error_message IS '失败时的错误信息';
CREATE INDEX idx_model_call_audits_work_created ON model_call_audits(work_id, created_at DESC);
CREATE INDEX idx_model_call_audits_generation_job_created ON model_call_audits(generation_job_id, created_at DESC);
CREATE INDEX idx_model_call_audits_requested_by_created ON model_call_audits(requested_by, created_at DESC) WHERE deleted = FALSE;
CREATE TABLE audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
work_id BIGINT NOT NULL REFERENCES works(id) ON DELETE CASCADE,
entity_type VARCHAR(64) NOT NULL,
entity_id VARCHAR(128) NOT NULL,
action VARCHAR(64) NOT NULL,
user_id UUID NOT NULL REFERENCES users(id) ON DELETE RESTRICT,
payload JSONB,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE audit_logs IS '业务审计日志表:记录关键业务操作';
COMMENT ON COLUMN audit_logs.id IS '日志 ID(UUID)';
COMMENT ON COLUMN audit_logs.work_id IS '所属作品 → works.id';
COMMENT ON COLUMN audit_logs.entity_type IS '目标实体类型,如 SUGGESTION、PROPOSAL、BLOCK、KNOWLEDGE_ENTITY';
COMMENT ON COLUMN audit_logs.entity_id IS '目标实体 ID(字符串,兼容 UUID 和 BIGINT)';
COMMENT ON COLUMN audit_logs.action IS '操作动作,如 ACCEPT_SUGGESTION、REJECT_SUGGESTION、CREATE_ENTITY、UPDATE_ATTRIBUTE';
COMMENT ON COLUMN audit_logs.user_id IS '操作者 → users.id';
COMMENT ON COLUMN audit_logs.payload IS '结构化上下文(JSONB),禁止写正文全文';
CREATE INDEX idx_audit_logs_work_created ON audit_logs(work_id, created_at DESC);
CREATE INDEX idx_audit_logs_work_entity_created ON audit_logs(work_id, entity_type, created_at DESC) WHERE deleted = FALSE;
CREATE TRIGGER update_audit_logs_updated_at
BEFORE UPDATE ON audit_logs FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- 9. Integration 域(外部集成)
-- ============================================================
CREATE TABLE newapi_user_bindings (
muse_user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
newapi_user_id INTEGER NOT NULL,
newapi_token_id INTEGER NOT NULL,
newapi_token_secret_encrypted TEXT NOT NULL,
status VARCHAR(32) NOT NULL,
last_synced_at TIMESTAMP,
last_sync_error TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted BOOLEAN NOT NULL DEFAULT FALSE
);
COMMENT ON TABLE newapi_user_bindings IS 'New-API 用户绑定表:Muse 用户与 New-API 账户的关联';
COMMENT ON COLUMN newapi_user_bindings.muse_user_id IS 'Muse 用户 ID → users.id';
COMMENT ON COLUMN newapi_user_bindings.newapi_user_id IS 'New-API 侧用户 ID';
COMMENT ON COLUMN newapi_user_bindings.newapi_token_id IS 'New-API 侧 Token ID';
COMMENT ON COLUMN newapi_user_bindings.newapi_token_secret_encrypted IS 'New-API Token 密文(AES 加密存储,运行时解密后通过 header 传给 Agent Service)';
COMMENT ON COLUMN newapi_user_bindings.status IS '绑定状态 ── ACTIVE: 正常 | SYNCING: 同步中 | ERROR: 异常';
COMMENT ON COLUMN newapi_user_bindings.last_synced_at IS '最后同步时间';
COMMENT ON COLUMN newapi_user_bindings.last_sync_error IS '最后同步错误信息';
CREATE INDEX idx_newapi_user_bindings_newapi_user_id ON newapi_user_bindings(newapi_user_id);
CREATE INDEX idx_newapi_user_bindings_status ON newapi_user_bindings(status);
CREATE TRIGGER update_newapi_user_bindings_updated_at
BEFORE UPDATE ON newapi_user_bindings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ============================================================
-- END OF CURRENT SCHEMA (V1-V18)
-- ============================================================
-- 以下表/字段属于 spec v7 S1-0 前置 migration,尚未落地:
-- 新增表:knowledge_events, projection_outbox, projection_watermarks, ragflow_id_mappings
-- 扩展字段:meta_schemas.domain, knowledge_relations.properties/since_chapter/until_chapter,
-- proposals.source_kind/source_ref_id/source_block_revision/source_content_hash
-- 新产品形态目标 Schema 尚未落地为 migration:
-- 倾向新增表:prompt_versions, agent_configs, newapi_plan_mappings,
-- global_knowledge_bases, global_knowledge_access_policies,
-- evaluation_datasets, evaluation_runs
-- 扩展字段:ui_visible, user_editable, user_searchable, exportable,
-- 以及任务来源与审计上下文字段
-- 待确认表:local_knowledge_bases, usage_logs
--
-- 重要结论:
-- 1. 本文件原内容来自旧 `services/muse-engine` Flyway V1-V18 合并快照,
-- 使用 UUID、BIGSERIAL、PostgreSQL JSONB、S0-ID 和旧自研单体口径。
-- 2. 阶段 7 的后端工程基线已调整为 `YunaiV/yudao-cloud` fork:
-- - 后端复用 Yudao Cloud 的 gateway、system、infra、framework、job、log、file、config 等能力。
-- - 管理后台调用 `/admin-api/**`。
-- - 用户端 `muse-studio` 调用 `/app-api/**`。
-- - Muse 业务表按 content、knowledge、ai、market、account 等模块新增。
-- 3. 因此,旧 SQL 不再是目标库的完整建表 SQL,也不能直接搬到 `yudao-cloud`。
--
-- 禁止用途:
-- - 不允许把本文件作为 `yudao-cloud` 目标库初始化脚本执行。
-- - 不允许以本文件的 UUID/BIGSERIAL/JSONB/S0-ID 设计反向覆盖 `后端-04`。
-- - 不允许在本文件上继续补旧 `muse-engine` 风格 DDL,然后声称已适配 Yudao。
--
-- 允许用途:
-- - 作为旧实现快照的迁移对照。
-- - 用于检查哪些旧字段语义需要在新 `后端-04` 中被保留、改名或废弃。
-- - 用于后续生成 Yudao migration 时做差异提醒。
--
-- 新目标 SQL 生成前置条件:
-- 1. `后端-04-统一数据库Schema-v1.md` 的模块 owner 和表清单确认。
-- 2. 确认 account 是新增 `yudao-module-account`,还是改造 `yudao-module-member`。
-- 3. 确认目标数据库类型、Yudao migration 工具、物理外键策略和多租户字段策略。
-- 4. 确认 JSON 字段的物理类型和 MyBatis TypeHandler。
-- 5. 按 Yudao 模块分别生成 migration,不再维护一个跨模块手写大 SQL。
--
-- 当前文件刻意不保留任何可执行 DDL,避免误建旧库。
-- ============================================================

File diff suppressed because it is too large Load Diff