docs: add backend rewrite governance and route index

This commit is contained in:
2026-04-22 18:51:29 +08:00
parent 7e49c3a3c6
commit 35958d5942
4 changed files with 324 additions and 19 deletions

View File

@@ -4,33 +4,39 @@
### Contract 与前端兼容
- [ ] 梳理当前 `packages/shared/src/contracts/*` 到 Rust DTO 的映射
- [ ] 设计 Rust 侧 contract 生成或手写策略
- [ ] 保持当前字段名、枚举值、响应结构稳定
- [ ] 为 breaking change 建立显式变更流程
- [x] 梳理当前 `packages/shared/src/contracts/*` 到 Rust DTO 的映射
- [x] 设计 Rust 侧 contract 生成或手写策略
- [x] 保持当前字段名、枚举值、响应结构稳定
- [x] 为 breaking change 建立显式变更流程
### SpacetimeDB schema 演进治理
- [ ] 约定 stable reducer 命名规则
- [ ] 约定 stable table 命名规则
- [ ] 约定列追加式演进规则
- [ ] 约定软删除而不是直接删表删列的场景
- [ ] 约定事件表与投影表拆分规则
- [x] 约定 stable reducer 命名规则
- [x] 约定 stable table 命名规则
- [x] 约定列追加式演进规则
- [x] 约定软删除而不是直接删表删列的场景
- [x] 约定事件表与投影表拆分规则
### 大对象与缓存治理
- [ ] 明确哪些内容入 OSS
- [ ] 明确哪些内容只存 SpacetimeDB 元数据
- [ ] 明确哪些内容允许短期本地缓存
- [ ] 明确 workflow cache 生命周期
- [x] 明确哪些内容入 OSS
- [x] 明确哪些内容只存 SpacetimeDB 元数据
- [x] 明确哪些内容允许短期本地缓存
- [x] 明确 workflow cache 生命周期
### 文档维护
- [ ] 每个阶段完成后同步更新设计文档
- [ ] 每个阶段完成后补一份落地记录
- [ ] 完成接口迁移后更新新的模块与 API 索引文档
- [x] 每个阶段完成后同步更新设计文档
- [x] 每个阶段完成后补一份落地记录
- [x] 完成接口迁移后更新新的模块与 API 索引文档
- [ ] `M4` 结构变更同步对齐 `docs/technical/RPG_ENTRY_RUNTIME_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md`
- [ ] `M5` 结构变更同步对齐 `docs/technical/CREATION_FLOW_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md`
- [x] `M5` 结构变更同步对齐 `docs/technical/CREATION_FLOW_CHAIN_REFACTOR_EXECUTION_PLAN_2026-04-21.md`
补充说明:
1. 横向治理规则已冻结在 [../docs/technical/BACKEND_REWRITE_CROSS_CUTTING_GOVERNANCE_2026-04-22.md](../docs/technical/BACKEND_REWRITE_CROSS_CUTTING_GOVERNANCE_2026-04-22.md)。
2. Rust 侧 96 条 Axum 路由索引已冻结在 [../docs/technical/RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md](../docs/technical/RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md)。
3. `M4` 当前仍存在 `runtime_story` 独立 crate 拆分工作区,结构文档对齐需等该拆分收口后再勾选。
## 2. 第一优先级建议执行顺序
@@ -44,13 +50,13 @@
## 3. 最终验收清单
- [ ] 当前 `96` 条后端接口已全部迁移或有兼容替代
- [x] 当前 `96` 条后端接口已全部迁移或有兼容替代
- [ ] 当前 `6` 个挂载面已全部迁移
- [ ] 当前 `12` 个内部模块已完成新架构落位
- [ ] Axum 已成为唯一 HTTP / SSE / 副作用边界
- [ ] SpacetimeDB 已成为唯一运行时状态真相源
- [ ] 阿里云 OSS 已成为唯一资产对象仓
- [ ] `M4` 已与 `rpgEntry / rpgSession / rpgRuntime / rpgRuntimeStory / rpgProfile` 主链口径一致
- [ ] `M5` 已与 `agent session -> result preview -> published profile` 主链口径一致
- [x] `M5` 已与 `agent session -> result preview -> published profile` 主链口径一致
- [ ] 前端主流程在不大改 UI 的前提下可跑通
- [ ] 能完成灰度切流,并保留可回退能力

View File

@@ -0,0 +1,138 @@
# 后端重写横向治理规则2026-04-22
更新时间:`2026-04-22`
## 1. 文档目标
本文件冻结 `SpacetimeDB + Axum + OSS` 后端重写收口阶段的横向规则,覆盖:
1. 前端 TypeScript contract 与 Rust DTO 的映射策略。
2. SpacetimeDB table / reducer / procedure 的演进规则。
3. 大对象、manifest、workflow cache 的存储边界。
4. 阶段文档与 API 索引的维护规则。
这些规则用于减少 M4/M5/M6/M7 后续并行推进时的 contract 漂移。
## 2. Contract 与前端兼容
### 2.1 映射原则
1. `packages/shared/src/contracts/*` 是前端消费 contract 的现有事实来源。
2. `server-rs/crates/shared-contracts/src/*.rs` 是 Rust `api-server` 返回 DTO 的事实来源。
3. 两侧字段名必须继续使用当前前端已消费的 JSON 命名,不因 Rust 字段命名风格改变外部 shape。
4. Rust DTO 必须通过 `serde(rename_all = "camelCase")`、显式 `rename` 或兼容枚举值保持旧 contract。
5. 临时兼容字段只能标记为 optional不能在没有迁移说明和测试前直接删除。
### 2.2 当前映射面
| 前端 contract | Rust DTO 模块 | 当前用途 |
| --- | --- | --- |
| `packages/shared/src/contracts/auth.ts` | `shared-contracts::auth` | 登录方式、用户信息、会话、审计、验证码与微信登录 |
| `packages/shared/src/contracts/runtime.ts` | `shared-contracts::runtime` | profile dashboard、play stats、wallet ledger、browse history、settings、inventory |
| `packages/shared/src/contracts/rpgRuntimeStoryAction.ts` | `shared-contracts::runtime_story` | runtime story action request / response、state resolve、view model |
| `packages/shared/src/contracts/rpgRuntimeStoryState.ts` | `shared-contracts::runtime_story` | runtime story state / presentation 兼容 |
| `packages/shared/src/contracts/rpgAgent*.ts` | `shared-contracts::runtime``custom_world` 相关 DTO | custom world agent session、message、operation、action |
| `packages/shared/src/contracts/rpgCreation*.ts` | `shared-contracts::runtime``custom_world` 相关 DTO | result preview、works、library、published profile |
| `packages/shared/src/contracts/common.ts` | `shared-contracts::api` | 统一 success / error envelope |
### 2.3 变更流程
1. 扩字段:先加 Rust optional 字段和 contract test再接前端消费。
2. 改字段语义:必须新增技术方案说明旧语义、新语义、迁移期兼容逻辑和回退方式。
3. 删字段或删枚举必须先证明前端调用、Node 兼容层、历史 fixture 和测试都不再消费。
4. breaking change 必须在任务清单和设计文档中显式标注,不允许只靠 PR diff 表达。
5. 所有 shared contract 变更至少运行 `cargo test -p shared-contracts --manifest-path server-rs/Cargo.toml`
## 3. SpacetimeDB Schema 演进治理
本节按 SpacetimeDB 约束执行:
1. reducer 是事务性写入口,不依赖 reducer 返回值读取数据。
2. reducer 必须确定性执行,不做网络、文件系统、外部随机数或时间副作用。
3. 客户端读取依赖 table / subscription / procedure 返回的显式 DTO不把 Axum 进程内缓存当真相。
4. 用户身份以后续接入 SpacetimeDB 直连时的 `ctx.sender()` 为准,不信任客户端传入 owner 字段。
### 3.1 命名规则
1. table 使用稳定单数 snake_case 名称,例如 `story_session``asset_object``custom_world_agent_session`
2. reducer 使用动作动词 + 领域对象,例如 `upsert_runtime_snapshot``confirm_asset_object``turn_in_quest`
3. 需要同步返回 DTO 的 procedure 统一使用 `_and_return``get_ / list_ / compile_` 语义。
4. public table 只暴露客户端确实需要订阅或查询的状态内部审计、token、风控等默认不 public。
5. event table 只用于事件广播,不替代持久状态表。
### 3.2 列演进规则
1. 优先追加 optional 字段,不直接改名、改类型或删除列。
2. 必须删除语义时,先软废弃字段并让读模型停止依赖,再在独立迁移窗口清理。
3. 状态类枚举新增值时,前端必须有 unknown / fallback 处理。
4. 需要唯一约束或索引时,先补设计文档说明查询路径,再改 schema。
5. 大规模重排表结构必须拆成新表 + 双写 / 读模型迁移,不在原表上做破坏性变更。
### 3.3 软删除规则
1. 用户可见业务实体优先使用 `status``deleted_at``archived_at` 表达生命周期。
2. 会话、作品、资产绑定、审计和任务记录默认不物理删除。
3. 物理删除只用于临时草稿、过期验证码、过期 OAuth state 等明确可丢弃数据。
4. 删除 reducer 必须写清是否幂等,重复调用不能造成不可恢复错误。
## 4. 大对象与缓存治理
### 4.1 OSS 存储边界
必须进入 OSS
1. 图片、视频、动作帧、封面图、场景图。
2. 大型 JSON manifest。
3. 角色工作流缓存 JSON。
4. 导入视频和生成过程草稿资源。
只进入 SpacetimeDB 元数据:
1. `bucket``object_key``asset_kind``content_type``content_length``content_hash``version`
2. `asset_entity_binding` 的业务实体、槽位、owner 和 profile 绑定关系。
3. AI task、asset task、publish gate 等状态字段。
4. 可用于列表和权限判断的轻量 summary。
### 4.2 本地缓存边界
1. 生产主链不得把仓库 `public/generated-*` 作为资产真相。
2.`/generated-*` 仅作为同源代理兼容路径,读取私有 OSS 对象。
3. 测试环境允许使用 `#[cfg(test)]` 内存兜底,但必须在文档中注明不进入生产链。
4. workflow cache 当前真相是 OSS JSON 草稿对象,不落本地文件。
5. 临时生成文件如需存在,必须限制在进程临时目录,并在任务完成后清理。
### 4.3 Manifest 与版本
1. 多文件资产集合使用 OSS manifest 表达,不重复新增结构化表,除非已证明查询需求需要。
2. `asset_object.version` 当前默认 `1`,版本升级必须说明兼容读取规则。
3. `content_hash` 可为空,但一旦用于去重,必须先补冲突处理和重算策略。
4. 强业务资产表只有在需要领域查询、审核、回滚或权限策略时再新增。
## 5. 文档维护规则
1. 工程修改必须同步对应阶段任务清单。
2. 新增或改变接口时,同步更新 [RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md](./RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md)。
3. 仍存在 Node 旧能力差异时,同步更新 [NODE_BACKEND_MODULE_AND_API_INDEX.md](./NODE_BACKEND_MODULE_AND_API_INDEX.md) 的过期说明或新增 Rust 侧补充索引。
4. M4 结构变更同步维护 RPG runtime 链路文档。
5. M5 结构变更同步维护 creation flow 链路文档。
6. M6 资产链路变更同步维护 OSS / asset_object / generated path 文档。
7. M7 切流相关变更同步维护部署、预检、smoke 与回滚文档。
## 6. 验收门禁
横向治理完成不等价于真实切流完成。当前可本地验收的门禁是:
1. `cargo check -p api-server --manifest-path server-rs/Cargo.toml`
2. `cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml`
3. `cargo test -p shared-contracts --manifest-path server-rs/Cargo.toml`
4. `cargo test -p api-server --manifest-path server-rs/Cargo.toml --no-run`
5. `node scripts/check-encoding.mjs ...`
真实切流前仍必须单独完成:
1. OSS 真实读写 smoke。
2. LLM / DashScope 真实生成 smoke。
3. 关键 SSE 接口联调。
4. SpacetimeDB publish / rollback 演练。
5. 灰度环境双跑对比。

View File

@@ -4,6 +4,8 @@
## 文档列表
- [RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md](./RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md):记录当前 Rust `api-server` 已挂载的 96 条 Axum 路由,按 auth、assets、runtime、custom world、story、generated path 等挂载面归类,用于对照 Node 能力基线与切流 smoke 清单。
- [BACKEND_REWRITE_CROSS_CUTTING_GOVERNANCE_2026-04-22.md](./BACKEND_REWRITE_CROSS_CUTTING_GOVERNANCE_2026-04-22.md):冻结后端重写收口阶段的横向治理规则,覆盖 TypeScript contract 到 Rust DTO 映射、SpacetimeDB schema 演进、大对象 / workflow cache 存储边界和文档维护门禁。
- [PLATFORM_LLM_TEXT_GATEWAY_DESIGN_2026-04-21.md](./PLATFORM_LLM_TEXT_GATEWAY_DESIGN_2026-04-21.md)`platform-llm` 文本模型网关首版设计,冻结 OpenAI 兼容 `/chat/completions`、SSE 增量解析、错误模型与重试边界。
- [API_SERVER_PLATFORM_LLM_PROXY_DESIGN_2026-04-21.md](./API_SERVER_PLATFORM_LLM_PROXY_DESIGN_2026-04-21.md)`api-server` 接入 `platform-llm` 的最小代理设计,冻结 `/api/llm/chat/completions` 的配置、状态注入与首版非流式兼容边界。
- [PHONE_SMS_LOGIN_STAGE_A_IMPLEMENTATION_2026-04-21.md](./PHONE_SMS_LOGIN_STAGE_A_IMPLEMENTATION_2026-04-21.md):冻结手机号验证码登录第一阶段的真实落地边界,明确游客兜底默认关闭、公开请求不污染登录态,以及 smoke 必须覆盖短信登录主链。

View File

@@ -0,0 +1,159 @@
# Rust API Server 路由索引2026-04-22
更新时间:`2026-04-22`
## 1. 文档目标
本文件记录当前 `server-rs/crates/api-server/src/app.rs` 中已挂载的 Rust Axum 路由面,用于对照 Node 后端 `96` 条路由能力基线。
本文件只做路由索引,不替代单个阶段的设计文档;接口字段、权限、错误模型仍以各阶段技术方案和 `shared-contracts` 为准。
## 2. 当前统计
当前 Rust `api-server``app.rs` 可抽取到 `96` 条路由:
1. 内部鉴权调试接口:`2` 条。
2. AI task 接口:`9` 条。
3. assets / OSS 接口:`15` 条。
4. auth 接口:`12` 条。
5. custom world / agent 接口:`23` 条。
6. llm proxy 接口:`1` 条。
7. profile / runtime profile 接口:`12` 条。
8. runtime story / story gameplay 接口:`15` 条。
9. legacy generated 静态路径兼容:`6` 条。
10. health check`1` 条。
## 3. 路由清单
### 3.1 内部鉴权调试
1. `GET /_internal/auth/claims`
2. `GET /_internal/auth/refresh-cookie`
### 3.2 AI Task
1. `POST /api/ai/tasks`
2. `POST /api/ai/tasks/{task_id}/start`
3. `POST /api/ai/tasks/{task_id}/cancel`
4. `POST /api/ai/tasks/{task_id}/complete`
5. `POST /api/ai/tasks/{task_id}/fail`
6. `POST /api/ai/tasks/{task_id}/chunks`
7. `POST /api/ai/tasks/{task_id}/references`
8. `POST /api/ai/tasks/{task_id}/stages/{stage_kind}/start`
9. `POST /api/ai/tasks/{task_id}/stages/{stage_kind}/complete`
### 3.3 Assets / OSS
1. `POST /api/assets/direct-upload-tickets`
2. `POST /api/assets/sts-upload-credentials`
3. `POST /api/assets/objects/confirm`
4. `POST /api/assets/objects/bind`
5. `GET /api/assets/read-url`
6. `POST /api/assets/character-visual/generate`
7. `GET /api/assets/character-visual/jobs/{task_id}`
8. `POST /api/assets/character-visual/publish`
9. `POST /api/assets/character-animation/generate`
10. `GET /api/assets/character-animation/jobs/{task_id}`
11. `POST /api/assets/character-animation/publish`
12. `POST /api/assets/character-animation/import-video`
13. `GET /api/assets/character-animation/templates`
14. `GET /api/assets/character-workflow-cache/{character_id}`
15. `GET / POST /api/assets/character-workflow-cache`
### 3.4 Auth
1. `GET /api/auth/login-options`
2. `GET /api/auth/me`
3. `POST /api/auth/logout`
4. `POST /api/auth/logout-all`
5. `GET /api/auth/sessions`
6. `POST /api/auth/refresh`
7. `POST /api/auth/phone/send-code`
8. `POST /api/auth/phone/login`
9. `GET /api/auth/wechat/start`
10. `GET /api/auth/wechat/callback`
11. `POST /api/auth/wechat/bind-phone`
12. `POST /api/auth/entry`
### 3.5 Custom World / Agent
1. `GET /api/runtime/custom-world-library`
2. `GET /api/runtime/custom-world-library/{profile_id}`
3. `POST /api/runtime/custom-world-library/{profile_id}/publish`
4. `POST /api/runtime/custom-world-library/{profile_id}/unpublish`
5. `GET /api/runtime/custom-world-gallery`
6. `GET /api/runtime/custom-world-gallery/{owner_user_id}/{profile_id}`
7. `GET /api/runtime/custom-world/works`
8. `POST /api/runtime/custom-world/agent/sessions`
9. `GET /api/runtime/custom-world/agent/sessions/{session_id}`
10. `POST /api/runtime/custom-world/agent/sessions/{session_id}/messages`
11. `GET /api/runtime/custom-world/agent/sessions/{session_id}/messages/stream`
12. `GET /api/runtime/custom-world/agent/sessions/{session_id}/operations/{operation_id}`
13. `GET /api/runtime/custom-world/agent/sessions/{session_id}/cards/{card_id}`
14. `POST /api/runtime/custom-world/agent/sessions/{session_id}/actions`
15. `POST /api/custom-world/entity`
16. `POST /api/runtime/custom-world/entity`
17. `POST /api/custom-world/scene-npc`
18. `POST /api/runtime/custom-world/scene-npc`
19. `POST /api/custom-world/scene-image`
20. `POST /api/custom-world/cover-image`
21. `POST /api/custom-world/cover-upload`
22. `POST /api/runtime/custom-world/cover-image`
23. `POST /api/runtime/custom-world/cover-upload`
### 3.6 LLM Proxy
1. `POST /api/llm/chat/completions`
### 3.7 Profile / Runtime Profile
1. `GET /api/profile/dashboard`
2. `GET /api/runtime/profile/dashboard`
3. `GET /api/profile/play-stats`
4. `GET /api/runtime/profile/play-stats`
5. `GET /api/profile/wallet-ledger`
6. `GET /api/runtime/profile/wallet-ledger`
7. `GET /api/profile/browse-history`
8. `GET /api/runtime/profile/browse-history`
9. `GET /api/profile/save-archives`
10. `GET /api/runtime/profile/save-archives`
11. `POST /api/profile/save-archives/{world_key}`
12. `POST /api/runtime/profile/save-archives/{world_key}`
### 3.8 Runtime Story / Gameplay
1. `POST /api/runtime/save/snapshot`
2. `GET /api/runtime/settings`
3. `GET /api/runtime/story/state/{session_id}`
4. `POST /api/runtime/story/state/resolve`
5. `POST /api/runtime/story/actions/resolve`
6. `POST /api/runtime/story/initial`
7. `POST /api/runtime/story/continue`
8. `POST /api/story/sessions`
9. `POST /api/story/sessions/continue`
10. `GET /api/story/sessions/{story_session_id}/state`
11. `POST /api/story/battles`
12. `POST /api/story/battles/resolve`
13. `GET /api/story/battles/{battle_state_id}`
14. `POST /api/story/npc/battle`
15. `GET /api/runtime/sessions/{runtime_session_id}/inventory`
### 3.9 Legacy Generated 路径
1. `GET /generated-character-drafts/{*path}`
2. `GET /generated-characters/{*path}`
3. `GET /generated-animations/{*path}`
4. `GET /generated-custom-world-scenes/{*path}`
5. `GET /generated-custom-world-covers/{*path}`
6. `GET /generated-qwen-sprites/{*path}`
### 3.10 Health
1. `GET /healthz`
## 4. 维护规则
1. 新增、删除或改名 Rust 路由时,必须同步更新本索引。
2. 如果 Node 后端 `NODE_BACKEND_MODULE_AND_API_INDEX.md` 的现役能力面发生变化,必须同时更新本索引与对应阶段任务清单。
3. 任何 breaking route change 都必须先更新阶段设计文档,再改代码。
4. 真实切流前,必须用本索引对照代理层、前端调用面和 smoke 清单,避免只完成编译而遗漏外部可访问路径。