From 7c844854c009de1e127ae7b3393b5d8e3b796bab Mon Sep 17 00:00:00 2001 From: kdletters Date: Mon, 20 Apr 2026 23:52:49 +0800 Subject: [PATCH] docs: initialize rewrite plan and freeze backend surfaces --- BACKEND_REWRITE_TASKLIST.md | 12 + .../00_MASTER_TASKLIST.md | 151 ++++ .../01_M0_M2_FOUNDATION_AND_AUTH.md | 152 ++++ .../02_M3_RUNTIME_PROFILE.md | 50 ++ .../03_M4_STORY_AND_GAMEPLAY.md | 59 ++ .../04_M5_CUSTOM_WORLD_AND_AGENT.md | 80 ++ .../05_M6_ASSETS_OSS_EDITOR.md | 84 ++ .../06_M7_TEST_DEPLOY_CUTOVER.md | 46 ++ .../07_CROSS_CUTTING_AND_ACCEPTANCE.md | 51 ++ ..._CAPABILITY_SURFACE_BASELINE_2026-04-20.md | 179 +++++ backend-rewrite-tasklist/README.md | 23 + docs/technical/README.md | 1 + ...M_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md | 745 ++++++++++++++++++ 13 files changed, 1633 insertions(+) create mode 100644 BACKEND_REWRITE_TASKLIST.md create mode 100644 backend-rewrite-tasklist/00_MASTER_TASKLIST.md create mode 100644 backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md create mode 100644 backend-rewrite-tasklist/02_M3_RUNTIME_PROFILE.md create mode 100644 backend-rewrite-tasklist/03_M4_STORY_AND_GAMEPLAY.md create mode 100644 backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md create mode 100644 backend-rewrite-tasklist/05_M6_ASSETS_OSS_EDITOR.md create mode 100644 backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md create mode 100644 backend-rewrite-tasklist/07_CROSS_CUTTING_AND_ACCEPTANCE.md create mode 100644 backend-rewrite-tasklist/M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md create mode 100644 backend-rewrite-tasklist/README.md create mode 100644 docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md diff --git a/BACKEND_REWRITE_TASKLIST.md b/BACKEND_REWRITE_TASKLIST.md new file mode 100644 index 00000000..1877d65e --- /dev/null +++ b/BACKEND_REWRITE_TASKLIST.md @@ -0,0 +1,12 @@ +# 后端重写任务清单入口 + +完整总纲与拆分后的任务文件已统一整理到根目录新建目录: + +- [backend-rewrite-tasklist/README.md](./backend-rewrite-tasklist/README.md) + +其中: + +- 总纲主清单:[backend-rewrite-tasklist/00_MASTER_TASKLIST.md](./backend-rewrite-tasklist/00_MASTER_TASKLIST.md) +- 阶段拆分文件入口:[backend-rewrite-tasklist/README.md](./backend-rewrite-tasklist/README.md) + +后续如继续细化任务,请优先在该目录内维护,避免根目录散落多份版本。 diff --git a/backend-rewrite-tasklist/00_MASTER_TASKLIST.md b/backend-rewrite-tasklist/00_MASTER_TASKLIST.md new file mode 100644 index 00000000..5b8edcf6 --- /dev/null +++ b/backend-rewrite-tasklist/00_MASTER_TASKLIST.md @@ -0,0 +1,151 @@ +# SpacetimeDB + Axum + 阿里云 OSS 后端重写任务总纲 + +日期:`2026-04-20` + +关联设计文档: + +- [../docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md](../docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md) +- [../docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md](../docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md) + +关联拆分任务: + +- [01_M0_M2_FOUNDATION_AND_AUTH.md](./01_M0_M2_FOUNDATION_AND_AUTH.md) +- [02_M3_RUNTIME_PROFILE.md](./02_M3_RUNTIME_PROFILE.md) +- [03_M4_STORY_AND_GAMEPLAY.md](./03_M4_STORY_AND_GAMEPLAY.md) +- [04_M5_CUSTOM_WORLD_AND_AGENT.md](./04_M5_CUSTOM_WORLD_AND_AGENT.md) +- [05_M6_ASSETS_OSS_EDITOR.md](./05_M6_ASSETS_OSS_EDITOR.md) +- [06_M7_TEST_DEPLOY_CUTOVER.md](./06_M7_TEST_DEPLOY_CUTOVER.md) +- [07_CROSS_CUTTING_AND_ACCEPTANCE.md](./07_CROSS_CUTTING_AND_ACCEPTANCE.md) + +## 0. 使用说明 + +这份总纲用于把控整体重写节奏,拆分文件用于落地执行。 + +执行原则: + +1. 第一阶段优先兼容当前 `/api/*`、`/healthz`、`/generated-*` 访问习惯。 +2. 不允许先删旧能力再补新能力,必须按能力面平移。 +3. 以当前 Node 后端 `96` 条路由、`6` 个挂载面、`12` 个模块为最低覆盖基线。 +4. 每个阶段完成后,都要形成可运行、可回归、可继续迭代的中间态。 + +## 1. 总体里程碑 + +- [ ] `M0`:冻结当前后端能力清单与迁移边界 +- [ ] `M1`:搭建 Rust 工作区、Axum 主入口与基础中间件 +- [ ] `M2`:完成鉴权、会话、JWT、refresh cookie 主链迁移 +- [ ] `M3`:完成 runtime snapshot / settings / profile 迁移 +- [ ] `M4`:完成 story action 主循环与核心 gameplay reducer 迁移 +- [ ] `M5`:完成 custom world / agent 主链迁移 +- [ ] `M6`:完成 assets / OSS / editor 主链迁移 +- [ ] `M7`:完成联调、回归、部署与切流准备 + +## 2. 阶段导航 + +### `M0 ~ M2` + +重点: + +1. 冻结能力清单 +2. 搭建 Rust workspace +3. 搭建 Axum 基础设施 +4. 迁移鉴权、会话、JWT、refresh cookie + +详见: + +- [01_M0_M2_FOUNDATION_AND_AUTH.md](./01_M0_M2_FOUNDATION_AND_AUTH.md) + +### `M3` + +重点: + +1. 迁移 runtime snapshot +2. 迁移 settings +3. 迁移 profile dashboard / browse history / save archive + +详见: + +- [02_M3_RUNTIME_PROFILE.md](./02_M3_RUNTIME_PROFILE.md) + +### `M4` + +重点: + +1. 迁移 story action 主循环 +2. 迁移 gameplay reducer +3. 兼容当前 story view model 与 state 恢复接口 + +详见: + +- [03_M4_STORY_AND_GAMEPLAY.md](./03_M4_STORY_AND_GAMEPLAY.md) + +### `M5` + +重点: + +1. 迁移传统 custom world 问答流 +2. 迁移 custom world library / gallery +3. 迁移 custom world agent 会话、消息、卡片、操作 + +详见: + +- [04_M5_CUSTOM_WORLD_AND_AGENT.md](./04_M5_CUSTOM_WORLD_AND_AGENT.md) + +### `M6` + +重点: + +1. 迁移 assets +2. 接入阿里云 OSS +3. 迁移 editor 读写能力 +4. 做旧静态资源路径兼容 + +详见: + +- [05_M6_ASSETS_OSS_EDITOR.md](./05_M6_ASSETS_OSS_EDITOR.md) + +### `M7` + +重点: + +1. 联调 +2. 回归 +3. 部署 +4. 观测 +5. 灰度切流 + +详见: + +- [06_M7_TEST_DEPLOY_CUTOVER.md](./06_M7_TEST_DEPLOY_CUTOVER.md) + +## 3. 横向专项 + +以下专项贯穿整个迁移期: + +1. contract 与前端兼容 +2. SpacetimeDB schema 演进治理 +3. 大对象与缓存治理 +4. 文档持续维护 + +详见: + +- [07_CROSS_CUTTING_AND_ACCEPTANCE.md](./07_CROSS_CUTTING_AND_ACCEPTANCE.md) + +## 4. 第一优先级建议执行顺序 + +1. 先做 `M0`,冻结基线,避免迁移过程中口径漂移。 +2. 再做 `M1 + M2`,先把 Axum 壳与鉴权打稳。 +3. 再做 `M3`,优先跑通快照、设置、profile。 +4. 再做 `M4`,把 story action 主循环真正迁走。 +5. 然后做 `M5`,迁 custom world 与 agent。 +6. 最后做 `M6 + M7`,收口 assets、editor、部署与切流。 + +## 5. 最终验收清单 + +- [ ] 当前 `96` 条后端接口已全部迁移或有兼容替代 +- [ ] 当前 `6` 个挂载面已全部迁移 +- [ ] 当前 `12` 个内部模块已完成新架构落位 +- [ ] Axum 已成为唯一 HTTP / SSE / 副作用边界 +- [ ] SpacetimeDB 已成为唯一运行时状态真相源 +- [ ] 阿里云 OSS 已成为唯一资产对象仓 +- [ ] 前端主流程在不大改 UI 的前提下可跑通 +- [ ] 能完成灰度切流,并保留可回退能力 diff --git a/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md b/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md new file mode 100644 index 00000000..5e7ba592 --- /dev/null +++ b/backend-rewrite-tasklist/01_M0_M2_FOUNDATION_AND_AUTH.md @@ -0,0 +1,152 @@ +# M0 ~ M2:基础设施与鉴权任务清单 + +## M0:冻结能力与重写边界 + +### 能力冻结 + +- [x] 整理当前后端 6 个挂载面并锁定为重写验收基线 + 交付物:[M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md](./M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md) +- [ ] 整理当前后端 96 条路由并生成一份“旧接口 -> 新实现”映射表 +- [ ] 整理当前 12 个内部模块并锁定迁移归属 +- [ ] 整理当前所有 SSE 接口与事件格式 +- [ ] 整理当前所有 `/generated-*` 静态资源前缀 +- [ ] 整理当前前端直接依赖的响应头、envelope、错误格式 + +### 仓库边界 + +- [ ] 确认 Rust 后端新目录名与根目录落位方案 +- [ ] 确认旧 `server-node/` 在迁移期继续保留,不提前删除 +- [ ] 确认前端第一阶段仍然只访问 Axum,不直连 SpacetimeDB +- [ ] 确认外部副作用统一收口在 Axum,不放进 SpacetimeDB 模块 + +### 交付物 + +- [ ] 新增“接口映射表”文档 +- [ ] 新增“模块迁移清单”文档 +- [ ] 新增“阶段验收矩阵”文档 + +## M1:Rust 工作区与 Axum 基础设施 + +### 工作区搭建 + +- [ ] 在根目录新增 `server-rs/` +- [ ] 创建 workspace `Cargo.toml` +- [ ] 创建 `crates/api-server` +- [ ] 创建 `crates/spacetime-module` +- [ ] 创建 `crates/application` +- [ ] 创建 `crates/domain` +- [ ] 创建 `crates/contracts` +- [ ] 创建 `crates/auth-service` +- [ ] 创建 `crates/oss-service` +- [ ] 创建 `crates/llm-service` +- [ ] 创建 `crates/spacetime-client` +- [ ] 创建 `crates/tests` + +### Axum 基础能力 + +- [ ] 搭建 `main.rs` / `Router` / `with_state` +- [ ] 接入统一配置加载 +- [ ] 接入统一日志与 tracing +- [ ] 接入 `request_id` 中间件 +- [ ] 接入统一错误处理中间件 +- [ ] 接入当前项目兼容的 response envelope +- [ ] 接入 `x-request-id` +- [ ] 接入 `x-api-version` +- [ ] 接入 `x-route-version` +- [ ] 接入 `x-response-time-ms` +- [ ] 实现 `/healthz` + +### 基础工程脚本 + +- [ ] 新增本地开发脚本 +- [ ] 新增测试脚本 +- [ ] 新增 lint / fmt / clippy / check 脚本 +- [ ] 新增 smoke 脚本 +- [ ] 新增 SpacetimeDB 本地开发脚本 + +### 阶段验收 + +- [ ] Axum 服务可独立启动 +- [ ] `/healthz` 返回与当前工程兼容 +- [ ] 基础 response envelope 与 request id 行为稳定 +- [ ] Rust workspace 能完整编译通过 + +## M2:鉴权、会话、JWT 与 refresh cookie + +### SpacetimeDB 身份表 + +- [ ] 设计 `user_account` +- [ ] 设计 `auth_identity` +- [ ] 设计 `refresh_session` +- [ ] 设计 `auth_audit_log` +- [ ] 设计 `auth_risk_block` +- [ ] 设计 `sms_auth_event` +- [ ] 设计 `wechat_auth_state` + +### Axum 鉴权服务 + +- [ ] 实现密码登录 +- [ ] 实现账号自动创建 / 幂等登录兼容策略 +- [ ] 实现 Bearer JWT 校验 +- [ ] 实现 refresh cookie 读取 +- [ ] 实现 refresh token 轮换 +- [ ] 实现会话吊销 +- [ ] 实现全端登出 +- [ ] 实现 `me` 查询 + +### 手机验证码登录 + +- [ ] 接入阿里云短信发送 adapter +- [ ] 实现发送验证码接口 +- [ ] 实现验证码校验接口 +- [ ] 实现手机号绑定 +- [ ] 实现手机号换绑 +- [ ] 实现发送频率限制 +- [ ] 实现验证码失败次数限制 +- [ ] 实现 captcha 触发逻辑 +- [ ] 实现风控封禁与解除 + +### 微信登录 + +- [ ] 接入微信 OAuth adapter +- [ ] 实现 `wechat/start` +- [ ] 实现 `wechat/callback` +- [ ] 实现微信身份绑定 +- [ ] 实现微信账号补绑手机号 +- [ ] 实现桌面端 / 微信内打开场景区分 + +### OIDC 与 SpacetimeDB 身份透传 + +- [ ] 设计 JWT claims +- [ ] 确认 `iss/sub/sid/provider/roles` 字段 +- [ ] 让 Axum 自身可校验 JWT +- [ ] 让 SpacetimeDB 可识别 Axum 签发的身份令牌 +- [ ] 验证 reducer / view 可读取用户身份上下文 + +### 当前接口兼容 + +- [ ] 兼容 `/api/auth/login-options` +- [ ] 兼容 `/api/auth/entry` +- [ ] 兼容 `/api/auth/me` +- [ ] 兼容 `/api/auth/logout` +- [ ] 兼容 `/api/auth/logout-all` +- [ ] 兼容 `/api/auth/refresh` +- [ ] 兼容 `/api/auth/sessions` +- [ ] 兼容 `/api/auth/sessions/:sessionId/revoke` +- [ ] 兼容 `/api/auth/audit-logs` +- [ ] 兼容 `/api/auth/risk-blocks` +- [ ] 兼容 `/api/auth/risk-blocks/:scopeType/lift` +- [ ] 兼容 `/api/auth/phone/send-code` +- [ ] 兼容 `/api/auth/phone/login` +- [ ] 兼容 `/api/auth/phone/change` +- [ ] 兼容 `/api/auth/wechat/start` +- [ ] 兼容 `/api/auth/wechat/callback` +- [ ] 兼容 `/api/auth/wechat/bind-phone` + +### 阶段验收 + +- [ ] 密码登录主链可用 +- [ ] refresh cookie 主链可用 +- [ ] 手机验证码主链可用 +- [ ] 微信登录主链可用 +- [ ] 所有旧鉴权接口可通过 contract 回归 diff --git a/backend-rewrite-tasklist/02_M3_RUNTIME_PROFILE.md b/backend-rewrite-tasklist/02_M3_RUNTIME_PROFILE.md new file mode 100644 index 00000000..9a2da5b2 --- /dev/null +++ b/backend-rewrite-tasklist/02_M3_RUNTIME_PROFILE.md @@ -0,0 +1,50 @@ +# M3:runtime snapshot / settings / profile 任务清单 + +## 1. SpacetimeDB 运行时主表 + +- [ ] 设计 `runtime_snapshot` +- [ ] 设计 `runtime_setting` +- [ ] 设计 `profile_dashboard_state` +- [ ] 设计 `profile_wallet_ledger` +- [ ] 设计 `profile_played_world` +- [ ] 设计 `profile_save_archive` +- [ ] 设计 `user_browse_history` + +## 2. 兼容快照策略 + +- [ ] 设计“领域表真相 + 兼容聚合快照”策略 +- [ ] 设计 snapshot projection 刷新机制 +- [ ] 迁移当前 snapshot hydration / normalize 规则 +- [ ] 迁移当前 save archive 聚合逻辑 +- [ ] 迁移当前 browse history 去重与排序逻辑 + +## 3. Axum facade + +- [ ] 兼容 `GET /api/runtime/save/snapshot` +- [ ] 兼容 `PUT /api/runtime/save/snapshot` +- [ ] 兼容 `DELETE /api/runtime/save/snapshot` +- [ ] 兼容 `GET /api/runtime/settings` +- [ ] 兼容 `PUT /api/runtime/settings` +- [ ] 兼容 `GET /api/runtime/profile/dashboard` +- [ ] 兼容 `GET /api/profile/dashboard` +- [ ] 兼容 `GET /api/runtime/profile/wallet-ledger` +- [ ] 兼容 `GET /api/profile/wallet-ledger` +- [ ] 兼容 `GET /api/runtime/profile/play-stats` +- [ ] 兼容 `GET /api/profile/play-stats` +- [ ] 兼容 `GET /api/runtime/profile/save-archives` +- [ ] 兼容 `GET /api/profile/save-archives` +- [ ] 兼容 `POST /api/runtime/profile/save-archives/:worldKey` +- [ ] 兼容 `POST /api/profile/save-archives/:worldKey` +- [ ] 兼容 `GET /api/runtime/profile/browse-history` +- [ ] 兼容 `POST /api/runtime/profile/browse-history` +- [ ] 兼容 `DELETE /api/runtime/profile/browse-history` +- [ ] 兼容 `GET /api/profile/browse-history` +- [ ] 兼容 `POST /api/profile/browse-history` +- [ ] 兼容 `DELETE /api/profile/browse-history` + +## 4. 阶段验收 + +- [ ] 登录用户可正常保存、读取、删除存档 +- [ ] 兼容路径与主路径返回一致 +- [ ] profile dashboard / browse history / save archive 行为一致 +- [ ] 前端当前恢复流程可在不改 UI 的前提下跑通 diff --git a/backend-rewrite-tasklist/03_M4_STORY_AND_GAMEPLAY.md b/backend-rewrite-tasklist/03_M4_STORY_AND_GAMEPLAY.md new file mode 100644 index 00000000..946c3911 --- /dev/null +++ b/backend-rewrite-tasklist/03_M4_STORY_AND_GAMEPLAY.md @@ -0,0 +1,59 @@ +# M4:story action 与 gameplay reducer 任务清单 + +## 1. SpacetimeDB gameplay 表 + +- [ ] 设计 `story_session` +- [ ] 设计 `story_event` +- [ ] 设计 `npc_state` +- [ ] 设计 `quest_record` +- [ ] 设计 `inventory_slot` +- [ ] 设计 `treasure_record` +- [ ] 设计 `battle_state` +- [ ] 设计 `player_progression` +- [ ] 设计 `chapter_progression` + +## 2. 核心 reducer + +- [ ] 设计 `resolve_story_action` +- [ ] 设计 `continue_story` +- [ ] 设计 `begin_story_session` +- [ ] 设计 `sync_runtime_snapshot_projection` +- [ ] 设计 `apply_quest_signal` +- [ ] 设计 `apply_inventory_mutation` +- [ ] 设计 `resolve_npc_interaction` +- [ ] 设计 `resolve_treasure_interaction` +- [ ] 设计 `resolve_combat_action` +- [ ] 设计 `update_progression_state` + +## 3. 迁移模块规则 + +- [ ] 迁移 `story` +- [ ] 迁移 `combat` +- [ ] 迁移 `inventory` +- [ ] 迁移 `npc` +- [ ] 迁移 `progression` +- [ ] 迁移 `quest` +- [ ] 迁移 `runtime-item` +- [ ] 迁移 `runtime` 的状态归一化规则 + +## 4. 兼容接口 + +- [ ] 兼容 `POST /api/runtime/story/actions/resolve` +- [ ] 兼容 `GET /api/runtime/story/state/:sessionId` +- [ ] 兼容 `POST /api/runtime/story/initial` +- [ ] 兼容 `POST /api/runtime/story/continue` + +## 5. ViewModel 兼容 + +- [ ] 兼容当前 `RuntimeStoryActionResponse` +- [ ] 兼容当前 `RuntimeStoryOptionView` +- [ ] 兼容当前 `interaction` 元数据 +- [ ] 兼容当前 battle / toast / patch 响应结构 +- [ ] 兼容当前 `currentStory` 回填逻辑 + +## 6. 阶段验收 + +- [ ] 当前前端 story 选项点击后可走新后端闭环 +- [ ] NPC / quest / treasure / combat 主循环行为不回退 +- [ ] `story state` 恢复链可用 +- [ ] 旧 Node 版 story route 回归用例完成平移 diff --git a/backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md b/backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md new file mode 100644 index 00000000..c167be35 --- /dev/null +++ b/backend-rewrite-tasklist/04_M5_CUSTOM_WORLD_AND_AGENT.md @@ -0,0 +1,80 @@ +# M5:custom world / gallery / agent 任务清单 + +## 1. SpacetimeDB custom world 表 + +- [ ] 设计 `custom_world_profile` +- [ ] 设计 `custom_world_session` +- [ ] 设计 `custom_world_agent_session` +- [ ] 设计 `custom_world_agent_message` +- [ ] 设计 `custom_world_agent_operation` +- [ ] 设计 `custom_world_draft_card` +- [ ] 设计 `custom_world_asset_link` +- [ ] 设计 `custom_world_gallery_entry` + +## 2. 传统 custom world 问答流 + +- [ ] 迁移 `create session` +- [ ] 迁移 `answer question` +- [ ] 迁移 `generate stream` +- [ ] 迁移 profile compile +- [ ] 迁移 library 存储与删除 +- [ ] 迁移 publish / unpublish +- [ ] 迁移 gallery 列表与详情 + +## 3. custom world agent 主链 + +- [ ] 迁移 session create +- [ ] 迁移 session snapshot +- [ ] 迁移 message submit +- [ ] 迁移 message stream +- [ ] 迁移 operation query +- [ ] 迁移 card detail +- [ ] 迁移 card update +- [ ] 迁移 draft foundation +- [ ] 迁移 entity generation +- [ ] 迁移 role asset sync + +## 4. Axum 编排层 + +- [ ] 接入 LLM 编排 +- [ ] 接入世界草稿编译 +- [ ] 接入角色 / 地点 / 场景 NPC 生成 +- [ ] 接入封面图生成 +- [ ] 接入场景图生成 +- [ ] 接入 OSS 对象写入与绑定 +- [ ] 接入 SSE 事件分发 + +## 5. 兼容接口 + +- [ ] 兼容 `/api/runtime/custom-world/sessions` +- [ ] 兼容 `/api/runtime/custom-world/sessions/:sessionId` +- [ ] 兼容 `/api/runtime/custom-world/sessions/:sessionId/answers` +- [ ] 兼容 `/api/runtime/custom-world/sessions/:sessionId/generate/stream` +- [ ] 兼容 `/api/runtime/custom-world-library` +- [ ] 兼容 `/api/runtime/custom-world-library/:profileId` +- [ ] 兼容 `/api/runtime/custom-world-library/:profileId/publish` +- [ ] 兼容 `/api/runtime/custom-world-library/:profileId/unpublish` +- [ ] 兼容 `/api/runtime/custom-world-gallery` +- [ ] 兼容 `/api/runtime/custom-world-gallery/:ownerUserId/:profileId` +- [ ] 兼容 `/api/runtime/custom-world/works` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions/:sessionId` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions/:sessionId/messages` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions/:sessionId/messages/stream` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions/:sessionId/actions` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions/:sessionId/operations/:operationId` +- [ ] 兼容 `/api/runtime/custom-world/agent/sessions/:sessionId/cards/:cardId` +- [ ] 兼容 `/api/custom-world/entity` +- [ ] 兼容 `/api/runtime/custom-world/entity` +- [ ] 兼容 `/api/custom-world/scene-npc` +- [ ] 兼容 `/api/runtime/custom-world/scene-npc` +- [ ] 兼容 `/api/custom-world/scene-image` +- [ ] 兼容 `/api/custom-world/cover-image` +- [ ] 兼容 `/api/custom-world/cover-upload` + +## 6. 阶段验收 + +- [ ] 传统 custom world 主链可用 +- [ ] custom world library / gallery 主链可用 +- [ ] custom world agent 主链可用 +- [ ] agent 会话、消息、卡片、操作不再依赖单大 JSON 会话体 diff --git a/backend-rewrite-tasklist/05_M6_ASSETS_OSS_EDITOR.md b/backend-rewrite-tasklist/05_M6_ASSETS_OSS_EDITOR.md new file mode 100644 index 00000000..38112571 --- /dev/null +++ b/backend-rewrite-tasklist/05_M6_ASSETS_OSS_EDITOR.md @@ -0,0 +1,84 @@ +# M6:assets / 阿里云 OSS / editor 任务清单 + +## 1. OSS 基础设施 + +- [ ] 创建 OSS bucket 方案 +- [ ] 设计对象键前缀 +- [ ] 设计 `object_key -> cdn_url` 解析策略 +- [ ] 设计 public / private 对象访问策略 +- [ ] 设计签名 URL 输出策略 +- [ ] 设计 `x-oss-meta-*` 元数据规范 +- [ ] 设计内容 hash / 版本字段规范 + +## 2. 上传与对象确认 + +- [ ] 实现浏览器 `PostObject` 直传签名接口 +- [ ] 实现 STS 临时授权接口 +- [ ] 实现服务端上传 helper +- [ ] 实现上传完成后的对象确认接口 +- [ ] 实现对象绑定业务实体 reducer + +## 3. 资产任务系统 + +- [ ] 设计 `asset_job` +- [ ] 设计 `asset_object` +- [ ] 设计 `asset_manifest` +- [ ] 设计 `character_visual_asset` +- [ ] 设计 `character_animation_asset` +- [ ] 设计 `scene_image_asset` +- [ ] 设计 `sprite_sheet_asset` + +## 4. 资产生成链路 + +- [ ] 迁移角色主形象生成 +- [ ] 迁移角色动作生成 +- [ ] 迁移动作模板查询 +- [ ] 迁移视频导入 +- [ ] 迁移工作流缓存 +- [ ] 迁移 Qwen 主图生成 +- [ ] 迁移 Qwen 整表生成 +- [ ] 迁移 Qwen 修帧 +- [ ] 迁移 Qwen 保存 +- [ ] 迁移场景图生成 +- [ ] 迁移封面图上传 + +## 5. 编辑器能力 + +- [ ] 迁移编辑器 JSON 读取 +- [ ] 迁移编辑器 JSON 保存 +- [ ] 迁移图标目录枚举 +- [ ] 开发态保留本地文件适配 +- [ ] 线上态评估对象化替代方案 + +## 6. 路径兼容 + +- [ ] 兼容 `/generated-character-drafts/*` +- [ ] 兼容 `/generated-characters/*` +- [ ] 兼容 `/generated-custom-world-scenes/*` +- [ ] 兼容 `/generated-qwen-sprites/*` + +## 7. 兼容接口 + +- [ ] 兼容 `/api/assets/character-visual/generate` +- [ ] 兼容 `/api/assets/character-visual/jobs/:taskId` +- [ ] 兼容 `/api/assets/character-visual/publish` +- [ ] 兼容 `/api/assets/character-animation/generate` +- [ ] 兼容 `/api/assets/character-animation/jobs/:taskId` +- [ ] 兼容 `/api/assets/character-animation/publish` +- [ ] 兼容 `/api/assets/character-animation/import-video` +- [ ] 兼容 `/api/assets/character-animation/templates` +- [ ] 兼容 `/api/assets/character-workflow-cache` +- [ ] 兼容 `/api/assets/character-workflow-cache/:characterId` +- [ ] 兼容 `/api/assets/qwen-sprite/master` +- [ ] 兼容 `/api/assets/qwen-sprite/sheet` +- [ ] 兼容 `/api/assets/qwen-sprite/frame-repair` +- [ ] 兼容 `/api/assets/qwen-sprite/save` +- [ ] 兼容 `/api/editor/catalog/items` +- [ ] 兼容 `/api/editor/json/:resourceId` + +## 8. 阶段验收 + +- [ ] 所有新生成资产都写入 OSS +- [ ] 前端仍能通过旧路径习惯访问资源 +- [ ] 资产任务状态可查询 +- [ ] 编辑器主链不依赖旧 Node 后端 diff --git a/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md b/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md new file mode 100644 index 00000000..318f84e4 --- /dev/null +++ b/backend-rewrite-tasklist/06_M7_TEST_DEPLOY_CUTOVER.md @@ -0,0 +1,46 @@ +# M7:联调、回归、部署与切流任务清单 + +## 1. 测试体系 + +- [ ] 为 Axum handler 补接口测试 +- [ ] 为 SpacetimeDB reducer 补规则测试 +- [ ] 为 view / projection 补数据一致性测试 +- [ ] 为 auth 主链补集成测试 +- [ ] 为 runtime snapshot 主链补集成测试 +- [ ] 为 story action 主链补集成测试 +- [ ] 为 custom world / agent 主链补集成测试 +- [ ] 为 assets / OSS 主链补集成测试 +- [ ] 为兼容 contract 补回归测试 + +## 2. 部署准备 + +- [ ] 设计 Axum 部署方式 +- [ ] 设计 SpacetimeDB 发布方式 +- [ ] 设计 OSS bucket / CDN / 域名方案 +- [ ] 设计环境变量清单 +- [ ] 设计灰度环境 +- [ ] 设计数据迁移脚本 +- [ ] 设计回滚策略 + +## 3. 观测能力 + +- [ ] 接入 tracing / request id / structured logs +- [ ] 接入慢请求追踪 +- [ ] 接入上游 LLM / OSS / 短信 / 微信失败日志 +- [ ] 接入关键 reducer 执行日志 +- [ ] 接入资产任务状态日志 + +## 4. 切流准备 + +- [ ] 准备旧 Node 与新 Rust 双跑窗口 +- [ ] 准备 API 对比脚本 +- [ ] 准备主流程 smoke 清单 +- [ ] 准备前端切换开关 +- [ ] 准备回退开关 + +## 5. 阶段验收 + +- [ ] 全链路 smoke 通过 +- [ ] 主流程回归通过 +- [ ] 关键 SSE 接口联调通过 +- [ ] 可在灰度环境完成切流 diff --git a/backend-rewrite-tasklist/07_CROSS_CUTTING_AND_ACCEPTANCE.md b/backend-rewrite-tasklist/07_CROSS_CUTTING_AND_ACCEPTANCE.md new file mode 100644 index 00000000..5e1bec03 --- /dev/null +++ b/backend-rewrite-tasklist/07_CROSS_CUTTING_AND_ACCEPTANCE.md @@ -0,0 +1,51 @@ +# 横向专项、执行顺序与最终验收 + +## 1. 横向专项任务 + +### Contract 与前端兼容 + +- [ ] 梳理当前 `packages/shared/src/contracts/*` 到 Rust DTO 的映射 +- [ ] 设计 Rust 侧 contract 生成或手写策略 +- [ ] 保持当前字段名、枚举值、响应结构稳定 +- [ ] 为 breaking change 建立显式变更流程 + +### SpacetimeDB schema 演进治理 + +- [ ] 约定 stable reducer 命名规则 +- [ ] 约定 stable table 命名规则 +- [ ] 约定列追加式演进规则 +- [ ] 约定软删除而不是直接删表删列的场景 +- [ ] 约定事件表与投影表拆分规则 + +### 大对象与缓存治理 + +- [ ] 明确哪些内容入 OSS +- [ ] 明确哪些内容只存 SpacetimeDB 元数据 +- [ ] 明确哪些内容允许短期本地缓存 +- [ ] 明确 workflow cache 生命周期 + +### 文档维护 + +- [ ] 每个阶段完成后同步更新设计文档 +- [ ] 每个阶段完成后补一份落地记录 +- [ ] 完成接口迁移后更新新的模块与 API 索引文档 + +## 2. 第一优先级建议执行顺序 + +1. 先做 `M0`,冻结基线,避免迁移过程中口径漂移。 +2. 再做 `M1 + M2`,先把 Axum 壳与鉴权打稳。 +3. 再做 `M3`,优先跑通快照、设置、profile。 +4. 再做 `M4`,把 story action 主循环真正迁走。 +5. 然后做 `M5`,迁 custom world 与 agent。 +6. 最后做 `M6 + M7`,收口 assets、editor、部署与切流。 + +## 3. 最终验收清单 + +- [ ] 当前 `96` 条后端接口已全部迁移或有兼容替代 +- [ ] 当前 `6` 个挂载面已全部迁移 +- [ ] 当前 `12` 个内部模块已完成新架构落位 +- [ ] Axum 已成为唯一 HTTP / SSE / 副作用边界 +- [ ] SpacetimeDB 已成为唯一运行时状态真相源 +- [ ] 阿里云 OSS 已成为唯一资产对象仓 +- [ ] 前端主流程在不大改 UI 的前提下可跑通 +- [ ] 能完成灰度切流,并保留可回退能力 diff --git a/backend-rewrite-tasklist/M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md b/backend-rewrite-tasklist/M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md new file mode 100644 index 00000000..b4c964e9 --- /dev/null +++ b/backend-rewrite-tasklist/M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md @@ -0,0 +1,179 @@ +# M0:后端挂载面冻结基线 + +日期:`2026-04-20` + +依据来源: + +- [../docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md](../docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md) +- [../server-node/manifests/backend-capability-index.json](../server-node/manifests/backend-capability-index.json) + +## 1. 文档目的 + +这份文档用于完成 `M0` 的第一条任务: + +- 整理当前后端 `6` 个挂载面并锁定为重写验收基线 + +这里的“冻结”不是要求新后端永远维持原实现,而是要求: + +1. 新后端第一阶段必须完整覆盖这 `6` 个挂载面。 +2. 每个挂载面的入口职责、路径空间、权限模式、主要边界不能丢。 +3. 允许内部实现从 `Express + PostgreSQL + 本地 public/generated-*` 重写为 `Axum + SpacetimeDB + 阿里云 OSS`,但不允许把挂载面职责打散到无法对照验收。 + +## 2. 冻结结论 + +当前 Node 后端的正式挂载面固定为以下 `6` 个: + +| 挂载面 ID | 中文名称 | 当前路由数 | 当前入口 | 必须保留的顶层路径 | +| --- | --- | --- | --- | --- | +| `assets` | 资产生成工具面 | `14` | `server-node/src/app.ts -> /api/assets` | `/api/assets/*` | +| `auth` | 鉴权与会话面 | `17` | `server-node/src/app.ts -> /api/auth` | `/api/auth/*` | +| `editor` | 编辑器工具面 | `3` | `server-node/src/app.ts -> /api/editor` | `/api/editor/*` | +| `health` | 基础健康检查 | `1` | `server-node/src/app.ts -> /healthz` | `/healthz` | +| `runtime-main` | 运行时主能力面 | `59` | `server-node/src/app.ts -> /api` | `/api/runtime/*`、`/api/profile/*`、`/api/custom-world/*`、`/api/llm/*`、`/api/ws/*` | +| `runtime-story-action` | 运行时 Story Action 面 | `2` | `server-node/src/app.ts -> /api/runtime/story` | `/api/runtime/story/*` | + +冻结总数: + +1. 对外挂载面:`6` +2. 已登记路由:`96` +3. 公开接口:`10` +4. JWT 接口:`69` +5. 开关控制接口:`17` +6. 流式接口:`6` + +## 3. 各挂载面冻结要求 + +### 3.1 `assets` + +当前定位: + +1. 角色主形象生成 +2. 角色动作生成 +3. Qwen 精灵表生成与保存 +4. 工作流缓存 +5. 产物发布到 `public/generated-*` + +重写后的冻结要求: + +1. 仍保留独立的 `/api/assets/*` 命名空间。 +2. 仍保留“生成任务、任务状态查询、发布/保存”三类操作语义。 +3. 当前基于本地 `public/generated-*` 的产物落地,可改为 `OSS + 元数据表`,但前端一阶段必须继续通过原有路径习惯访问资源。 +4. 当前 `ASSETS_API_ENABLED` 门禁能力必须保留。 + +### 3.2 `auth` + +当前定位: + +1. 本地账号登录 +2. 手机验证码登录 +3. 微信登录 +4. refresh session +5. 会话吊销 +6. 审计与风控 + +重写后的冻结要求: + +1. 仍保留独立的 `/api/auth/*` 命名空间。 +2. 仍保留当前 `JWT + refresh cookie` 双令牌模型。 +3. 仍保留 `password / phone / wechat` 三类登录能力面。 +4. 仍保留审计日志、风控封禁、会话列表与会话吊销能力。 + +### 3.3 `editor` + +当前定位: + +1. 编辑器 JSON 读取 +2. 编辑器 JSON 回写 +3. 图标目录枚举 + +重写后的冻结要求: + +1. 仍保留独立的 `/api/editor/*` 命名空间。 +2. 仍保留 `EDITOR_API_ENABLED` 开关门禁。 +3. 开发态允许继续对本地工作区做读写适配,生产态可重构为对象化资源方案,但接口职责不能消失。 + +### 3.4 `health` + +当前定位: + +1. 提供后端进程健康探针 +2. 为代理层与 smoke 提供最小可用确认 + +重写后的冻结要求: + +1. 仍保留 `/healthz`。 +2. 仍返回简单、无鉴权、无数据库强耦合的健康状态。 +3. 仍可作为 smoke 与部署探针的第一检查点。 + +### 3.5 `runtime-main` + +当前定位: + +1. 运行时存档、设置、个人档案 +2. 聊天、剧情、任务、运行时物品意图 +3. custom world library / gallery / sessions +4. custom world agent 会话、消息、操作 + +重写后的冻结要求: + +1. 仍保留运行时主入口作为最大能力面,不把这些能力拆散到前端无法感知的新命名空间。 +2. 仍兼容当前: + - `/api/runtime/*` + - `/api/profile/*` + - `/api/custom-world/*` + - `/api/llm/*` + - `/api/ws/*` +3. 除公开画廊与少量公开接口外,仍以登录态为默认访问前提。 +4. 当前大量业务逻辑虽然会迁到 `SpacetimeDB reducer/view + Axum facade`,但对前端看起来仍应是一个统一运行时能力面。 + +### 3.6 `runtime-story-action` + +当前定位: + +1. story choice 动作解析 +2. story session 状态恢复 + +重写后的冻结要求: + +1. 仍保留 `/api/runtime/story/*` 作为独立挂载面。 +2. 仍保持“前端动作输入 -> 后端统一结算 -> 返回新状态”的接口职责。 +3. 当前 `storyActionService` 里跨 `quest / inventory / runtime-item / npc / progression / combat / runtime` 的协作,迁移后必须继续存在,只是实现位置改到 `SpacetimeDB + Axum`。 + +## 4. 挂载面与新架构映射 + +| 当前挂载面 | 新架构主归属 | 说明 | +| --- | --- | --- | +| `assets` | `Axum + OSS + SpacetimeDB asset metadata` | 外部副作用在 Axum,二进制在 OSS,任务与引用状态在 SpacetimeDB。 | +| `auth` | `Axum auth-service + SpacetimeDB auth tables` | 登录副作用与 cookie/JWT 在 Axum,身份与会话状态在 SpacetimeDB。 | +| `editor` | `Axum editor facade` | 开发态保留本地文件适配,后续再逐步对象化。 | +| `health` | `Axum health route` | 维持最小化健康检查面。 | +| `runtime-main` | `Axum runtime facade + SpacetimeDB runtime/custom-world tables` | Axum 维持兼容 REST/SSE,SpacetimeDB 负责状态真相。 | +| `runtime-story-action` | `Axum story facade + SpacetimeDB gameplay reducers/views` | Story Action 入口继续独立存在,但结算内核迁到新状态层。 | + +## 5. 本轮冻结后的硬约束 + +后续迁移中,不允许出现以下情况: + +1. 把 `6` 个挂载面减少成更少但无法一一对照的“超级入口”。 +2. 把当前 `/api/auth/*`、`/api/assets/*`、`/api/editor/*`、`/api/runtime/story/*` 顶层命名空间直接改掉。 +3. 在未完成路径兼容前,直接移除 `/healthz` 或 `/generated-*` 的既有访问习惯。 +4. 在未完成契约回归前,把 `runtime-main` 和 `runtime-story-action` 的职责重新混成一个难以验收的大入口。 + +## 6. 本任务完成定义 + +当以下条件成立时,这条任务视为完成: + +1. 当前 `6` 个挂载面已经有正式书面冻结清单。 +2. 每个挂载面都有: + - 当前入口 + - 当前路由数 + - 顶层路径空间 + - 重写后必须保留的职责边界 +3. 后续任务可以直接以这份文档作为验收引用,不再靠聊天记录记忆。 + +## 7. 后续直接依赖这份基线的任务 + +1. 整理当前后端 `96` 条路由并生成“旧接口 -> 新实现”映射表 +2. 整理当前 `12` 个内部模块并锁定迁移归属 +3. 设计 Axum 路由树 +4. 设计 SpacetimeDB 表 / reducer / view 分层 diff --git a/backend-rewrite-tasklist/README.md b/backend-rewrite-tasklist/README.md new file mode 100644 index 00000000..7782a154 --- /dev/null +++ b/backend-rewrite-tasklist/README.md @@ -0,0 +1,23 @@ +# 后端重写任务清单目录 + +日期:`2026-04-20` + +本目录用于集中存放 `SpacetimeDB + Axum + 阿里云 OSS` 后端重写相关任务清单。 + +## 文件结构 + +- [00_MASTER_TASKLIST.md](./00_MASTER_TASKLIST.md):总纲主清单,保留完整阶段结构与最终验收项。 +- [01_M0_M2_FOUNDATION_AND_AUTH.md](./01_M0_M2_FOUNDATION_AND_AUTH.md):能力冻结、Rust 工作区、Axum 基础设施、鉴权与会话迁移任务。 +- [02_M3_RUNTIME_PROFILE.md](./02_M3_RUNTIME_PROFILE.md):runtime snapshot / settings / profile 迁移任务。 +- [03_M4_STORY_AND_GAMEPLAY.md](./03_M4_STORY_AND_GAMEPLAY.md):story action 主循环与 gameplay reducer 迁移任务。 +- [04_M5_CUSTOM_WORLD_AND_AGENT.md](./04_M5_CUSTOM_WORLD_AND_AGENT.md):custom world / gallery / agent 主链迁移任务。 +- [05_M6_ASSETS_OSS_EDITOR.md](./05_M6_ASSETS_OSS_EDITOR.md):assets / 阿里云 OSS / editor 迁移任务。 +- [06_M7_TEST_DEPLOY_CUTOVER.md](./06_M7_TEST_DEPLOY_CUTOVER.md):联调、回归、部署、观测与切流任务。 +- [07_CROSS_CUTTING_AND_ACCEPTANCE.md](./07_CROSS_CUTTING_AND_ACCEPTANCE.md):横向专项、执行顺序与最终验收清单。 +- [M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md](./M0_CAPABILITY_SURFACE_BASELINE_2026-04-20.md):当前 Node 后端 `6` 个挂载面的冻结基线,用于后续接口映射、模块迁移与验收对照。 + +## 维护规则 + +1. 总纲与拆分文件都以本目录为唯一维护位置。 +2. 总纲用于把控全局节奏,拆分文件用于实际逐项推进。 +3. 如阶段任务发生明显变化,需要同步更新总纲与对应拆分文件。 diff --git a/docs/technical/README.md b/docs/technical/README.md index 3c79fc45..ff21fca7 100644 --- a/docs/technical/README.md +++ b/docs/technical/README.md @@ -4,6 +4,7 @@ ## 文档列表 +- [SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md](./SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md):基于当前 Node 后端能力清单,设计用 `SpacetimeDB + Axum + 阿里云 OSS` 重写后端的目标架构、模块映射、数据分层、迁移顺序与验收标准。 - [REPO_NOISE_CLEANUP_BASELINE_2026-04-19.md](./REPO_NOISE_CLEANUP_BASELINE_2026-04-19.md):落实工程清理审计第一阶段后的仓库噪音清理范围、忽略规则闭合点与后续约束。 - [PROMPT_DIRECTORY_MANAGEMENT_2026-04-19.md](./PROMPT_DIRECTORY_MANAGEMENT_2026-04-19.md):后端提示词收口到 `server-node/src/prompts/` 的目录方案、兼容策略与后续新增规则。 - [CUSTOM_WORLD_DRAFT_GENERATION_FAILURE_ANALYSIS_AND_FIX_2026-04-20.md](./CUSTOM_WORLD_DRAFT_GENERATION_FAILURE_ANALYSIS_AND_FIX_2026-04-20.md):世界草稿生成失败后等待页误显示为“卡在编译草稿卡”的根因拆解、主链与增强链路边界,以及本次修复策略。 diff --git a/docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md b/docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md new file mode 100644 index 00000000..5d844507 --- /dev/null +++ b/docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md @@ -0,0 +1,745 @@ +# 基于 SpacetimeDB + Axum + 阿里云 OSS 的后端重写设计文档 + +日期:`2026-04-20` + +## 1. 文档定位 + +这份文档不是继续扩写当前 `server-node/` 的实现细节,而是基于**当前仓库已经落地的后端能力**,为下一版 Rust 后端提供一份可以直接落地编码的重写设计。 + +目标很明确: + +1. 保留当前项目已经具备的后端能力面,不做需求缩水。 +2. 把后端实现从 `Express + PostgreSQL + 本地 public/generated-* 文件` 重写为: + - `Axum`:唯一 HTTP 边界层与流式接口层 + - `SpacetimeDB`:唯一运行时状态与实时订阅真相源 + - `阿里云 OSS`:唯一大文件与二进制资产存储 +3. 让前端在第一阶段尽量少改,优先兼容当前 `/api/*`、`/healthz`、SSE 与资源路径习惯。 + +## 2. 当前工程必须继承的能力基线 + +以 `docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md` 当前生成结果为准,现有 Node 后端的能力基线是: + +- 对外挂载面:`6` 个 +- 已登记路由:`96` 条 +- 内部模块目录:`12` 个 +- 公开接口:`10` 条 +- JWT 接口:`69` 条 +- 环境开关接口:`17` 条 +- 流式接口:`6` 条 + +重写后的 Rust 后端,第一阶段必须至少完整覆盖这 6 个挂载面: + +1. `health` +2. `auth` +3. `editor` +4. `assets` +5. `runtime-main` +6. `runtime-story-action` + +当前后端内部模块也不能“凭感觉重设计”,而要按现有职责做映射: + +1. `ai` +2. `assets` +3. `combat` +4. `custom-world` +5. `editor` +6. `inventory` +7. `npc` +8. `progression` +9. `quest` +10. `runtime` +11. `runtime-item` +12. `story` + +## 3. 技术选型后的硬边界 + +### 3.1 SpacetimeDB 的平台约束与本项目边界 + +根据 SpacetimeDB 官方 Rust crate 文档,`reducer` 不能直接使用 `std::net` 或 `std::fs` 进行外部 IO;而 2.0 官方文档又提供了 `procedure + ctx.http` 的受控 HTTP 能力。 +也就是说,**平台层面并不是完全不能做外部调用**,但对于本项目这次重写,我们仍然主动把下面这些副作用统一放到 Axum,而不是塞进 SpacetimeDB: + +1. 阿里云 OSS 上传、下载、签名 +2. DashScope / Ark / 其他 LLM 请求 +3. 微信 OAuth +4. 短信验证码 +5. 本地文件系统读写 + +这样设计不是因为“SpacetimeDB 绝对做不到”,而是因为这类能力都要求: + +1. 更强的重试、超时、日志和熔断能力 +2. 更自由的 SDK / multipart / 签名上传实现 +3. 与 HTTP 头、cookie、回调、对象存储策略深度耦合 +4. 与游戏状态 schema 解耦,避免把第三方供应商能力直接绑进数据库模块发布周期 + +结论: + +- `SpacetimeDB` 负责状态、规则、订阅、命令执行与读模型。 +- `Axum` 负责所有外部副作用与 HTTP 协议。 + +### 3.2 Axum 的边界 + +根据 Axum 官方文档,`Router` 通过 `.with_state(...)` 注入共享状态后才成为可真正 `serve()` 的路由树;因此 Axum 适合作为: + +1. 统一 HTTP 入口 +2. Bearer / Cookie 鉴权入口 +3. SSE 输出入口 +4. OSS 上传凭证签发入口 +5. 与 SpacetimeDB 的应用层编排入口 + +结论: + +- Axum 是唯一 BFF / API Gateway。 +- 前端第一阶段仍然只认识 Axum,不直接依赖 SpacetimeDB 原生接口。 + +### 3.3 OSS 的边界 + +根据阿里云 OSS 官方文档: + +1. `PostObject` 适合浏览器表单直传,服务端可以下发 `policy`、`signature` 与上传条件。 +2. `STS` 临时访问凭证适合把上传权限以有限时、有限范围的方式下发给客户端。 +3. `PutObject` / `PostObject` 都支持 `x-oss-meta-*` 元数据与标签。 + +结论: + +- 所有图片、动画、精灵表、场景图、封面图、视频参考素材都存 OSS。 +- SpacetimeDB 只存对象键、版本、尺寸、状态、逻辑元数据,不存二进制。 +- Axum 负责下发直传凭证、校验上传结果、补写元数据。 + +## 4. 目标总体架构 + +```text +Web / Mobile Frontend +├─ 继续访问 /api/*、/healthz、/generated-* +└─ 第一阶段不直接依赖 SpacetimeDB 原生协议 + +Axum API Server +├─ auth:登录、refresh cookie、JWT/OIDC 签发 +├─ runtime facade:兼容当前 REST / SSE contract +├─ asset gateway:OSS 直传签名、对象确认、媒体任务编排 +├─ ai gateway:DashScope / Ark / 其他模型调用 +├─ editor gateway:开发态文件读写或对象化编辑能力 +├─ background workers:异步作业执行与回写 +└─ SpacetimeDB client:调用 reducer、查询 view / public table、订阅任务状态 + +SpacetimeDB Module +├─ auth tables:用户、身份、session、风控、审计 +├─ runtime tables:存档、设置、浏览历史、个人面板 +├─ gameplay tables:story / npc / quest / inventory / combat / progression +├─ custom-world tables:问答会话、agent 会话、草稿卡、操作记录 +├─ asset metadata tables:生成任务、对象清单、引用关系 +├─ reducers:唯一状态写入口 +└─ views / public tables:唯一读模型与订阅面 + +Aliyun OSS +├─ generated-character-drafts +├─ generated-characters +├─ generated-custom-world-scenes +├─ generated-qwen-sprites +├─ generated-cover-images +└─ editor-exports / temp-uploads / workflow-cache +``` + +## 5. 重写后的核心原则 + +### 5.1 先兼容当前 API 面,再逐步让前端吃到实时能力 + +第一阶段不要强推前端直接改成 SpacetimeDB 客户端模式,而是: + +1. Axum 保持当前 `/api/*` 路由空间。 +2. Axum 保持当前 `x-request-id / x-api-version / x-route-version` 头和响应 envelope。 +3. Axum 保持当前 story / custom-world-agent 的 SSE 体验。 +4. SpacetimeDB 先做后端内部真相源。 + +第二阶段再按模块把只读页改成直接订阅 SpacetimeDB。 + +### 5.2 命令与读模型分离 + +SpacetimeDB 官方文档明确说明: + +1. reducer 是唯一可修改表的入口。 +2. reducer 不直接返回业务数据给客户端。 +3. view 可被查询与订阅,并会随底层表变化自动更新。 + +因此本项目必须采用: + +- `Reducer = 命令入口` +- `View / Public Table = 读模型入口` +- `Axum = HTTP 兼容层与聚合层` + +### 5.3 大对象不进数据库 + +当前 Node 后端把生成结果落在 `public/generated-*`。重写后统一改成: + +- `OSS` 存二进制 +- `SpacetimeDB` 存引用和状态 +- `Axum` 输出 URL、签名 URL 或 CDN URL + +### 5.4 Schema 必须按 SpacetimeDB 的迁移约束设计 + +SpacetimeDB 官方文档对自动迁移的限制很强: + +1. 删表、改列类型、改列名、调整列顺序都不是安全日常操作。 +2. 新列只能追加到表末尾,且要提供默认值。 +3. reducer 改名或删除会直接影响客户端调用。 + +因此本项目的数据模型必须尽量满足: + +1. 主表稳定、字段追加式演进 +2. 高频变化数据优先事件表化 +3. 聚合结果优先投影表 / view,而不是频繁重塑旧表结构 + +## 6. 推荐工程结构 + +建议新增 Rust 工作区,例如 `server-rs/`: + +```text +server-rs/ +├─ Cargo.toml +├─ crates/ +│ ├─ api-server/ # Axum 入口 +│ ├─ spacetime-module/ # SpacetimeDB Rust 模块(编译为 wasm) +│ ├─ application/ # 用例编排层 +│ ├─ domain/ # 纯领域类型、枚举、ID、值对象 +│ ├─ contracts/ # HTTP DTO / SSE event / 内部 command DTO +│ ├─ auth-service/ # JWT、cookie、provider adapter +│ ├─ oss-service/ # OSS 直传、签名、对象管理 +│ ├─ llm-service/ # DashScope / Ark / 其他模型适配 +│ ├─ spacetime-client/ # 生成 bindings 后的 DB client adapter +│ └─ tests/ # 集成测试、contract 测试、smoke +└─ scripts/ + ├─ dev.sh / dev.ps1 + ├─ spacetime-publish.sh + └─ smoke.sh +``` + +目录职责约束: + +1. `spacetime-module/` 只能写纯状态逻辑,不写网络 / 文件系统。 +2. `api-server/` 只做协议装配、鉴权、中间件、handler。 +3. `application/` 编排 Axum、OSS、LLM、SpacetimeDB 之间的流程。 +4. `domain/` 只放纯数据结构和规则,不碰框架。 +5. `contracts/` 负责与当前前端兼容的 JSON / SSE 协议。 + +## 7. 目标模块映射 + +| 当前模块 | 重写后主归属 | 次归属 | 说明 | +| --- | --- | --- | --- | +| `auth` | Axum `auth-service` + SpacetimeDB private tables | 无 | 登录入口、refresh cookie、JWT/OIDC、审计与风控拆为“Axum 处理副作用 + SpacetimeDB 落状态”。 | +| `runtime` | SpacetimeDB module | Axum facade | 存档、设置、浏览历史、profile dashboard 统一进入 SpacetimeDB。 | +| `story` | SpacetimeDB module | Axum SSE facade | story action、状态推进、可选项构造、恢复态读取以后端 reducer/view 为准。 | +| `combat` | SpacetimeDB module | 无 | 纯规则计算,天然适合 reducer。 | +| `inventory` | SpacetimeDB module | 无 | 背包、赠礼、交易、物品副作用全部 reducer 化。 | +| `npc` | SpacetimeDB module | Axum for LLM dialogue | 关系、招募、状态机在 SpacetimeDB;LLM 台词生成留在 Axum。 | +| `progression` | SpacetimeDB module | 无 | 关卡、等级、敌对 scaling、章节推进都做领域表和 reducer。 | +| `quest` | SpacetimeDB module | Axum for AI quest drafting | 任务主状态在 SpacetimeDB;生成型内容由 Axum 生产后回写。 | +| `runtime-item` | SpacetimeDB module | Axum for AI intent | 物品奖励和解析归 reducer;AI 意图生成由 Axum 负责。 | +| `custom-world` | SpacetimeDB module + Axum orchestration | OSS | 会话、草稿、agent 状态放 SpacetimeDB;世界编译、资产生成、发布编排在 Axum。 | +| `ai` | Axum `llm-service` | SpacetimeDB task tables | 外部模型调用全部放 Axum。 | +| `assets` | Axum `oss-service` | SpacetimeDB asset metadata | 二进制进 OSS,元数据进 SpacetimeDB。 | +| `editor` | Axum `editor` namespace | OSS / local fs | 开发态保留本地文件适配,线上默认走对象化资源。 | + +## 8. 数据建模方案 + +## 8.1 表的分层 + +建议在 SpacetimeDB 中至少拆成 5 组表: + +### A. 身份与会话表 + +- `user_account` +- `auth_identity` +- `refresh_session` +- `auth_audit_log` +- `auth_risk_block` +- `sms_auth_event` +- `wechat_auth_state` + +说明: + +1. 这些表默认都应为 private。 +2. 密码哈希、短信验证码校验、微信 code 换 token 的动作在 Axum 完成。 +3. Axum 再调用 reducer 写入最终结果。 + +### B. 运行时主状态表 + +- `runtime_snapshot` +- `runtime_setting` +- `profile_dashboard_state` +- `profile_wallet_ledger` +- `profile_played_world` +- `profile_save_archive` +- `user_browse_history` + +说明: + +1. `runtime_snapshot` 继续作为“恢复游戏”的主聚合表。 +2. `profile_*` 作为只读页投影表,避免每次从大快照现算。 +3. `browse_history`、`save_archive` 单独建表,不要藏进 snapshot blob。 + +### C. Gameplay 领域表 + +- `story_session` +- `story_event` +- `npc_state` +- `quest_record` +- `inventory_slot` +- `treasure_record` +- `battle_state` +- `player_progression` +- `chapter_progression` + +说明: + +1. `story_action` 不直接改大 JSON,而是 reducer 驱动多个领域表。 +2. 是否继续保留兼容快照,可由投影 reducer 汇总生成。 +3. 旧前端仍需要 `gameState + currentStory` 时,由 Axum 聚合成兼容 DTO。 + +### D. Custom World 表 + +- `custom_world_profile` +- `custom_world_session` +- `custom_world_agent_session` +- `custom_world_agent_message` +- `custom_world_agent_operation` +- `custom_world_draft_card` +- `custom_world_asset_link` +- `custom_world_gallery_entry` + +说明: + +1. 传统问答流与 Agent 流不再混一个 payload。 +2. 卡片、操作、消息必须拆表,不能再都塞进一个大 JSON 会话体。 +3. 公开画廊作为独立投影,避免从 profile 运行时拼装。 + +### E. 资产与对象元数据表 + +- `asset_job` +- `asset_object` +- `asset_manifest` +- `character_visual_asset` +- `character_animation_asset` +- `scene_image_asset` +- `sprite_sheet_asset` + +说明: + +1. 任务状态在 SpacetimeDB。 +2. 二进制对象在 OSS。 +3. 所有业务实体只引用 `asset_object_key / cdn_url / version / hash`。 + +## 8.2 public / private 原则 + +依据 SpacetimeDB 官方访问权限文档: + +1. private table 默认只给 reducer / view / owner 看。 +2. public table 才适合直接查询和订阅。 + +本项目建议: + +- `auth_*`、`refresh_session`、风控、验证码全部 private +- `runtime_snapshot` private +- `story_session` private +- `custom_world_agent_*` 绝大多数 private +- `gallery`、公共角色卡、公共作品索引可 public +- 如需“用户自己的读模型”,优先用 `ViewContext` view 暴露 + +## 8.3 view 设计原则 + +依据 SpacetimeDB 官方 view 文档: + +1. view 可以被查询和订阅,底层表变化时会自动更新。 +2. `AnonymousViewContext` 可被所有用户共享物化结果,性能明显优于按用户单独计算。 +3. view 不适合全表 `.iter()` 扫描,应该通过索引查找或返回可分析的 query。 + +所以本项目的 view 设计规则必须是: + +1. 画廊、排行榜、商店、公共世界列表,优先匿名 view。 +2. “我的背包 / 我的档案 / 我的当前会话”这类按用户隔离的读模型,才用带身份上下文的 view。 +3. 首页、资料库、历史记录、存档列表都必须先有索引,再写 view。 + +## 9. 鉴权设计 + +## 9.1 总体方案 + +建议保留当前“密码 / 手机验证码 / 微信”三类登录能力,但把实现改成: + +1. Axum 负责登录副作用: + - 密码校验 + - 短信发送与校验 + - 微信 OAuth code 交换 + - refresh cookie 签发与轮换 +2. Axum 负责签发**OIDC 兼容 JWT** +3. 同一张 JWT 同时用于: + - Axum 自身 Bearer 鉴权 + - SpacetimeDB reducer / view 的身份透传 + +这是可行的,因为 SpacetimeDB 官方文档说明其可以从 OIDC 兼容 JWT 中提取身份声明,并在模块上下文中使用这些 claims。 + +## 9.2 Token 设计 + +建议: + +- `iss`:固定为 Axum 网关身份发行者,例如 `https://api.genarrative.example/auth` +- `sub`:稳定用户 ID +- 扩展 claims: + - `sid`:session id + - `provider`:password / phone / wechat + - `roles` + - `phone_verified` + - `display_name` + +## 9.3 Refresh Session + +建议保留当前模式: + +1. 浏览器短期 Bearer access token +2. HttpOnly refresh cookie +3. refresh session 服务端可吊销 + +但新的会话 ledger 写入 SpacetimeDB private 表即可。 + +## 10. Axum 侧设计 + +## 10.1 进程职责 + +Axum 进程建议拆成以下子系统: + +1. `http::middleware` + - request id + - tracing + - envelope / 错误标准化 + - auth extractor +2. `http::routes` + - `/healthz` + - `/api/auth/*` + - `/api/runtime/*` + - `/api/runtime/story/*` + - `/api/assets/*` + - `/api/editor/*` +3. `application::services` + - story facade + - runtime snapshot facade + - custom world facade + - asset facade +4. `infra` + - SpacetimeDB client + - OSS adapter + - DashScope / Ark adapter + - SMS / WeChat adapter + +## 10.2 流式接口 + +当前项目已经有 6 条流式接口,重写时不建议一上来全部改成 WebSocket。 + +第一阶段建议: + +1. 继续使用 Axum SSE 输出流式文本与阶段事件。 +2. Axum 在处理流式过程中,持续把阶段状态写回 SpacetimeDB。 +3. 前端仍按当前 SSE 协议消费。 + +适合继续保留为 Axum SSE 的场景: + +1. `story/initial` +2. `story/continue` +3. `chat/character/*` +4. `chat/npc/*` +5. `custom-world/generate/stream` +6. `custom-world/agent/messages/stream` + +## 10.3 兼容 contract + +Axum 第一阶段需要兼容当前项目的这些约定: + +1. 路径空间不变 +2. `x-request-id` +3. `x-api-version` +4. `x-route-version` +5. `x-response-time-ms` +6. 可选 envelope:`x-genarrative-response-envelope` + +这样前端可以在不大改 `src/services/*` 的前提下切换后端实现。 + +## 11. OSS 设计 + +## 11.1 对象键规划 + +建议统一对象键前缀,保持与当前前端路径习惯接近: + +```text +generated-character-drafts/{character_id}/{job_id}/{file} +generated-characters/{character_id}/visual/{asset_id}/{file} +generated-characters/{character_id}/animation/{asset_id}/{action}/{file} +generated-custom-world-scenes/{profile_id}/{landmark_id}/{asset_id}/{file} +generated-qwen-sprites/{role_id}/{sheet_id}/{file} +generated-cover-images/{profile_id}/{asset_id}/{file} +editor-cache/{resource_type}/{resource_id}/{file} +workflow-cache/{workflow_type}/{workflow_id}.json +``` + +## 11.2 上传模式 + +建议: + +1. 前端直传图片、封面、小文件:`PostObject` +2. 大文件或需要细粒度控制时:`STS + PutObject / Multipart` +3. 生成型资产:Axum worker 直接上传 OSS + +其中: + +- `PostObject` 用于浏览器上传时,Axum 负责生成 policy 与 signature。 +- policy 中必须明确: + - key 前缀 + - content-type 白名单 + - content-length-range + - success_action_status + +## 11.3 元数据与标签 + +建议所有业务对象写入统一元数据: + +- `x-oss-meta-owner-user-id` +- `x-oss-meta-profile-id` +- `x-oss-meta-entity-id` +- `x-oss-meta-asset-kind` +- `x-oss-meta-source-job-id` +- `x-oss-meta-content-hash` +- `x-oss-meta-origin` + +注意: + +1. OSS 官方文档要求自定义元数据使用 `x-oss-meta-*` 前缀。 +2. 所有元数据总大小不能超过 `8 KB`。 + +## 11.4 URL 策略 + +建议: + +1. 业务表里统一存 `object_key` +2. 对外输出 `cdn_url` +3. 私有对象额外输出短期签名 URL + +为了兼容当前前端相对路径使用习惯,第一阶段可以让 Axum 或 CDN 兼容以下历史前缀: + +1. `/generated-character-drafts/*` +2. `/generated-characters/*` +3. `/generated-custom-world-scenes/*` +4. `/generated-qwen-sprites/*` + +## 12. 关键业务流设计 + +## 12.1 Story Action + +目标: + +1. `storyActionService` 当前承担的跨模块结算必须迁到 SpacetimeDB reducer。 +2. Axum 只做 request parse、auth、调用 reducer、读取 view、拼回当前前端响应。 + +推荐流程: + +1. 前端 `POST /api/runtime/story/actions/resolve` +2. Axum 校验请求并附带 JWT +3. Axum 调用 SpacetimeDB `resolve_story_action` reducer +4. reducer 内部联动: + - `story` + - `combat` + - `inventory` + - `npc` + - `quest` + - `runtime-item` + - `progression` +5. reducer 写回领域表 +6. Axum 再读取 `current_story_view`、`runtime_snapshot_view` +7. Axum 返回兼容当前前端的 `RuntimeStoryActionResponse` + +## 12.2 存档与恢复 + +目标: + +1. 仍保留当前“完整恢复游戏”的能力。 +2. 但底层不再由 PostgreSQL 单大 JSON 承担全部职责。 + +建议: + +1. `runtime_snapshot` 继续保留兼容聚合快照,满足现有恢复链路。 +2. gameplay 真相由领域表维护。 +3. 每次重要 reducer 提交后,异步或同步刷新 snapshot projection。 + +这样可以兼顾: + +1. 旧前端兼容 +2. 新后端可审计 +3. SpacetimeDB 实时订阅能力 + +## 12.3 Custom World Agent + +当前 Node 后端中,`customWorldAgentOrchestrator + SessionStore + Operation` 已经是一条清晰主链。 +重写后建议进一步正规化: + +1. SpacetimeDB: + - 存会话 + - 存消息 + - 存卡片 + - 存操作状态 + - 存草稿 profile +2. Axum: + - 调 LLM + - 调图片生成 + - 调 OSS + - 发 SSE + - 把阶段结果回写 reducer + +不再允许“一整个 agent 会话对象 JSON 一把写回”作为长期形态。 + +## 12.4 资产生成 + +资产链路拆成四步: + +1. Axum 创建 `asset_job` +2. Axum worker 调外部模型 +3. 产物上传 OSS,写 `asset_object` +4. Axum 调 reducer 将对象绑定到: + - 角色 + - 地点 + - 世界草稿 + - Qwen sprite sheet + +所有“对象是否已经被业务引用”的事实,以 SpacetimeDB 绑定表为准,而不是以 OSS 是否存在某个 key 为准。 + +## 13. 迁移阶段建议 + +## Phase 0:冻结能力清单 + +交付: + +1. 固定当前 `96` 条接口为重写验收基线 +2. 固定当前 `12` 个模块为迁移映射基线 +3. 固定当前前端 contract 与 SSE 协议 + +## Phase 1:先搭 Axum 外壳与鉴权 + +交付: + +1. `/healthz` +2. `/api/auth/*` +3. response envelope +4. request id / tracing +5. Axum -> SpacetimeDB 基础 client +6. OIDC-compatible JWT 签发 + +## Phase 2:迁移 runtime snapshot / settings / profile + +交付: + +1. 存档 +2. 设置 +3. 浏览历史 +4. profile dashboard +5. save archives + +这是最容易先跑通的闭环。 + +## Phase 3:迁移 story action 主循环 + +交付: + +1. story reducer +2. combat / inventory / npc / quest / runtime-item / progression 联动 +3. `/api/runtime/story/*` + +这一阶段完成后,运行时真相就真正从 Node 版切出去了。 + +## Phase 4:迁移 custom world 与 agent + +交付: + +1. legacy custom world session +2. custom world library / gallery +3. custom world agent 会话、卡片、操作 +4. scene npc / entity generation + +## Phase 5:迁移 assets / editor + +交付: + +1. OSS 直传 +2. 生成任务 +3. 对象元数据 +4. 编辑器读写开发态适配 +5. 旧 `/generated-*` 路径兼容 + +## 14. 验收标准 + +重写完成至少要满足: + +1. 当前 `96` 条已登记路由全部有对应实现或明确兼容替代。 +2. 当前 6 个挂载面全部保留。 +3. 浏览器无需直接知道 SpacetimeDB 原生接口即可跑通主流程。 +4. story action、存档、custom world、agent、assets 都以后端为唯一真相。 +5. 所有生成图片、动画、精灵表都不再依赖本地 `public/generated-*` 持久化。 +6. Axum 和 SpacetimeDB 的职责边界稳定,不把外部网络 IO 偷放进 module。 + +## 15. 关键风险 + +### 15.1 不能把 SpacetimeDB 当 PostgreSQL 替身直接套 + +SpacetimeDB 更像“带强实时订阅能力的状态机数据库”,不是传统 SQL 仓储替身。 +如果仍沿用“单大 JSON + 巨型路由文件 + 过程式 handler”思路,重写后仍然会很快回到旧热点。 + +### 15.2 schema 演进成本高于 PostgreSQL + +SpacetimeDB 自动迁移更适合“增量追加”,不适合高频改列结构。 +所以必须提前定好: + +1. 稳定主键 +2. 稳定 reducer 命名 +3. 事件表 / 投影表边界 + +### 15.3 view 滥用会造成性能问题 + +如果把资料库、画廊、排行榜写成按用户逐个计算、又缺索引的 view,性能会很差。 +因此 read model 必须先建索引,再决定用匿名 view 还是按用户 view。 + +### 15.4 资产路径兼容是迁移成败关键 + +当前前端大量相对路径、角色图、场景图、动画图都是围绕 `/generated-*` 组织的。 +如果不先做路径兼容层,存档恢复和世界资料库会大面积失效。 + +## 16. 内部实现依据 + +这份设计稿对当前工程的判断,主要依据以下仓库现状: + +1. `server-node/src/server.ts` +2. `server-node/src/app.ts` +3. `server-node/src/routes/authRoutes.ts` +4. `server-node/src/routes/runtimeRoutes.ts` +5. `server-node/src/modules/story/storyActionRoutes.ts` +6. `server-node/src/repositories/runtimeRepository.ts` +7. `server-node/src/services/customWorldAgentOrchestrator.ts` +8. `docs/technical/NODE_BACKEND_MODULE_AND_API_INDEX.md` +9. `docs/technical/NODE_SERVER_KNOWLEDGE_GRAPH_2026-04-08.md` + +## 17. 外部技术依据 + +以下外部依据用于确定本次新架构的技术边界,均来自官方文档或官方 crate 文档: + +1. [SpacetimeDB Tables](https://spacetimedb.com/docs/tables/) +2. [SpacetimeDB Table Access Permissions](https://spacetimedb.com/docs/tables/access-permissions/) +3. [SpacetimeDB Reducers Overview](https://spacetimedb.com/docs/functions/reducers/) +4. [SpacetimeDB Views](https://spacetimedb.com/docs/functions/views/) +5. [SpacetimeDB Authorization](https://spacetimedb.com/docs/http/authorization/) +6. [SpacetimeDB Authentication](https://spacetimedb.com/docs/core-concepts/authentication/) +7. [SpacetimeDB Using Auth Claims](https://spacetimedb.com/docs/core-concepts/authentication/usage/) +8. [SpacetimeDB Rust crate docs](https://docs.rs/spacetimedb/latest/spacetimedb/) +9. [SpacetimeDB Rust Client SDK](https://spacetimedb.com/docs/sdks/rust/) +10. [Axum crate docs](https://docs.rs/axum/latest/axum/) +11. [Axum SSE](https://docs.rs/axum/latest/axum/response/sse/) +12. [阿里云 OSS 服务端签名表单上传](https://help.aliyun.com/zh/oss/user-guide/form-upload) +13. [阿里云 OSS STS 临时授权访问](https://help.aliyun.com/zh/oss/developer-reference/authorized-access-1) +14. [阿里云 OSS PutObject](https://help.aliyun.com/zh/oss/developer-reference/putobject) +15. [阿里云 OSS PostObject](https://help.aliyun.com/zh/oss/developer-reference/postobject) + +## 18. 一句话结论 + +这次重写最正确的落点不是“把 Express 改成 Axum”,而是: + +**让 Axum 成为唯一外部副作用和 HTTP 边界,让 SpacetimeDB 成为唯一状态机真相源,让 OSS 成为唯一资产对象仓,从而在不丢当前 96 条能力面的前提下,把项目升级成真正可持续扩展的 Rust 后端。**