From aa2e9b36d73e305431685b44b432e3d002463020 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 29 Apr 2026 11:51:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=20server-rs=20DDD=20?= =?UTF-8?q?=E9=87=8D=E6=9E=84=E8=AE=A1=E5=88=92=E4=B8=8E=E9=AA=A8=E6=9E=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PLAN.md | 8 + ...KEND_IMPLEMENTATION_BASELINE_2026-04-25.md | 9 + docs/technical/README.md | 2 + .../SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md | 393 ++++++++++++++++++ ...VER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md | 310 ++++++++++++++ package.json | 1 + scripts/check-server-rs-ddd-boundaries.mjs | 155 +++++++ server-rs/README.md | 12 + server-rs/crates/module-ai/src/application.rs | 4 + server-rs/crates/module-ai/src/commands.rs | 4 + server-rs/crates/module-ai/src/domain.rs | 4 + server-rs/crates/module-ai/src/errors.rs | 3 + server-rs/crates/module-ai/src/events.rs | 3 + server-rs/crates/module-ai/src/lib.rs | 6 + .../crates/module-assets/src/application.rs | 8 + .../crates/module-assets/src/commands.rs | 7 + server-rs/crates/module-assets/src/domain.rs | 15 + server-rs/crates/module-assets/src/errors.rs | 5 + server-rs/crates/module-assets/src/events.rs | 4 + server-rs/crates/module-assets/src/lib.rs | 33 +- .../crates/module-auth/src/application.rs | 3 + server-rs/crates/module-auth/src/commands.rs | 3 + server-rs/crates/module-auth/src/domain.rs | 4 + server-rs/crates/module-auth/src/errors.rs | 3 + server-rs/crates/module-auth/src/events.rs | 3 + server-rs/crates/module-auth/src/lib.rs | 6 + .../crates/module-big-fish/src/application.rs | 3 + .../crates/module-big-fish/src/commands.rs | 3 + .../crates/module-big-fish/src/domain.rs | 4 + .../crates/module-big-fish/src/errors.rs | 3 + .../crates/module-big-fish/src/events.rs | 3 + server-rs/crates/module-big-fish/src/lib.rs | 6 + .../crates/module-combat/src/application.rs | 3 + .../crates/module-combat/src/commands.rs | 3 + server-rs/crates/module-combat/src/domain.rs | 4 + server-rs/crates/module-combat/src/errors.rs | 3 + server-rs/crates/module-combat/src/events.rs | 3 + server-rs/crates/module-combat/src/lib.rs | 6 + .../module-custom-world/src/application.rs | 3 + .../module-custom-world/src/commands.rs | 3 + .../crates/module-custom-world/src/domain.rs | 4 + .../crates/module-custom-world/src/errors.rs | 3 + .../crates/module-custom-world/src/events.rs | 3 + .../crates/module-custom-world/src/lib.rs | 6 + .../module-inventory/src/application.rs | 3 + .../crates/module-inventory/src/commands.rs | 3 + .../crates/module-inventory/src/domain.rs | 4 + .../crates/module-inventory/src/errors.rs | 3 + .../crates/module-inventory/src/events.rs | 3 + server-rs/crates/module-inventory/src/lib.rs | 6 + .../crates/module-npc/src/application.rs | 3 + server-rs/crates/module-npc/src/commands.rs | 3 + server-rs/crates/module-npc/src/domain.rs | 4 + server-rs/crates/module-npc/src/errors.rs | 3 + server-rs/crates/module-npc/src/events.rs | 3 + server-rs/crates/module-npc/src/lib.rs | 6 + .../module-progression/src/application.rs | 3 + .../crates/module-progression/src/commands.rs | 3 + .../crates/module-progression/src/domain.rs | 4 + .../crates/module-progression/src/errors.rs | 3 + .../crates/module-progression/src/events.rs | 3 + .../crates/module-progression/src/lib.rs | 6 + .../crates/module-puzzle/src/application.rs | 3 + .../crates/module-puzzle/src/commands.rs | 3 + server-rs/crates/module-puzzle/src/domain.rs | 4 + server-rs/crates/module-puzzle/src/errors.rs | 3 + server-rs/crates/module-puzzle/src/events.rs | 3 + server-rs/crates/module-puzzle/src/lib.rs | 6 + .../crates/module-quest/src/application.rs | 3 + server-rs/crates/module-quest/src/commands.rs | 3 + server-rs/crates/module-quest/src/domain.rs | 4 + server-rs/crates/module-quest/src/errors.rs | 3 + server-rs/crates/module-quest/src/events.rs | 3 + server-rs/crates/module-quest/src/lib.rs | 6 + .../module-runtime-item/src/application.rs | 3 + .../module-runtime-item/src/commands.rs | 3 + .../crates/module-runtime-item/src/domain.rs | 4 + .../crates/module-runtime-item/src/errors.rs | 3 + .../crates/module-runtime-item/src/events.rs | 3 + .../crates/module-runtime-item/src/lib.rs | 6 + .../src/application.rs | 3 + .../src/commands.rs | 3 + .../module-runtime-story-compat/src/domain.rs | 4 + .../module-runtime-story-compat/src/errors.rs | 3 + .../module-runtime-story-compat/src/events.rs | 3 + .../module-runtime-story-compat/src/lib.rs | 6 + .../crates/module-runtime/src/application.rs | 3 + .../crates/module-runtime/src/commands.rs | 3 + server-rs/crates/module-runtime/src/domain.rs | 4 + server-rs/crates/module-runtime/src/errors.rs | 3 + server-rs/crates/module-runtime/src/events.rs | 3 + server-rs/crates/module-runtime/src/lib.rs | 6 + .../crates/module-story/src/application.rs | 3 + server-rs/crates/module-story/src/commands.rs | 3 + server-rs/crates/module-story/src/domain.rs | 4 + server-rs/crates/module-story/src/errors.rs | 3 + server-rs/crates/module-story/src/events.rs | 3 + server-rs/crates/module-story/src/lib.rs | 6 + 98 files changed, 1261 insertions(+), 11 deletions(-) create mode 100644 docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md create mode 100644 docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md create mode 100644 scripts/check-server-rs-ddd-boundaries.mjs create mode 100644 server-rs/crates/module-ai/src/application.rs create mode 100644 server-rs/crates/module-ai/src/commands.rs create mode 100644 server-rs/crates/module-ai/src/domain.rs create mode 100644 server-rs/crates/module-ai/src/errors.rs create mode 100644 server-rs/crates/module-ai/src/events.rs create mode 100644 server-rs/crates/module-assets/src/application.rs create mode 100644 server-rs/crates/module-assets/src/commands.rs create mode 100644 server-rs/crates/module-assets/src/domain.rs create mode 100644 server-rs/crates/module-assets/src/errors.rs create mode 100644 server-rs/crates/module-assets/src/events.rs create mode 100644 server-rs/crates/module-auth/src/application.rs create mode 100644 server-rs/crates/module-auth/src/commands.rs create mode 100644 server-rs/crates/module-auth/src/domain.rs create mode 100644 server-rs/crates/module-auth/src/errors.rs create mode 100644 server-rs/crates/module-auth/src/events.rs create mode 100644 server-rs/crates/module-big-fish/src/application.rs create mode 100644 server-rs/crates/module-big-fish/src/commands.rs create mode 100644 server-rs/crates/module-big-fish/src/domain.rs create mode 100644 server-rs/crates/module-big-fish/src/errors.rs create mode 100644 server-rs/crates/module-big-fish/src/events.rs create mode 100644 server-rs/crates/module-combat/src/application.rs create mode 100644 server-rs/crates/module-combat/src/commands.rs create mode 100644 server-rs/crates/module-combat/src/domain.rs create mode 100644 server-rs/crates/module-combat/src/errors.rs create mode 100644 server-rs/crates/module-combat/src/events.rs create mode 100644 server-rs/crates/module-custom-world/src/application.rs create mode 100644 server-rs/crates/module-custom-world/src/commands.rs create mode 100644 server-rs/crates/module-custom-world/src/domain.rs create mode 100644 server-rs/crates/module-custom-world/src/errors.rs create mode 100644 server-rs/crates/module-custom-world/src/events.rs create mode 100644 server-rs/crates/module-inventory/src/application.rs create mode 100644 server-rs/crates/module-inventory/src/commands.rs create mode 100644 server-rs/crates/module-inventory/src/domain.rs create mode 100644 server-rs/crates/module-inventory/src/errors.rs create mode 100644 server-rs/crates/module-inventory/src/events.rs create mode 100644 server-rs/crates/module-npc/src/application.rs create mode 100644 server-rs/crates/module-npc/src/commands.rs create mode 100644 server-rs/crates/module-npc/src/domain.rs create mode 100644 server-rs/crates/module-npc/src/errors.rs create mode 100644 server-rs/crates/module-npc/src/events.rs create mode 100644 server-rs/crates/module-progression/src/application.rs create mode 100644 server-rs/crates/module-progression/src/commands.rs create mode 100644 server-rs/crates/module-progression/src/domain.rs create mode 100644 server-rs/crates/module-progression/src/errors.rs create mode 100644 server-rs/crates/module-progression/src/events.rs create mode 100644 server-rs/crates/module-puzzle/src/application.rs create mode 100644 server-rs/crates/module-puzzle/src/commands.rs create mode 100644 server-rs/crates/module-puzzle/src/domain.rs create mode 100644 server-rs/crates/module-puzzle/src/errors.rs create mode 100644 server-rs/crates/module-puzzle/src/events.rs create mode 100644 server-rs/crates/module-quest/src/application.rs create mode 100644 server-rs/crates/module-quest/src/commands.rs create mode 100644 server-rs/crates/module-quest/src/domain.rs create mode 100644 server-rs/crates/module-quest/src/errors.rs create mode 100644 server-rs/crates/module-quest/src/events.rs create mode 100644 server-rs/crates/module-runtime-item/src/application.rs create mode 100644 server-rs/crates/module-runtime-item/src/commands.rs create mode 100644 server-rs/crates/module-runtime-item/src/domain.rs create mode 100644 server-rs/crates/module-runtime-item/src/errors.rs create mode 100644 server-rs/crates/module-runtime-item/src/events.rs create mode 100644 server-rs/crates/module-runtime-story-compat/src/application.rs create mode 100644 server-rs/crates/module-runtime-story-compat/src/commands.rs create mode 100644 server-rs/crates/module-runtime-story-compat/src/domain.rs create mode 100644 server-rs/crates/module-runtime-story-compat/src/errors.rs create mode 100644 server-rs/crates/module-runtime-story-compat/src/events.rs create mode 100644 server-rs/crates/module-runtime/src/application.rs create mode 100644 server-rs/crates/module-runtime/src/commands.rs create mode 100644 server-rs/crates/module-runtime/src/domain.rs create mode 100644 server-rs/crates/module-runtime/src/errors.rs create mode 100644 server-rs/crates/module-runtime/src/events.rs create mode 100644 server-rs/crates/module-story/src/application.rs create mode 100644 server-rs/crates/module-story/src/commands.rs create mode 100644 server-rs/crates/module-story/src/domain.rs create mode 100644 server-rs/crates/module-story/src/errors.rs create mode 100644 server-rs/crates/module-story/src/events.rs diff --git a/PLAN.md b/PLAN.md index 2dcfcd13..3cff1170 100644 --- a/PLAN.md +++ b/PLAN.md @@ -6,6 +6,8 @@ 目标是把 Rust + SpacetimeDB 后端统一成清晰边界:领域规则在 `module-*`,事务和持久化在 `spacetime-module`,HTTP/BFF 在 `api-server`,外部能力在 `platform-*`,共享值处理和 DTO 分别在 `shared-kernel` / `shared-contracts`。 +全局并行执行任务清单见 `docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md`。runtime story 去兼容层属于该清单中的 `WP-RS` 工作包,不再单独维护专项清单。 + ## Target Architecture - `module-*`:领域模型、值对象、聚合方法、领域服务、命令、领域错误、领域事件、纯应用编排结果;禁止直接依赖 Axum、reqwest、OSS、LLM、文件系统、SpacetimeDB table 操作。 @@ -31,6 +33,12 @@ - `api-server` 中 handler 只保留 transport 逻辑,业务分支迁移到领域或应用层。 - `runtime_story`、`custom_world`、`puzzle`、`big_fish`、`inventory`、`quest`、`npc`、`combat`、`progression` 全部对齐同一结构。 +- 去兼容层任务边界: + - `module-runtime-story-compat` 不作为目标架构保留,迁移为无 `compat` 命名的 `module-runtime-story` 或拆入对应领域模块。 + - `api-server/src/runtime_story/compat*` 只允许作为待删除历史入口,不再新增兼容分支。 + - 前端 runtime story / chat client 统一改到 `POST /api/runtime/story/sessions/:sessionId/...` 新接口族。 + - 旧请求体里的 `worldType / character / monsters / history / context` 不再作为正式主链输入。 + - 表结构硬约束: - 默认保持现有 SpacetimeDB 主表兼容。 - 表结构变更采用最小必要原则。 diff --git a/docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md b/docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md index 7eba374a..14b8b54b 100644 --- a/docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md +++ b/docs/technical/CURRENT_BACKEND_IMPLEMENTATION_BASELINE_2026-04-25.md @@ -31,3 +31,12 @@ - 本地与远端部署:`RUST_LOCAL_AND_REMOTE_DEPLOYMENT_SCRIPTS_2026-04-22.md`、`JENKINS_RUST_BUILD_DEPLOY_PIPELINES_2026-04-23.md`。 如果旧文档与本基线冲突,以本基线和更新日期更近的 Rust / SpacetimeDB 文档为准。 + +## 4. DDD 重构总纲补充 + +`2026-04-28` 起,`server-rs` 后续后端改动还必须同时遵循 [SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md](./SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md): + +- `module-*` 只承载领域模型、命令、应用编排结果、领域事件和领域错误。 +- `spacetime-module` 只承载 SpacetimeDB 表、reducer、procedure、事务 adapter 与 mapper。 +- `api-server` 只承载 HTTP / SSE / BFF adapter 和外部平台服务编排。 +- 任何表结构变化仍必须同步 `migration.rs` 与 [SPACETIMEDB_TABLE_CATALOG.md](./SPACETIMEDB_TABLE_CATALOG.md)。 diff --git a/docs/technical/README.md b/docs/technical/README.md index f1e92a4c..c8c80e94 100644 --- a/docs/technical/README.md +++ b/docs/technical/README.md @@ -4,6 +4,8 @@ ## 文档列表 +- [SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md](./SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md):把 `server-rs` DDD 一次性重构拆成全局可并行工作包,覆盖 `module-*`、`spacetime-module`、`spacetime-client`、`api-server`、`platform-*`、共享契约和前端接入的依赖、边界与验收命令。 +- [SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md](./SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md):冻结 `server-rs` 一次性 DDD 重构总纲,明确 crate 依赖方向、模块目录、上下文聚合/命令/事件/读模型、SpacetimeDB adapter 映射和表结构变更约束。 - [RPG_PROMPT_FRONTEND_REMOVAL_AND_SERVER_RS_MIGRATION_2026-04-28.md](./RPG_PROMPT_FRONTEND_REMOVAL_AND_SERVER_RS_MIGRATION_2026-04-28.md):冻结 RPG 提示词禁止存在前端的边界,明确前端只保留 API client,角色私聊/NPC 对话/剧情续写等 prompt 统一收口到 `server-rs`。 - [RPG_CREATION_RESULT_VIEW_BACKEND_TRUTH_MIGRATION_2026-04-28.md](./RPG_CREATION_RESULT_VIEW_BACKEND_TRUTH_MIGRATION_2026-04-28.md):冻结 RPG 创作结果页保存、Agent session/result preview 真相优先级和结果页入口裁决迁移到后端 result-view 的落地边界。 - [RPG_CREATION_PROFILE_GENERATION_BACKEND_MIGRATION_2026-04-28.md](./RPG_CREATION_PROFILE_GENERATION_BACKEND_MIGRATION_2026-04-28.md):记录 RPG 创作 profile 生成移除非浏览器 legacy AI 回退,统一通过 `server-rs` 的 `/api/runtime/custom-world/profile` 生成世界底稿。 diff --git a/docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md b/docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md new file mode 100644 index 00000000..2328d39c --- /dev/null +++ b/docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md @@ -0,0 +1,393 @@ +# server-rs DDD 一次性重构落地方案 + +日期:`2026-04-28` + +## 1. 背景与当前结论 + +当前仓库已经进入 `server-rs + Axum + SpacetimeDB` 单一后端路线,旧 `server-node` 已不存在,后续不再围绕 Express / PostgreSQL 做兼容设计。本轮重构目标不是新增玩法,而是把已有 Rust 后端统一成可长期演进的 DDD 边界: + +1. 领域规则沉到 `module-*`。 +2. SpacetimeDB 事务、表、reducer、procedure 留在 `spacetime-module`。 +3. HTTP / SSE / BFF 留在 `api-server`。 +4. 外部副作用留在 `platform-*` 或 `api-server` 应用编排层。 +5. 前后端 DTO 留在 `shared-contracts`,跨领域纯值处理留在 `shared-kernel`。 + +本文件是后续编码前的总纲。若局部历史文档与本文冲突,以本文和对应 SpacetimeDB skill 为准;若本文仍无法精准指导某一处编码,必须先补本文或新增更细技术文档,再继续改工程。 + +## 2. 依赖方向 + +允许方向: + +```text +api-server + -> shared-contracts + -> module-* + -> spacetime-client + -> platform-* + +spacetime-module + -> module-* + -> shared-kernel + +module-* + -> shared-kernel + -> 其他 module-* 的纯领域类型(仅在确有跨域规则复用时) + +platform-* + -> shared-kernel + +shared-contracts + -> shared-kernel +``` + +禁止方向: + +1. `module-*` 直接依赖 Axum、HTTP client、OSS、LLM、文件系统、SpacetimeDB table/reducer/procedure API。 +2. `module-*` 新增 `mapper.rs`,映射只能落在 adapter crate。 +3. `spacetime-module` 反向依赖 `api-server`、`spacetime-client` 或 `platform-*`。 +4. `shared-kernel` / `shared-contracts` 依赖业务 crate。 +5. 前端绕过 Axum 直接承接后端业务规则或数据真相。 + +阶段性例外必须满足三个条件: + +1. 在本文“阶段性债务表”登记。 +2. 有明确迁出目标 crate。 +3. 不允许继续扩大例外范围。 + +## 3. crate 职责矩阵 + +| crate | 职责 | 禁止内容 | +| --- | --- | --- | +| `module-ai` | AI 任务、阶段、流式片段、结果引用的纯领域模型和状态机 | 真实 LLM 调用、HTTP、SSE | +| `module-assets` | 资产对象、资产绑定、历史查询输入输出和纯校验规则 | OSS head、reqwest、进程内 fallback store 扩散到领域核心 | +| `module-auth` | 用户、会话、验证码、微信绑定、密码规则、领域错误 | 文件持久化、真实短信副作用、HTTP cookie 写入 | +| `module-big-fish` | 大鱼创作会话、素材槽、运行态规则 | 图片生成、OSS 上传、HTTP handler | +| `module-combat` | 战斗聚合、行动结算、奖励结果 | 直接写背包表、直接发放成长账本 | +| `module-custom-world` | 世界 profile、Agent 会话、草稿卡、发布门禁规则 | LLM 推理、OSS、Axum response shape | +| `module-inventory` | 背包、装备槽、堆叠与消耗规则 | SpacetimeDB table 操作 | +| `module-npc` | NPC 关系、好感、互动、招募规则 | 战斗表初始化事务 | +| `module-progression` | 玩家等级、章节预算、经验记账规则 | 查询前端视图拼装 | +| `module-puzzle` | 拼图创作与运行态纯规则 | 图片生成、排行榜 HTTP shape | +| `module-quest` | 任务领取、推进、完成、交付规则 | 奖励跨域副作用直接写表 | +| `module-runtime` | 运行时设置、快照、个人页状态、存档领域模型 | 直接读写 SpacetimeDB | +| `module-runtime-item` | 宝箱、奖励物品、运行时物品快照 | 背包持久化事务 | +| `module-runtime-story` | RPG runtime story 新接口下的纯应用编排、剧情投影、场景旅行、战后收束、prompt context 投影 | Axum、LLM、SpacetimeDB | +| `module-story` | story session、story event 与推进输入输出 | 直接调用 LLM 或 HTTP | +| `spacetime-module` | 表、reducer、procedure、事务内查询写回、row/snapshot mapper、event table | 领域规则大段堆叠 | +| `spacetime-client` | api-server 调用 SpacetimeDB 的客户端 facade 与绑定 mapper | 领域规则 | +| `api-server` | 路由、鉴权上下文、请求响应映射、SSE、平台服务编排 | 表结构定义、领域规则主逻辑 | +| `platform-*` | JWT/SMS/微信/OSS/LLM/HTTP client 等外部能力 | 玩法领域规则 | +| `shared-kernel` | 字符串、时间、ID、纯值归一化 | 业务流程 | +| `shared-contracts` | HTTP/前端 DTO、兼容 response shape | 领域状态机 | + +## 4. 统一目录结构 + +所有 `module-*` 必须具备以下文件。第一阶段允许旧实现仍在 `lib.rs` 或历史子模块中,但新增和迁移代码必须进入对应落点。 + +```text +src/ +├─ lib.rs +├─ domain.rs 或 domain/ +├─ commands.rs +├─ application.rs +├─ events.rs +└─ errors.rs +``` + +落位规则: + +1. `domain.rs` / `domain/*`:聚合、值对象、领域方法、纯校验、状态迁移。 +2. `commands.rs`:写入用例输入,只表达意图和必要参数,不含 adapter 类型。 +3. `application.rs`:纯应用编排函数,输出领域事件或应用结果,不执行外部副作用。 +4. `events.rs`:领域事件和跨上下文事件,例如奖励待入账、画廊投影待刷新。 +5. `errors.rs`:领域错误,优先可测试、可映射,不直接绑定 HTTP status。 +6. `mapper.rs`:只允许在 `api-server`、`spacetime-module`、`spacetime-client` 等 adapter crate 中出现。 + +## 5. 上下文设计清单 + +### 5.1 认证 `module-auth` + +聚合: + +1. `AuthUser`:账号、公开叙世号、登录方式、绑定状态、token version。 +2. `RefreshSession`:refresh token hash、客户端信息、过期、吊销、last seen。 +3. `SmsVerification`:手机号、场景、验证码状态、冷却、失败次数。 +4. `WechatBinding`:微信 provider 身份、union id、绑定状态。 + +命令: + +1. `PasswordEntryInput` +2. `SendPhoneCodeInput` +3. `PhoneLoginInput` +4. `CreateRefreshSessionInput` +5. `RevokeRefreshSessionInput` +6. `ResolveWechatLoginInput` + +事件: + +1. `AuthUserCreated` +2. `RefreshSessionIssued` +3. `RefreshSessionRevoked` +4. `PhoneCodeAccepted` +5. `WechatIdentityLinked` + +读模型: + +1. `AuthMeResult` +2. `PublicUserSearchResult` +3. `AuthSessionListResult` + +迁移要求:文件持久化和内存 store 从领域核心剥离到 adapter 或临时测试支撑;短信真实发送继续在 `platform-auth`。 + +### 5.2 资产 `module-assets` + +聚合: + +1. `AssetObject`:bucket、object key、访问策略、hash、版本、业务归属。 +2. `AssetEntityBinding`:实体类型、实体 id、slot、资产对象 id。 + +命令: + +1. `ConfirmAssetObjectInput` +2. `AssetObjectUpsertInput` +3. `AssetEntityBindingInput` +4. `AssetHistoryListInput` + +事件: + +1. `AssetObjectConfirmed` +2. `AssetEntityBindingChanged` + +读模型: + +1. `AssetObjectUpsertSnapshot` +2. `AssetEntityBindingSnapshot` +3. `AssetHistoryEntrySnapshot` + +迁移要求:OSS `head_object`、reqwest client 和 fallback store 不再放入领域核心;SpacetimeDB 持久化由 `spacetime-module` 完成。 + +### 5.3 RPG 运行时 + +覆盖 `module-story`、`module-combat`、`module-inventory`、`module-npc`、`module-progression`、`module-quest`、`module-runtime-item`。 + +聚合: + +1. `StorySession`、`StoryEvent` +2. `BattleState` +3. `InventorySlot` +4. `NpcState` +5. `PlayerProgression`、`ChapterProgression` +6. `QuestRecord`、`QuestLog` +7. `TreasureRecord` + +跨上下文事件: + +1. `CombatVictoryResolved` +2. `QuestTurnedIn` +3. `InventoryItemsGranted` +4. `ProgressionXpGranted` +5. `NpcRelationChanged` +6. `RuntimeStoryProjectionChanged` + +事务边界: + +1. 单聚合变更在对应 `module-*` 纯函数中完成。 +2. 战斗奖励、任务奖励、背包写入、成长记账由 `spacetime-module` 或应用服务显式编排。 +3. reducer/procedure 不允许复制领域规则,只负责取 row、调用领域函数、写回 row 和事件表。 + +### 5.4 世界创作 `module-custom-world` + +聚合: + +1. `CustomWorldProfile` +2. `CustomWorldSession` +3. `CustomWorldAgentSession` +4. `CustomWorldAgentMessage` +5. `CustomWorldAgentOperation` +6. `CustomWorldDraftCard` +7. `CustomWorldGalleryEntry` + +命令: + +1. 创建/恢复 Agent 会话。 +2. 写入用户消息。 +3. 写入 LLM 最终回复。 +4. 更新草稿卡。 +5. 发布/下架 profile。 + +事件: + +1. `CustomWorldDraftChanged` +2. `CustomWorldProfilePublished` +3. `CustomWorldGalleryProjectionChanged` +4. `CustomWorldAgentOperationProgressed` + +迁移要求:LLM 提示词和推理在 `api-server + platform-llm`,SpacetimeDB 只落真相表和投影。 + +### 5.5 拼图 `module-puzzle` + +聚合: + +1. `PuzzleAgentSession` +2. `PuzzleAgentMessage` +3. `PuzzleWorkProfile` +4. `PuzzleRuntimeRun` + +事件: + +1. `PuzzleDraftChanged` +2. `PuzzleWorkPublished` +3. `PuzzleRunAdvanced` + +读模型: + +1. 作品卡片。 +2. 运行态快照。 +3. 排行榜结果。 + +### 5.6 大鱼吃小鱼 `module-big-fish` + +聚合: + +1. `BigFishCreationSession` +2. `BigFishAgentMessage` +3. `BigFishAssetSlot` +4. `BigFishRuntimeRun` + +事件: + +1. `BigFishDraftChanged` +2. `BigFishAssetSlotChanged` +3. `BigFishRunTicked` + +### 5.7 AI `module-ai` + +聚合: + +1. `AiTask` +2. `AiTaskStage` +3. `AiTextChunk` +4. `AiResultReference` + +事件: + +1. `AiTaskStarted` +2. `AiTaskStageCompleted` +3. `AiTaskFailed` +4. `AiResultAttached` + +边界:真实模型调用只在 `platform-llm`,`module-ai` 只表达状态机。 + +## 6. SpacetimeDB adapter 映射 + +`spacetime-module` 中每个上下文遵循: + +```text +src// +├─ mod.rs +├─ tables.rs # table 和 public/event 标记 +├─ reducers.rs # 客户端可调用写入口 +├─ procedures.rs # 需要同步返回或外部 procedure 语义的入口 +├─ mapper.rs # row <-> module-* snapshot/input +└─ queries.rs # 事务内查询辅助,只返回 adapter DTO +``` + +当前已有历史拆分与本文不同名时,先按现有文档继续维护;新增或迁移时逐步对齐上面结构。 + +Reducer / procedure 规则: + +1. reducer 使用 `&ReducerContext`,返回 `Result<(), String>` 处理预期错误。 +2. reducer 内授权必须基于 `ctx.sender()`,禁止信任参数中的身份。 +3. reducer 禁止网络、文件系统、外部随机数和全局状态。 +4. procedure 使用 SpacetimeDB 2.0 正确 API;涉及事务必须显式 `with_tx` / `try_with_tx`。 +5. 表访问必须使用 `ctx.db.table()`,更新只通过主键。 +6. 复杂查询不复用写模型;需要前端订阅时新增明确读模型或 public 投影表。 + +## 7. 表结构约束 + +默认不改现有 SpacetimeDB 主表。确需改表时按以下优先级: + +1. 新增 optional 字段。 +2. 新增投影表或 event table。 +3. 新增索引。 +4. 最后才考虑 rename/delete/type change,且必须单独写迁移方案。 + +任何 table 变更必须同步: + +1. `server-rs/crates/spacetime-module/src/migration.rs` +2. `docs/technical/SPACETIMEDB_TABLE_CATALOG.md` +3. 对应 reducer/procedure 测试或最小 smoke +4. 绑定生成和前端/`spacetime-client` 映射 + +本阶段只做目录、文档和边界检查,不变更表结构,因此不需要改 `migration.rs`。 + +## 8. 查询策略 + +1. 写模型不直接服务复杂前端页面。 +2. 每个前端场景必须有独立 query/result DTO。 +3. private table 默认不暴露给前端。 +4. public table 只服务明确订阅场景。 +5. event table 用于 reducer 后广播一次性事件,客户端必须显式订阅。 + +## 9. 第一阶段落地范围 + +第一阶段只做低风险基础设施: + +1. 新增本文作为 DDD 总纲。 +2. 所有 `module-*` 补齐 `domain / commands / application / events / errors` 过渡落位文件。 +3. 新增 `scripts/check-server-rs-ddd-boundaries.mjs`,检查 DDD 骨架、禁用 mapper 落位和 SpacetimeDB/Axum 绝对边界。 +4. 更新文档索引和后端 README。 +5. 不改表、不改 reducer/procedure 名、不改 HTTP contract。 + +### 9.1 首个样板切片 + +`module-assets` 先作为 DDD 分层导出样板: + +1. `domain.rs` 对外导出资产对象、实体绑定、访问策略、快照和纯校验函数。 +2. `commands.rs` 对外导出确认资产、绑定实体、资产历史查询等输入。 +3. `application.rs` 对外导出应用结果和纯构建函数。 +4. `errors.rs` 对外导出资产领域错误。 +5. `asset_object_core.rs` 暂作为内部历史实现文件保留,不再由 `lib.rs` 直接对外导出;后续触碰资产规则时继续把实现逐段迁到 DDD 文件。 + +## 10. 阶段性债务表 + +| 债务 | 当前位置 | 迁出目标 | 约束 | +| --- | --- | --- | --- | +| 资产 OSS head 与 reqwest 服务仍在 `module-assets` server-service feature | `module-assets/src/asset_object_service.rs` | `api-server` 应用服务或独立 adapter crate | 不得被 `domain.rs` 引用,不得新增更多 OSS 领域规则 | +| 认证内存 store / 文件持久化仍在 `module-auth` | `module-auth/src/lib.rs` | adapter / repository 目录或 `api-server` 启动恢复层 | 新业务规则不得继续依赖文件路径 | +| `spacetime-module/src/lib.rs` 仍有大量 gameplay 入口 | `spacetime-module/src/lib.rs` | `src/gameplay/*`、`src/custom_world/*`、`src/puzzle/*` | 新增实现禁止继续堆回根入口 | +| 部分 `module-*` 仍是单文件领域实现 | 多个 `module-*` 的 `src/lib.rs` | 对应 DDD 文件 | 每次触碰模块时顺手迁移相关片段 | +| runtime story 兼容层仍存在 | `module-runtime-story-compat`、`api-server/src/runtime_story/compat*`、前端旧 runtime story client | `module-runtime-story`、session scoped 新接口、前端新 client | 本轮允许 breaking change,不再为旧 HTTP shape 保留双接口 | + +## 11. 全局并行执行清单 + +`2026-04-29` 起,`server-rs` DDD 全局重构按 `SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md` 执行。该清单覆盖: + +1. 文档、契约、DDD 骨架和边界检查。 +2. `module-auth`、`module-assets`、`module-ai`、`module-custom-world`、`module-big-fish`、`module-puzzle`、`module-runtime`、RPG gameplay 域和 runtime story 域。 +3. `spacetime-module`、`spacetime-client`、`api-server`、`platform-*` 和前端接入。 +4. 旧层删除、命名收口、全链验证和 Maincloud smoke。 + +## 12. 去兼容层任务 + +`2026-04-29` 起,runtime story / chat 改造按 `SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md` 中的 `WP-RS Runtime Story 去兼容层` 工作包执行。该工作包明确: + +1. 当前 `compat` 层可以物理删除。 +2. 新接口采用 `POST /api/runtime/story/sessions/:sessionId/...` 的 session scoped 口径。 +3. 前端允许同步修改以匹配新 contract。 +4. `api-server` 不再为旧 `worldType / character / monsters / history / context` 请求体保留正式主链分支。 + +## 13. 验收命令 + +阶段验收至少执行: + +```powershell +node scripts/check-server-rs-ddd-boundaries.mjs +cargo fmt --all --check --manifest-path server-rs/Cargo.toml +cargo test --workspace --manifest-path server-rs/Cargo.toml +cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml +npm run api-server:maincloud +npm run check:encoding +``` + +若 `npm run api-server:maincloud` 因本机未配置 Maincloud 数据库或令牌失败,必须记录具体错误;不能改用旧后端重启命令。 diff --git a/docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md b/docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md new file mode 100644 index 00000000..542b8bb8 --- /dev/null +++ b/docs/technical/SERVER_RS_DDD_PARALLEL_TASKLIST_2026-04-29.md @@ -0,0 +1,310 @@ +# server-rs DDD 全局并行任务清单(2026-04-29) + +## 1. 目标与范围 + +本文件是 `server-rs` DDD 一次性重构的总任务清单,覆盖所有后端 crate、SpacetimeDB adapter、HTTP/BFF、共享契约、平台能力和前端接入。runtime story 去兼容层不再单独维护专项清单,统一归入本文的 `WP-RS` 工作包。 + +本轮目标: + +1. 全部业务规则沉到 `module-*`。 +2. `spacetime-module` 只保留 SpacetimeDB table、reducer、procedure、row mapper、事务编排和 event table。 +3. `api-server` 只保留 HTTP/BFF、鉴权、SSE、请求响应映射、SpacetimeDB client 调用和平台服务编排。 +4. `platform-*` 只承载外部副作用实现。 +5. `shared-contracts` 冻结 HTTP/前端 DTO;`shared-kernel` 承载跨领域纯值处理。 +6. 前端只消费后端新接口和后端投影,不承接正式业务真相。 + +用户已明确允许去掉现有兼容层并修改前端以匹配新接口,因此全局任务不以旧接口兼容为约束;任何 breaking change 必须记录在对应任务交接和 API 文档中。 + +## 2. 全局依赖图 + +```mermaid +flowchart TD + G0["G0 文档、边界、冻结窗口"] + G1["G1 契约与路由矩阵"] + G2["G2 module-* DDD 骨架与边界检查"] + A["WP-A Auth"] + AS["WP-AS Assets"] + AI["WP-AI AI Task"] + CW["WP-CW Custom World"] + BF["WP-BF Big Fish"] + PZ["WP-PZ Puzzle"] + RT["WP-RT Runtime/Profile/Save"] + RPG["WP-RPG Gameplay 域"] + RS["WP-RS Runtime Story 去兼容层"] + ST["WP-ST SpacetimeDB Adapter"] + SC["WP-SC Spacetime Client"] + API["WP-API api-server BFF"] + PF["WP-PF platform side effects"] + FE["WP-FE Frontend Clients/UI"] + DEL["WP-DEL 删除旧层与命名收口"] + V["WP-V 全链验证与发布 smoke"] + + G0 --> G1 + G0 --> G2 + G1 --> A + G1 --> AS + G1 --> AI + G1 --> CW + G1 --> BF + G1 --> PZ + G1 --> RT + G1 --> RPG + G1 --> RS + G2 --> A + G2 --> AS + G2 --> AI + G2 --> CW + G2 --> BF + G2 --> PZ + G2 --> RT + G2 --> RPG + G2 --> RS + A --> ST + AS --> ST + AI --> ST + CW --> ST + BF --> ST + PZ --> ST + RT --> ST + RPG --> ST + RS --> ST + ST --> SC + SC --> API + PF --> API + API --> FE + FE --> DEL + API --> DEL + ST --> DEL + DEL --> V +``` + +## 3. 并行分批 + +### 3.1 第一批:冻结边界 + +只能串行完成,避免后续并行任务各自定义接口。 + +1. `G0 文档、边界、冻结窗口` +2. `G1 契约与路由矩阵` +3. `G2 module-* DDD 骨架与边界检查` + +### 3.2 第二批:领域纯规则并行迁移 + +第二批互相并行,但每个任务只能改自己的 `module-*` 和对应文档。 + +1. `WP-A Auth` +2. `WP-AS Assets` +3. `WP-AI AI Task` +4. `WP-CW Custom World` +5. `WP-BF Big Fish` +6. `WP-PZ Puzzle` +7. `WP-RT Runtime/Profile/Save` +8. `WP-RPG Gameplay 域` +9. `WP-RS Runtime Story 去兼容层` + +### 3.3 第三批:adapter 和 BFF 接线 + +领域任务有稳定应用结果后启动。 + +1. `WP-ST SpacetimeDB Adapter` +2. `WP-SC Spacetime Client` +3. `WP-PF platform side effects` +4. `WP-API api-server BFF` + +### 3.4 第四批:前端与旧层删除 + +后端新接口可用后启动。 + +1. `WP-FE Frontend Clients/UI` +2. `WP-DEL 删除旧层与命名收口` +3. `WP-V 全链验证与发布 smoke` + +## 4. 工作包总表 + +| 工作包 | 可并行条件 | 主要文件边界 | 禁止触碰 | 交付物 | 验收 | +| --- | --- | --- | --- | --- | --- | +| G0 文档、边界、冻结窗口 | 首个串行 | `PLAN.md`、`docs/technical/*DDD*`、`docs/planning/*` | 业务代码 | 全局任务清单、专项清单索引、阶段性交接模板 | 编码检查通过 | +| G1 契约与路由矩阵 | G0 后 | `shared-contracts`、`packages/shared/src/contracts/*`、API 路由索引 | 领域实现 | DTO 分组、breaking change 清单、前后端路由矩阵 | shared contract 测试通过 | +| G2 DDD 骨架与边界检查 | G0 后 | `module-*` 骨架、`scripts/check-server-rs-ddd-boundaries.mjs` | 业务重写 | 所有 `module-*` 具备 `domain/commands/application/events/errors`,检查脚本覆盖禁用依赖 | `npm.cmd run check:server-rs-ddd` | +| WP-A Auth | G1/G2 后 | `module-auth`、`spacetime-module/src/auth*`、`api-server/src/auth*`、`platform-auth` | 其他玩法域 | 账号、会话、验证码、微信绑定领域化;真实短信/微信在 platform | `cargo test -p module-auth`,auth API 测试 | +| WP-AS Assets | G1/G2 后 | `module-assets`、`spacetime-module/src/asset_metadata/*`、资产 API、OSS adapter | 玩法业务规则 | 资产对象与绑定规则纯化;OSS head/upload 移出领域核心 | `cargo test -p module-assets`,资产 facade 测试 | +| WP-AI AI Task | G1/G2 后 | `module-ai`、`spacetime-module/src/ai/*`、AI task API | LLM prompt 业务规则 | AI task/stage/chunk/result 状态机领域化 | `cargo test -p module-ai`,AI task reducer/procedure smoke | +| WP-CW Custom World | G1/G2 后 | `module-custom-world`、`spacetime-module/src/custom_world/*`、`api-server` custom world 路由、前端创作 client | Big Fish/Puzzle | profile、agent session、draft card、gallery、publish gate 领域化;LLM 留在 API/platform | `cargo test -p module-custom-world`,custom world 定向测试 | +| WP-BF Big Fish | G1/G2 后 | `module-big-fish`、`spacetime-module/src/big_fish/*`、Big Fish API、Big Fish 前端 client | Puzzle/RPG | 会话、草稿、素材槽、运行态纯规则;草稿校验下沉 | `cargo test -p module-big-fish`,Big Fish API 测试 | +| WP-PZ Puzzle | G1/G2 后 | `module-puzzle`、`spacetime-module/src/puzzle*`、Puzzle API、Puzzle 前端 client | Big Fish/RPG | Agent session、work profile、runtime run、排行榜规则领域化 | `cargo test -p module-puzzle`,Puzzle 定向测试 | +| WP-RT Runtime/Profile/Save | G1/G2 后 | `module-runtime`、`spacetime-module/src/runtime/*`、runtime/save/profile API | RPG story 规则 | runtime setting、snapshot、wallet、played world、save archive 领域化 | `cargo test -p module-runtime`,runtime API 测试 | +| WP-RPG Gameplay 域 | G1/G2 后 | `module-combat`、`module-inventory`、`module-npc`、`module-progression`、`module-quest`、`module-runtime-item`、`module-story` | 创作域 | 战斗、背包、NPC、成长、任务、宝箱、story session 纯规则与跨域事件 | 各 module 测试;跨域应用结果测试 | +| WP-RS Runtime Story 去兼容层 | G1/G2 后 | `module-runtime-story`、`api-server/src/runtime_story/*`、`src/hooks/rpg-runtime-story/*` | 非 RPG 创作域 | 删除 compat 层、session scoped 新接口、前端匹配新接口 | 按专项文档验收 | +| WP-ST SpacetimeDB Adapter | 领域任务输出稳定后 | `spacetime-module/src/**`、`migration.rs`、表目录 | `api-server` 业务逻辑 | table/reducer/procedure/mapper/queries 按上下文拆分;必要 event/projection table | `cargo check -p spacetime-module`,需要时 `spacetime build/generate` | +| WP-SC Spacetime Client | WP-ST 接口稳定后 | `spacetime-client/src/**`、绑定 mapper | 领域规则 | typed facade、错误映射、row snapshot mapper | `cargo check -p spacetime-client` | +| WP-PF platform side effects | 可与 WP-API 并行 | `platform-*`、`api-server` platform 接线 | 领域状态机 | LLM、OSS、SMS、微信等副作用统一 adapter | platform crate 测试或 API smoke | +| WP-API api-server BFF | WP-SC/PF 可用后 | `api-server/src/**` | SpacetimeDB table 定义、领域主规则 | 路由、鉴权、SSE、请求响应映射、平台编排收口 | `cargo test -p api-server`,`cargo check -p api-server` | +| WP-FE Frontend Clients/UI | G1 和 WP-API 接口稳定后 | `src/services/**`、`src/hooks/**`、`src/components/**` | 后端规则复刻 | API client、hooks、UI 流程对齐新 contract;删除前端正式规则 | vitest/ESLint 定向测试 | +| WP-DEL 删除旧层与命名收口 | 新接口与前端迁移后 | 旧 compat、旧 facade、旧 contract、旧测试 | 新主链 | 物理删除旧入口、旧命名、旧 fixture 中非必要样本 | 搜索无运行代码引用旧层 | +| WP-V 全链验证与发布 smoke | 最后 | 文档、测试脚本、README | 新功能扩展 | 全链命令、Maincloud smoke、文档交接 | 第 8 节命令通过或记录非本轮阻塞 | + +## 5. 工作包边界细则 + +### 5.1 G1 契约与路由矩阵 + +必须先冻结: + +1. 当前保留、重命名、删除的 HTTP 路由。 +2. 每个前端页面对应的 query/result DTO。 +3. 每个写入接口对应的 command DTO。 +4. breaking change 清单。 +5. API 错误 envelope 与中文错误字段。 + +禁止在 G1 中实现业务逻辑。 + +### 5.2 module-* 领域任务通用规则 + +每个 `module-*` 工作包必须输出: + +1. `domain.rs` 或 `domain/*`:聚合和值对象。 +2. `commands.rs`:写入输入。 +3. `application.rs`:纯应用用例,输出应用结果或领域事件。 +4. `events.rs`:领域事件。 +5. `errors.rs`:领域错误。 +6. 单元测试。 + +禁止: + +1. Axum / HTTP status。 +2. SpacetimeDB `ReducerContext`、table API。 +3. reqwest、OSS、真实 LLM、文件系统。 +4. `mapper.rs`。 + +### 5.3 WP-ST SpacetimeDB Adapter + +按上下文拆到: + +```text +server-rs/crates/spacetime-module/src// +├─ mod.rs +├─ tables.rs +├─ reducers.rs +├─ procedures.rs +├─ mapper.rs +└─ queries.rs +``` + +当前已有模块可渐进对齐,但新增实现不得继续堆回 `lib.rs`。 + +SpacetimeDB 硬要求: + +1. reducer 使用 `&ReducerContext`。 +2. 预期失败返回 `Result<(), String>` 或 procedure 错误,不用 panic 表达业务失败。 +3. 授权基于 `ctx.sender()`。 +4. 表访问使用 `ctx.db.table()`。 +5. 更新只通过主键,非主键更新走 delete + insert。 +6. reducer 无网络、文件、外部随机数和全局可变状态。 + +### 5.4 WP-API api-server + +允许: + +1. 鉴权与 request context。 +2. route handler / extractor。 +3. DTO 映射。 +4. 调用 `spacetime-client`。 +5. 调用 `platform-*`。 +6. SSE stream。 + +禁止: + +1. 大段领域分支。 +2. SpacetimeDB table 定义。 +3. 为旧接口继续保留双主链。 + +### 5.5 WP-FE Frontend Clients/UI + +前端只负责表现: + +1. 调用 API。 +2. 管理 loading/error/transition。 +3. 渲染服务端 query/result DTO。 +4. 保存 UI 临时输入。 + +禁止: + +1. 正式业务状态机。 +2. 正式任务、战斗、背包、NPC、章节、世界 mutation 规则。 +3. prompt 正式组装。 +4. 绕过后端直接写真相。 + +## 6. 关键依赖与防冲突边界 + +1. `shared-contracts` 由 G1 统一所有权,其他任务只消费,不私自改 DTO shape。 +2. `spacetime-module/src/lib.rs` 由 WP-ST 统一所有权,领域任务不直接改根入口。 +3. `api-server/src/app.rs` 路由挂载由 WP-API 统一所有权。 +4. `src/services/aiService.ts`、`src/services/rpg-runtime/*` 由 WP-FE 统一所有权。 +5. `module-runtime-story` 与 runtime story 新接口由 WP-RS 所有,不和 WP-RPG 混写。 +6. 若某任务必须改别人的边界文件,先在交接记录中写明改动动机和待合流点。 + +## 7. 文档产出要求 + +每个工作包完成后必须更新或新增对应文档: + +1. 技术方案:放 `docs/technical/`。 +2. 审计和迁移验证:放 `docs/audits/engineering/`。 +3. 用户体验或踩坑:放 `docs/experience/`。 +4. 表结构变化:更新 `docs/technical/SPACETIMEDB_TABLE_CATALOG.md`。 +5. API 路由变化:更新 `docs/technical/RUST_API_SERVER_ROUTE_INDEX_2026-04-22.md` 或新增新版路由索引。 + +交接摘要必须包含: + +1. 已改文件。 +2. 未完成项。 +3. 依赖的上游/下游任务。 +4. 验证命令与结果。 +5. 是否触碰表结构、是否同步 `migration.rs`。 + +## 8. 全局验收命令 + +基础检查: + +```powershell +npm.cmd run check:server-rs-ddd +cargo fmt --all --check --manifest-path server-rs/Cargo.toml +cargo check -p api-server --manifest-path server-rs/Cargo.toml +cargo check -p spacetime-client --manifest-path server-rs/Cargo.toml +cargo check -p spacetime-module --manifest-path server-rs/Cargo.toml +npm.cmd run check:encoding +``` + +领域测试: + +```powershell +cargo test -p module-ai -p module-assets -p module-auth -p module-big-fish -p module-combat -p module-custom-world -p module-inventory -p module-npc -p module-progression -p module-puzzle -p module-quest -p module-runtime -p module-runtime-item -p module-runtime-story -p module-story --manifest-path server-rs/Cargo.toml +``` + +接口与前端测试按触碰范围执行: + +```powershell +cargo test -p api-server --manifest-path server-rs/Cargo.toml +npm.cmd run test -- src/services +npm.cmd run test -- src/hooks +``` + +后端代码变更后必须执行: + +```powershell +npm.cmd run api-server:maincloud +``` + +若改 SpacetimeDB table / reducer / procedure: + +```powershell +spacetime build +spacetime generate --lang typescript --out-dir <前端绑定目录> --module-path server-rs/crates/spacetime-module +spacetime describe --json +``` + +不能用旧后端重启命令替代 `npm.cmd run api-server:maincloud`。 + +## 9. 专项任务引用 + +当前不再单独维护专项清单。`WP-RS Runtime Story 去兼容层` 已内联在本文第 4 节工作包总表中。 + +后续如果某个工作包仍存在编码级歧义,必须先在本文补齐边界;只有单个工作包过大且无法在本文清晰承载时,才新增对应专项清单。 diff --git a/package.json b/package.json index fb91884e..5132d144 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "preview": "node scripts/vite-cli.mjs preview", "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\"", "check:encoding": "node scripts/check-encoding.mjs", + "check:server-rs-ddd": "node scripts/check-server-rs-ddd-boundaries.mjs", "lint:eslint": "eslint . --ext .ts,.tsx,.js,.mjs,.cjs --max-warnings 0", "lint:guardrails": "npm run lint:eslint", "typecheck": "tsc -p tsconfig.typecheck-guardrails.json --noEmit", diff --git a/scripts/check-server-rs-ddd-boundaries.mjs b/scripts/check-server-rs-ddd-boundaries.mjs new file mode 100644 index 00000000..3963e951 --- /dev/null +++ b/scripts/check-server-rs-ddd-boundaries.mjs @@ -0,0 +1,155 @@ +import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs'; +import { basename, join, relative } from 'node:path'; + +const repoRoot = process.cwd(); +const cratesDir = join(repoRoot, 'server-rs', 'crates'); +const requiredModuleFiles = [ + 'domain.rs', + 'commands.rs', + 'application.rs', + 'events.rs', + 'errors.rs', +]; +const requiredLibModules = ['domain', 'commands', 'application', 'events', 'errors']; +const forbiddenModuleWidePatterns = [ + { + pattern: /\baxum::/u, + message: 'module-* 不允许直接依赖 Axum', + }, + { + pattern: /\bspacetimedb::(?:table|reducer|procedure|ReducerContext|ProcedureContext|Table)\b/u, + message: 'module-* 不允许声明 SpacetimeDB table/reducer/procedure 或直接操作表', + }, +]; +const forbiddenCorePatterns = [ + { + pattern: /\breqwest::/u, + message: 'DDD 核心文件不允许直接依赖 reqwest', + }, + { + pattern: /\bplatform_oss::/u, + message: 'DDD 核心文件不允许直接依赖 OSS adapter', + }, + { + pattern: /\bplatform_llm::/u, + message: 'DDD 核心文件不允许直接依赖 LLM adapter', + }, + { + pattern: /\bspacetime_client::/u, + message: 'DDD 核心文件不允许直接依赖 SpacetimeDB client adapter', + }, + { + pattern: /\bstd::fs\b/u, + message: 'DDD 核心文件不允许直接访问文件系统', + }, + { + pattern: /\btokio::/u, + message: 'DDD 核心文件不允许绑定异步运行时', + }, +]; + +function normalizePath(path) { + return path.replace(/\\/gu, '/'); +} + +function readText(path) { + return readFileSync(path, 'utf8'); +} + +function listRustFiles(dir) { + const files = []; + + function walk(currentDir) { + for (const name of readdirSync(currentDir)) { + const fullPath = join(currentDir, name); + const stat = statSync(fullPath); + + if (stat.isDirectory()) { + walk(fullPath); + continue; + } + + if (name.endsWith('.rs')) { + files.push(fullPath); + } + } + } + + walk(dir); + return files; +} + +function collectModuleCrates() { + return readdirSync(cratesDir) + .filter((name) => name.startsWith('module-')) + .filter((name) => existsSync(join(cratesDir, name, 'Cargo.toml'))) + .sort(); +} + +const failures = []; +const moduleCrates = collectModuleCrates(); + +for (const crateName of moduleCrates) { + const crateDir = join(cratesDir, crateName); + const srcDir = join(crateDir, 'src'); + const libPath = join(srcDir, 'lib.rs'); + + for (const fileName of requiredModuleFiles) { + const filePath = join(srcDir, fileName); + if (!existsSync(filePath)) { + failures.push(`${crateName} 缺少 DDD 落位文件 src/${fileName}`); + } + } + + if (existsSync(libPath)) { + const libText = readText(libPath); + for (const moduleName of requiredLibModules) { + const moduleDeclaration = new RegExp( + `(?:^|\\n)\\s*(?:pub(?:\\([^)]*\\))?\\s+)?mod\\s+${moduleName}\\s*;`, + 'u', + ); + if (!moduleDeclaration.test(libText)) { + failures.push(`${crateName} 的 lib.rs 缺少模块声明 mod ${moduleName};`); + } + } + } + + for (const rustFile of listRustFiles(srcDir)) { + const relativePath = normalizePath(relative(repoRoot, rustFile)); + const fileName = basename(rustFile); + const text = readText(rustFile); + + if (fileName === 'mapper.rs') { + failures.push(`${relativePath} 不能位于 module-*,mapper 只能放在 adapter crate`); + } + + for (const rule of forbiddenModuleWidePatterns) { + if (rule.pattern.test(text)) { + failures.push(`${relativePath}: ${rule.message}`); + } + } + + const isDddCoreFile = requiredModuleFiles.some((name) => + relativePath.endsWith(`/src/${name}`), + ); + if (!isDddCoreFile) { + continue; + } + + for (const rule of forbiddenCorePatterns) { + if (rule.pattern.test(text)) { + failures.push(`${relativePath}: ${rule.message}`); + } + } + } +} + +if (failures.length > 0) { + console.error('server-rs DDD boundary check failed:'); + for (const failure of failures) { + console.error(`- ${failure}`); + } + process.exit(1); +} + +console.log(`server-rs DDD boundary check passed for ${moduleCrates.length} module crate(s).`); diff --git a/server-rs/README.md b/server-rs/README.md index 55fbec94..61a16c62 100644 --- a/server-rs/README.md +++ b/server-rs/README.md @@ -97,6 +97,18 @@ 3. 前端或 Node 侧的 SpacetimeDB TypeScript SDK、订阅、绑定使用按 `spacetimedb-typescript`、`spacetimedb-concepts` 执行。 4. 若仓库内旧实现或旧文档与这些 skill 冲突,先修正文档和方案,再继续编码。 +## 6. DDD 目录与边界 + +`2026-04-28` 起,`server-rs` 进入 DDD 边界收口阶段,完整规则见 [../docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md](../docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md)。 + +新增或迁移业务代码时必须遵守: + +1. `module-*` 统一维护 `domain.rs`、`commands.rs`、`application.rs`、`events.rs`、`errors.rs`。 +2. `module-*` 不新增 Axum、reqwest、OSS、LLM、文件系统、SpacetimeDB table/reducer/procedure 依赖。 +3. `mapper.rs` 只允许出现在 `api-server`、`spacetime-module`、`spacetime-client` 等 adapter crate。 +4. `spacetime-module` 新增业务入口前先确认是否已有对应上下文目录,禁止继续把大段业务流程堆回 `src/lib.rs`。 +5. 根目录可执行 `npm run check:server-rs-ddd` 检查第一阶段 DDD 骨架与绝对边界。 + ## 5. 关联文档 1. [../docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md](../docs/technical/SPACETIMEDB_AXUM_OSS_BACKEND_REWRITE_DESIGN_2026-04-20.md) diff --git a/server-rs/crates/module-ai/src/application.rs b/server-rs/crates/module-ai/src/application.rs new file mode 100644 index 00000000..0d7b7129 --- /dev/null +++ b/server-rs/crates/module-ai/src/application.rs @@ -0,0 +1,4 @@ +//! AI 应用编排过渡落位。 +//! +//! 这里仅返回纯应用结果或领域事件;真实 LLM 调用继续留在 `platform-llm` +//! 与 `api-server` 编排层。 diff --git a/server-rs/crates/module-ai/src/commands.rs b/server-rs/crates/module-ai/src/commands.rs new file mode 100644 index 00000000..7c013929 --- /dev/null +++ b/server-rs/crates/module-ai/src/commands.rs @@ -0,0 +1,4 @@ +//! AI 写入命令过渡落位。 +//! +//! 只描述创建任务、推进阶段、追加文本片段和挂接结果引用等用例输入, +//! 不承载外部模型请求或持久化细节。 diff --git a/server-rs/crates/module-ai/src/domain.rs b/server-rs/crates/module-ai/src/domain.rs new file mode 100644 index 00000000..aa3ab37d --- /dev/null +++ b/server-rs/crates/module-ai/src/domain.rs @@ -0,0 +1,4 @@ +//! AI 领域模型过渡落位。 +//! +//! 当前历史实现仍在 `lib.rs`。后续迁移 `AiTask`、阶段、流式片段和结果引用时, +//! 只能放入纯领域类型与状态迁移,不能引入 LLM、HTTP 或 SpacetimeDB adapter。 diff --git a/server-rs/crates/module-ai/src/errors.rs b/server-rs/crates/module-ai/src/errors.rs new file mode 100644 index 00000000..84689dd7 --- /dev/null +++ b/server-rs/crates/module-ai/src/errors.rs @@ -0,0 +1,3 @@ +//! AI 领域错误过渡落位。 +//! +//! 错误必须可被 HTTP adapter 和 SpacetimeDB adapter 显式映射,不能直接绑定状态码。 diff --git a/server-rs/crates/module-ai/src/events.rs b/server-rs/crates/module-ai/src/events.rs new file mode 100644 index 00000000..289edb08 --- /dev/null +++ b/server-rs/crates/module-ai/src/events.rs @@ -0,0 +1,3 @@ +//! AI 领域事件过渡落位。 +//! +//! 用于表达任务开始、阶段完成、任务失败和结果引用挂接等跨上下文事实。 diff --git a/server-rs/crates/module-ai/src/lib.rs b/server-rs/crates/module-ai/src/lib.rs index c63f395f..fc414ea2 100644 --- a/server-rs/crates/module-ai/src/lib.rs +++ b/server-rs/crates/module-ai/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{ collections::HashMap, error::Error, diff --git a/server-rs/crates/module-assets/src/application.rs b/server-rs/crates/module-assets/src/application.rs new file mode 100644 index 00000000..84782f3a --- /dev/null +++ b/server-rs/crates/module-assets/src/application.rs @@ -0,0 +1,8 @@ +//! 资产应用编排落位。 +//! +//! 这里只组合纯校验与应用结果;对象探测、签名和持久化由 adapter 层完成。 + +pub use crate::asset_object_core::{ + AssetEntityBindingProcedureResult, AssetHistoryListResult, AssetObjectProcedureResult, + ConfirmAssetObjectResult, build_asset_entity_binding_input, build_asset_object_upsert_input, +}; diff --git a/server-rs/crates/module-assets/src/commands.rs b/server-rs/crates/module-assets/src/commands.rs new file mode 100644 index 00000000..e9ece91a --- /dev/null +++ b/server-rs/crates/module-assets/src/commands.rs @@ -0,0 +1,7 @@ +//! 资产写入命令落位。 +//! +//! 用于表达确认资产对象、绑定实体槽位和查询资产历史的输入,不直接访问 OSS。 + +pub use crate::asset_object_core::{ + AssetEntityBindingInput, AssetHistoryListInput, AssetObjectUpsertInput, ConfirmAssetObjectInput, +}; diff --git a/server-rs/crates/module-assets/src/domain.rs b/server-rs/crates/module-assets/src/domain.rs new file mode 100644 index 00000000..86ca5df6 --- /dev/null +++ b/server-rs/crates/module-assets/src/domain.rs @@ -0,0 +1,15 @@ +//! 资产领域模型落位。 +//! +//! 当前先通过本文件承接对外领域 API 分层导出,旧实现仍留在 +//! `asset_object_core.rs` 内部文件中,后续再逐段搬入本文件或 `domain/` 子目录。 +//! 本层只允许保留资产对象、实体绑定、访问策略、版本和业务归属等纯规则。 + +pub use crate::asset_object_core::{ + ASSET_BINDING_ID_PREFIX, ASSET_OBJECT_ID_PREFIX, AssetEntityBindingRecord, + AssetEntityBindingSnapshot, AssetHistoryEntryRecord, AssetHistoryEntrySnapshot, + AssetObjectAccessPolicy, AssetObjectRecord, AssetObjectUpsertSnapshot, + INITIAL_ASSET_OBJECT_VERSION, build_asset_entity_binding_record, + build_asset_history_entry_record, build_asset_object_record, generate_asset_binding_id, + generate_asset_object_id, normalize_optional_value, validate_asset_entity_binding_fields, + validate_asset_object_fields, +}; diff --git a/server-rs/crates/module-assets/src/errors.rs b/server-rs/crates/module-assets/src/errors.rs new file mode 100644 index 00000000..a5a61bf5 --- /dev/null +++ b/server-rs/crates/module-assets/src/errors.rs @@ -0,0 +1,5 @@ +//! 资产领域错误落位。 +//! +//! 字段错误和业务错误在这里收口,HTTP 状态码与 SpacetimeDB 字符串错误由 adapter 映射。 + +pub use crate::asset_object_core::AssetObjectFieldError; diff --git a/server-rs/crates/module-assets/src/events.rs b/server-rs/crates/module-assets/src/events.rs new file mode 100644 index 00000000..47c4b000 --- /dev/null +++ b/server-rs/crates/module-assets/src/events.rs @@ -0,0 +1,4 @@ +//! 资产领域事件过渡落位。 +//! +//! 用于表达资产已确认、绑定已变更和资产历史投影待刷新等事实。 +//! 当前阶段暂不新增事件类型,避免在 SpacetimeDB 表未补 event table 前扩散未消费 API。 diff --git a/server-rs/crates/module-assets/src/lib.rs b/server-rs/crates/module-assets/src/lib.rs index ccec64a2..384fd60a 100644 --- a/server-rs/crates/module-assets/src/lib.rs +++ b/server-rs/crates/module-assets/src/lib.rs @@ -1,20 +1,31 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + mod asset_object_core; #[cfg(feature = "server-service")] mod asset_object_service; -pub use asset_object_core::{ - ASSET_BINDING_ID_PREFIX, ASSET_OBJECT_ID_PREFIX, AssetEntityBindingInput, - AssetEntityBindingProcedureResult, AssetEntityBindingRecord, AssetEntityBindingSnapshot, - AssetHistoryEntryRecord, AssetHistoryEntrySnapshot, AssetHistoryListInput, - AssetHistoryListResult, AssetObjectAccessPolicy, AssetObjectFieldError, - AssetObjectProcedureResult, AssetObjectRecord, AssetObjectUpsertInput, - AssetObjectUpsertSnapshot, ConfirmAssetObjectInput, ConfirmAssetObjectResult, - INITIAL_ASSET_OBJECT_VERSION, build_asset_entity_binding_input, - build_asset_entity_binding_record, build_asset_history_entry_record, build_asset_object_record, - build_asset_object_upsert_input, generate_asset_binding_id, generate_asset_object_id, - normalize_optional_value, validate_asset_entity_binding_fields, validate_asset_object_fields, +pub use application::{ + AssetEntityBindingProcedureResult, AssetHistoryListResult, AssetObjectProcedureResult, + ConfirmAssetObjectResult, build_asset_entity_binding_input, build_asset_object_upsert_input, }; #[cfg(feature = "server-service")] pub use asset_object_service::{ AssetObjectService, ConfirmAssetObjectError, InMemoryAssetObjectStore, }; +pub use commands::{ + AssetEntityBindingInput, AssetHistoryListInput, AssetObjectUpsertInput, ConfirmAssetObjectInput, +}; +pub use domain::{ + ASSET_BINDING_ID_PREFIX, ASSET_OBJECT_ID_PREFIX, AssetEntityBindingRecord, + AssetEntityBindingSnapshot, AssetHistoryEntryRecord, AssetHistoryEntrySnapshot, + AssetObjectAccessPolicy, AssetObjectRecord, AssetObjectUpsertSnapshot, + INITIAL_ASSET_OBJECT_VERSION, build_asset_entity_binding_record, + build_asset_history_entry_record, build_asset_object_record, generate_asset_binding_id, + generate_asset_object_id, normalize_optional_value, validate_asset_entity_binding_fields, + validate_asset_object_fields, +}; +pub use errors::AssetObjectFieldError; diff --git a/server-rs/crates/module-auth/src/application.rs b/server-rs/crates/module-auth/src/application.rs new file mode 100644 index 00000000..0ee4d360 --- /dev/null +++ b/server-rs/crates/module-auth/src/application.rs @@ -0,0 +1,3 @@ +//! 认证应用编排过渡落位。 +//! +//! 这里只返回纯应用结果与领域事件;短信 provider、JWT 签发和持久化由外层 adapter 完成。 diff --git a/server-rs/crates/module-auth/src/commands.rs b/server-rs/crates/module-auth/src/commands.rs new file mode 100644 index 00000000..0bb82399 --- /dev/null +++ b/server-rs/crates/module-auth/src/commands.rs @@ -0,0 +1,3 @@ +//! 认证写入命令过渡落位。 +//! +//! 用于表达密码入口、手机号验证码、微信登录、刷新会话签发和吊销等用例输入。 diff --git a/server-rs/crates/module-auth/src/domain.rs b/server-rs/crates/module-auth/src/domain.rs new file mode 100644 index 00000000..96d1450c --- /dev/null +++ b/server-rs/crates/module-auth/src/domain.rs @@ -0,0 +1,4 @@ +//! 认证领域模型过渡落位。 +//! +//! 后续迁移账号、刷新会话、验证码和微信绑定聚合时,只保留认证规则; +//! 文件持久化、真实短信发送、cookie 写入和 HTTP 上下文都不属于领域核心。 diff --git a/server-rs/crates/module-auth/src/errors.rs b/server-rs/crates/module-auth/src/errors.rs new file mode 100644 index 00000000..6dbf5350 --- /dev/null +++ b/server-rs/crates/module-auth/src/errors.rs @@ -0,0 +1,3 @@ +//! 认证领域错误过渡落位。 +//! +//! 领域错误保持可测试、可映射,不能直接依赖 Axum、cookie 或平台 provider 错误模型。 diff --git a/server-rs/crates/module-auth/src/events.rs b/server-rs/crates/module-auth/src/events.rs new file mode 100644 index 00000000..cc43780e --- /dev/null +++ b/server-rs/crates/module-auth/src/events.rs @@ -0,0 +1,3 @@ +//! 认证领域事件过渡落位。 +//! +//! 用于表达用户创建、会话签发/吊销、手机号验证通过和微信身份绑定等事实。 diff --git a/server-rs/crates/module-auth/src/lib.rs b/server-rs/crates/module-auth/src/lib.rs index 57005c54..a23d30ef 100644 --- a/server-rs/crates/module-auth/src/lib.rs +++ b/server-rs/crates/module-auth/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{ collections::HashMap, error::Error, diff --git a/server-rs/crates/module-big-fish/src/application.rs b/server-rs/crates/module-big-fish/src/application.rs new file mode 100644 index 00000000..51eb1590 --- /dev/null +++ b/server-rs/crates/module-big-fish/src/application.rs @@ -0,0 +1,3 @@ +//! 大鱼吃小鱼应用编排过渡落位。 +//! +//! 这里只组合领域规则并返回结果或事件,不直接调用外部图片、视频或存储服务。 diff --git a/server-rs/crates/module-big-fish/src/commands.rs b/server-rs/crates/module-big-fish/src/commands.rs new file mode 100644 index 00000000..c53f4d56 --- /dev/null +++ b/server-rs/crates/module-big-fish/src/commands.rs @@ -0,0 +1,3 @@ +//! 大鱼吃小鱼写入命令过渡落位。 +//! +//! 用于表达创建会话、写入消息、更新资产槽和推进运行态等输入。 diff --git a/server-rs/crates/module-big-fish/src/domain.rs b/server-rs/crates/module-big-fish/src/domain.rs new file mode 100644 index 00000000..8057d81f --- /dev/null +++ b/server-rs/crates/module-big-fish/src/domain.rs @@ -0,0 +1,4 @@ +//! 大鱼吃小鱼领域模型过渡落位。 +//! +//! 后续迁移创作会话、资产槽和运行态聚合时,只保留玩法状态与规则; +//! 图片生成、OSS 与 HTTP handler 均留在 adapter 层。 diff --git a/server-rs/crates/module-big-fish/src/errors.rs b/server-rs/crates/module-big-fish/src/errors.rs new file mode 100644 index 00000000..aff78b03 --- /dev/null +++ b/server-rs/crates/module-big-fish/src/errors.rs @@ -0,0 +1,3 @@ +//! 大鱼吃小鱼领域错误过渡落位。 +//! +//! 错误只表达玩法规则失败,由 HTTP 和 SpacetimeDB adapter 分别映射展示。 diff --git a/server-rs/crates/module-big-fish/src/events.rs b/server-rs/crates/module-big-fish/src/events.rs new file mode 100644 index 00000000..07522de8 --- /dev/null +++ b/server-rs/crates/module-big-fish/src/events.rs @@ -0,0 +1,3 @@ +//! 大鱼吃小鱼领域事件过渡落位。 +//! +//! 用于表达草稿变化、资产槽变化和运行态 tick 等事实。 diff --git a/server-rs/crates/module-big-fish/src/lib.rs b/server-rs/crates/module-big-fish/src/lib.rs index 74bd0ea7..bab85a70 100644 --- a/server-rs/crates/module-big-fish/src/lib.rs +++ b/server-rs/crates/module-big-fish/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-combat/src/application.rs b/server-rs/crates/module-combat/src/application.rs new file mode 100644 index 00000000..8bae736d --- /dev/null +++ b/server-rs/crates/module-combat/src/application.rs @@ -0,0 +1,3 @@ +//! 战斗应用编排过渡落位。 +//! +//! 这里只返回结算结果与待处理事件,不直接写入其他上下文表。 diff --git a/server-rs/crates/module-combat/src/commands.rs b/server-rs/crates/module-combat/src/commands.rs new file mode 100644 index 00000000..e4281bef --- /dev/null +++ b/server-rs/crates/module-combat/src/commands.rs @@ -0,0 +1,3 @@ +//! 战斗写入命令过渡落位。 +//! +//! 用于表达创建战斗、使用技能、逃离和结算等输入,不直接携带表行类型。 diff --git a/server-rs/crates/module-combat/src/domain.rs b/server-rs/crates/module-combat/src/domain.rs new file mode 100644 index 00000000..b0ea813e --- /dev/null +++ b/server-rs/crates/module-combat/src/domain.rs @@ -0,0 +1,4 @@ +//! 战斗领域模型过渡落位。 +//! +//! 后续迁移 `BattleState` 与行动结算规则时,只保留单聚合内部状态变化; +//! 背包奖励、成长记账和任务联动由应用服务或 SpacetimeDB 事务 adapter 编排。 diff --git a/server-rs/crates/module-combat/src/errors.rs b/server-rs/crates/module-combat/src/errors.rs new file mode 100644 index 00000000..d39ae03b --- /dev/null +++ b/server-rs/crates/module-combat/src/errors.rs @@ -0,0 +1,3 @@ +//! 战斗领域错误过渡落位。 +//! +//! 错误保持纯领域语义,不能绑定 HTTP 状态码或 SpacetimeDB 字符串格式。 diff --git a/server-rs/crates/module-combat/src/events.rs b/server-rs/crates/module-combat/src/events.rs new file mode 100644 index 00000000..da3f7d73 --- /dev/null +++ b/server-rs/crates/module-combat/src/events.rs @@ -0,0 +1,3 @@ +//! 战斗领域事件过渡落位。 +//! +//! 用于表达战斗胜利、切磋完成、奖励待发放和战斗被终止等事实。 diff --git a/server-rs/crates/module-combat/src/lib.rs b/server-rs/crates/module-combat/src/lib.rs index 7fd22c1f..70471778 100644 --- a/server-rs/crates/module-combat/src/lib.rs +++ b/server-rs/crates/module-combat/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use module_runtime_item::{ diff --git a/server-rs/crates/module-custom-world/src/application.rs b/server-rs/crates/module-custom-world/src/application.rs new file mode 100644 index 00000000..ab49352e --- /dev/null +++ b/server-rs/crates/module-custom-world/src/application.rs @@ -0,0 +1,3 @@ +//! 自定义世界应用编排过渡落位。 +//! +//! 这里只组合领域规则并返回草稿、发布门禁、投影刷新等结果或事件。 diff --git a/server-rs/crates/module-custom-world/src/commands.rs b/server-rs/crates/module-custom-world/src/commands.rs new file mode 100644 index 00000000..2bca44c3 --- /dev/null +++ b/server-rs/crates/module-custom-world/src/commands.rs @@ -0,0 +1,3 @@ +//! 自定义世界写入命令过渡落位。 +//! +//! 用于表达会话创建、消息写入、草稿更新、发布和下架等用例输入。 diff --git a/server-rs/crates/module-custom-world/src/domain.rs b/server-rs/crates/module-custom-world/src/domain.rs new file mode 100644 index 00000000..e1ad6d84 --- /dev/null +++ b/server-rs/crates/module-custom-world/src/domain.rs @@ -0,0 +1,4 @@ +//! 自定义世界领域模型过渡落位。 +//! +//! 后续迁移 profile、Agent 会话、草稿卡、发布门禁和画廊投影规则时, +//! 只保留纯领域结构;LLM 推理、SSE 和 OSS 均留在外层 adapter。 diff --git a/server-rs/crates/module-custom-world/src/errors.rs b/server-rs/crates/module-custom-world/src/errors.rs new file mode 100644 index 00000000..9481fbcd --- /dev/null +++ b/server-rs/crates/module-custom-world/src/errors.rs @@ -0,0 +1,3 @@ +//! 自定义世界领域错误过渡落位。 +//! +//! 错误只表达世界创作规则失败,由 adapter 显式映射为 HTTP 或 reducer 错误。 diff --git a/server-rs/crates/module-custom-world/src/events.rs b/server-rs/crates/module-custom-world/src/events.rs new file mode 100644 index 00000000..078e28f7 --- /dev/null +++ b/server-rs/crates/module-custom-world/src/events.rs @@ -0,0 +1,3 @@ +//! 自定义世界领域事件过渡落位。 +//! +//! 用于表达草稿变化、profile 发布、画廊投影刷新和 Agent 操作进度变化。 diff --git a/server-rs/crates/module-custom-world/src/lib.rs b/server-rs/crates/module-custom-world/src/lib.rs index 2898856b..405a5aab 100644 --- a/server-rs/crates/module-custom-world/src/lib.rs +++ b/server-rs/crates/module-custom-world/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-inventory/src/application.rs b/server-rs/crates/module-inventory/src/application.rs new file mode 100644 index 00000000..bf76943f --- /dev/null +++ b/server-rs/crates/module-inventory/src/application.rs @@ -0,0 +1,3 @@ +//! 背包应用编排过渡落位。 +//! +//! 这里只返回背包变更结果和领域事件,不直接访问持久化。 diff --git a/server-rs/crates/module-inventory/src/commands.rs b/server-rs/crates/module-inventory/src/commands.rs new file mode 100644 index 00000000..cc2135b4 --- /dev/null +++ b/server-rs/crates/module-inventory/src/commands.rs @@ -0,0 +1,3 @@ +//! 背包写入命令过渡落位。 +//! +//! 用于表达授予物品、装备、卸下、消耗和整理等输入。 diff --git a/server-rs/crates/module-inventory/src/domain.rs b/server-rs/crates/module-inventory/src/domain.rs new file mode 100644 index 00000000..0378ad01 --- /dev/null +++ b/server-rs/crates/module-inventory/src/domain.rs @@ -0,0 +1,4 @@ +//! 背包领域模型过渡落位。 +//! +//! 后续迁移背包槽、装备槽、堆叠和消耗规则时,只保留物品状态变化; +//! SpacetimeDB 表查询写回由 adapter 处理。 diff --git a/server-rs/crates/module-inventory/src/errors.rs b/server-rs/crates/module-inventory/src/errors.rs new file mode 100644 index 00000000..1d1f235c --- /dev/null +++ b/server-rs/crates/module-inventory/src/errors.rs @@ -0,0 +1,3 @@ +//! 背包领域错误过渡落位。 +//! +//! 错误保持可测试的业务语义,例如数量不足、槽位冲突和物品不存在。 diff --git a/server-rs/crates/module-inventory/src/events.rs b/server-rs/crates/module-inventory/src/events.rs new file mode 100644 index 00000000..d64bba27 --- /dev/null +++ b/server-rs/crates/module-inventory/src/events.rs @@ -0,0 +1,3 @@ +//! 背包领域事件过渡落位。 +//! +//! 用于表达物品获得、物品消耗、装备变化和槽位投影变化等事实。 diff --git a/server-rs/crates/module-inventory/src/lib.rs b/server-rs/crates/module-inventory/src/lib.rs index 69510fca..29f081f1 100644 --- a/server-rs/crates/module-inventory/src/lib.rs +++ b/server-rs/crates/module-inventory/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-npc/src/application.rs b/server-rs/crates/module-npc/src/application.rs new file mode 100644 index 00000000..c248bbaf --- /dev/null +++ b/server-rs/crates/module-npc/src/application.rs @@ -0,0 +1,3 @@ +//! NPC 应用编排过渡落位。 +//! +//! 这里只返回关系变化、推荐动作和跨上下文事件,不直接写战斗表。 diff --git a/server-rs/crates/module-npc/src/commands.rs b/server-rs/crates/module-npc/src/commands.rs new file mode 100644 index 00000000..323c4985 --- /dev/null +++ b/server-rs/crates/module-npc/src/commands.rs @@ -0,0 +1,3 @@ +//! NPC 写入命令过渡落位。 +//! +//! 用于表达聊天、帮助、送礼、招募、开战和切磋等输入。 diff --git a/server-rs/crates/module-npc/src/domain.rs b/server-rs/crates/module-npc/src/domain.rs new file mode 100644 index 00000000..67d8ed08 --- /dev/null +++ b/server-rs/crates/module-npc/src/domain.rs @@ -0,0 +1,4 @@ +//! NPC 领域模型过渡落位。 +//! +//! 后续迁移 NPC 状态、关系、好感、招募和互动规则时,只保留社交领域变化; +//! 战斗初始化和跨表事务由外层编排。 diff --git a/server-rs/crates/module-npc/src/errors.rs b/server-rs/crates/module-npc/src/errors.rs new file mode 100644 index 00000000..d90a0c8e --- /dev/null +++ b/server-rs/crates/module-npc/src/errors.rs @@ -0,0 +1,3 @@ +//! NPC 领域错误过渡落位。 +//! +//! 错误只表达互动规则失败,例如状态不允许、好感不足或目标非法。 diff --git a/server-rs/crates/module-npc/src/events.rs b/server-rs/crates/module-npc/src/events.rs new file mode 100644 index 00000000..be1479d8 --- /dev/null +++ b/server-rs/crates/module-npc/src/events.rs @@ -0,0 +1,3 @@ +//! NPC 领域事件过渡落位。 +//! +//! 用于表达好感变化、关系变化、NPC 被招募和战斗请求产生等事实。 diff --git a/server-rs/crates/module-npc/src/lib.rs b/server-rs/crates/module-npc/src/lib.rs index 4cd756c6..46685a03 100644 --- a/server-rs/crates/module-npc/src/lib.rs +++ b/server-rs/crates/module-npc/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-progression/src/application.rs b/server-rs/crates/module-progression/src/application.rs new file mode 100644 index 00000000..45c21ae8 --- /dev/null +++ b/server-rs/crates/module-progression/src/application.rs @@ -0,0 +1,3 @@ +//! 成长应用编排过渡落位。 +//! +//! 这里只返回等级变化、预算变化和账本结果,不直接读取其他上下文表。 diff --git a/server-rs/crates/module-progression/src/commands.rs b/server-rs/crates/module-progression/src/commands.rs new file mode 100644 index 00000000..9f33f42a --- /dev/null +++ b/server-rs/crates/module-progression/src/commands.rs @@ -0,0 +1,3 @@ +//! 成长写入命令过渡落位。 +//! +//! 用于表达授予经验、创建章节预算、结算章节节奏等输入。 diff --git a/server-rs/crates/module-progression/src/domain.rs b/server-rs/crates/module-progression/src/domain.rs new file mode 100644 index 00000000..afab1f2c --- /dev/null +++ b/server-rs/crates/module-progression/src/domain.rs @@ -0,0 +1,4 @@ +//! 成长领域模型过渡落位。 +//! +//! 后续迁移玩家等级、章节预算和经验曲线时,只保留成长规则; +//! 任务、战斗等奖励来源通过事件或应用结果接入。 diff --git a/server-rs/crates/module-progression/src/errors.rs b/server-rs/crates/module-progression/src/errors.rs new file mode 100644 index 00000000..d1420234 --- /dev/null +++ b/server-rs/crates/module-progression/src/errors.rs @@ -0,0 +1,3 @@ +//! 成长领域错误过渡落位。 +//! +//! 错误保持纯领域语义,例如章节参数非法或经验来源不被接受。 diff --git a/server-rs/crates/module-progression/src/events.rs b/server-rs/crates/module-progression/src/events.rs new file mode 100644 index 00000000..7b03c0a5 --- /dev/null +++ b/server-rs/crates/module-progression/src/events.rs @@ -0,0 +1,3 @@ +//! 成长领域事件过渡落位。 +//! +//! 用于表达经验已授予、升级待处理和章节节奏变化等事实。 diff --git a/server-rs/crates/module-progression/src/lib.rs b/server-rs/crates/module-progression/src/lib.rs index adc6568e..b5abc40d 100644 --- a/server-rs/crates/module-progression/src/lib.rs +++ b/server-rs/crates/module-progression/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-puzzle/src/application.rs b/server-rs/crates/module-puzzle/src/application.rs new file mode 100644 index 00000000..0d900e85 --- /dev/null +++ b/server-rs/crates/module-puzzle/src/application.rs @@ -0,0 +1,3 @@ +//! 拼图应用编排过渡落位。 +//! +//! 这里只组合拼图规则并返回应用结果或领域事件,不直接调用图片服务。 diff --git a/server-rs/crates/module-puzzle/src/commands.rs b/server-rs/crates/module-puzzle/src/commands.rs new file mode 100644 index 00000000..1477be89 --- /dev/null +++ b/server-rs/crates/module-puzzle/src/commands.rs @@ -0,0 +1,3 @@ +//! 拼图写入命令过渡落位。 +//! +//! 用于表达会话消息、作品更新、发布、开局、交换拼图块和过关推进等输入。 diff --git a/server-rs/crates/module-puzzle/src/domain.rs b/server-rs/crates/module-puzzle/src/domain.rs new file mode 100644 index 00000000..a5dbb2b8 --- /dev/null +++ b/server-rs/crates/module-puzzle/src/domain.rs @@ -0,0 +1,4 @@ +//! 拼图领域模型过渡落位。 +//! +//! 后续迁移拼图 Agent 会话、作品 profile 和运行态聚合时,只保留玩法规则; +//! 图片生成、发布 HTTP shape 和排行榜适配留在外层。 diff --git a/server-rs/crates/module-puzzle/src/errors.rs b/server-rs/crates/module-puzzle/src/errors.rs new file mode 100644 index 00000000..0422cf7a --- /dev/null +++ b/server-rs/crates/module-puzzle/src/errors.rs @@ -0,0 +1,3 @@ +//! 拼图领域错误过渡落位。 +//! +//! 错误只表达拼图业务失败,例如标签不足、移动非法或运行态不存在。 diff --git a/server-rs/crates/module-puzzle/src/events.rs b/server-rs/crates/module-puzzle/src/events.rs new file mode 100644 index 00000000..04b0aacf --- /dev/null +++ b/server-rs/crates/module-puzzle/src/events.rs @@ -0,0 +1,3 @@ +//! 拼图领域事件过渡落位。 +//! +//! 用于表达草稿变化、作品发布、运行态推进和排行榜候选产生等事实。 diff --git a/server-rs/crates/module-puzzle/src/lib.rs b/server-rs/crates/module-puzzle/src/lib.rs index 28c7ddf7..7b334357 100644 --- a/server-rs/crates/module-puzzle/src/lib.rs +++ b/server-rs/crates/module-puzzle/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{ collections::{BTreeMap, BTreeSet, VecDeque}, error::Error, diff --git a/server-rs/crates/module-quest/src/application.rs b/server-rs/crates/module-quest/src/application.rs new file mode 100644 index 00000000..fce844be --- /dev/null +++ b/server-rs/crates/module-quest/src/application.rs @@ -0,0 +1,3 @@ +//! 任务应用编排过渡落位。 +//! +//! 这里只返回任务变更结果、日志和奖励待处理事件,不直接写背包或成长表。 diff --git a/server-rs/crates/module-quest/src/commands.rs b/server-rs/crates/module-quest/src/commands.rs new file mode 100644 index 00000000..5bbda4dc --- /dev/null +++ b/server-rs/crates/module-quest/src/commands.rs @@ -0,0 +1,3 @@ +//! 任务写入命令过渡落位。 +//! +//! 用于表达领取任务、推进信号、确认完成和交付任务等输入。 diff --git a/server-rs/crates/module-quest/src/domain.rs b/server-rs/crates/module-quest/src/domain.rs new file mode 100644 index 00000000..e99f5df9 --- /dev/null +++ b/server-rs/crates/module-quest/src/domain.rs @@ -0,0 +1,4 @@ +//! 任务领域模型过渡落位。 +//! +//! 后续迁移任务记录、步骤、目标、奖励和日志规则时,只保留任务聚合内部变化; +//! 奖励发放和成长记账通过事件交给外层事务编排。 diff --git a/server-rs/crates/module-quest/src/errors.rs b/server-rs/crates/module-quest/src/errors.rs new file mode 100644 index 00000000..3c7d6dd4 --- /dev/null +++ b/server-rs/crates/module-quest/src/errors.rs @@ -0,0 +1,3 @@ +//! 任务领域错误过渡落位。 +//! +//! 错误保持任务规则语义,例如状态不允许、目标不匹配或重复交付。 diff --git a/server-rs/crates/module-quest/src/events.rs b/server-rs/crates/module-quest/src/events.rs new file mode 100644 index 00000000..f058c25c --- /dev/null +++ b/server-rs/crates/module-quest/src/events.rs @@ -0,0 +1,3 @@ +//! 任务领域事件过渡落位。 +//! +//! 用于表达任务已领取、进度已推进、任务已完成和奖励待发放等事实。 diff --git a/server-rs/crates/module-quest/src/lib.rs b/server-rs/crates/module-quest/src/lib.rs index 153654ce..cb51b1fa 100644 --- a/server-rs/crates/module-quest/src/lib.rs +++ b/server-rs/crates/module-quest/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-runtime-item/src/application.rs b/server-rs/crates/module-runtime-item/src/application.rs new file mode 100644 index 00000000..92b91173 --- /dev/null +++ b/server-rs/crates/module-runtime-item/src/application.rs @@ -0,0 +1,3 @@ +//! 运行时物品应用编排过渡落位。 +//! +//! 这里只返回奖励结果、记录快照和待写入背包事件。 diff --git a/server-rs/crates/module-runtime-item/src/commands.rs b/server-rs/crates/module-runtime-item/src/commands.rs new file mode 100644 index 00000000..65095481 --- /dev/null +++ b/server-rs/crates/module-runtime-item/src/commands.rs @@ -0,0 +1,3 @@ +//! 运行时物品写入命令过渡落位。 +//! +//! 用于表达宝箱检查、开启、离开和奖励记录等输入。 diff --git a/server-rs/crates/module-runtime-item/src/domain.rs b/server-rs/crates/module-runtime-item/src/domain.rs new file mode 100644 index 00000000..3de58a29 --- /dev/null +++ b/server-rs/crates/module-runtime-item/src/domain.rs @@ -0,0 +1,4 @@ +//! 运行时物品领域模型过渡落位。 +//! +//! 后续迁移宝箱、奇遇和奖励物品规则时,只保留奖励生成与记录规则; +//! 背包落库由外层事务 adapter 编排。 diff --git a/server-rs/crates/module-runtime-item/src/errors.rs b/server-rs/crates/module-runtime-item/src/errors.rs new file mode 100644 index 00000000..9d54cadb --- /dev/null +++ b/server-rs/crates/module-runtime-item/src/errors.rs @@ -0,0 +1,3 @@ +//! 运行时物品领域错误过渡落位。 +//! +//! 错误只表达物品/奇遇规则失败,例如 encounter 缺失或奖励字段非法。 diff --git a/server-rs/crates/module-runtime-item/src/events.rs b/server-rs/crates/module-runtime-item/src/events.rs new file mode 100644 index 00000000..11b245e3 --- /dev/null +++ b/server-rs/crates/module-runtime-item/src/events.rs @@ -0,0 +1,3 @@ +//! 运行时物品领域事件过渡落位。 +//! +//! 用于表达宝箱已结算、奖励物品已生成和资源奖励待入账等事实。 diff --git a/server-rs/crates/module-runtime-item/src/lib.rs b/server-rs/crates/module-runtime-item/src/lib.rs index 792c6209..7c30cb8f 100644 --- a/server-rs/crates/module-runtime-item/src/lib.rs +++ b/server-rs/crates/module-runtime-item/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use module_inventory::{ diff --git a/server-rs/crates/module-runtime-story-compat/src/application.rs b/server-rs/crates/module-runtime-story-compat/src/application.rs new file mode 100644 index 00000000..e7e15af2 --- /dev/null +++ b/server-rs/crates/module-runtime-story-compat/src/application.rs @@ -0,0 +1,3 @@ +//! runtime story 兼容应用编排过渡落位。 +//! +//! 这里只组合旧规则并返回兼容结果;真实保存、SSE 和模型调用由外层完成。 diff --git a/server-rs/crates/module-runtime-story-compat/src/commands.rs b/server-rs/crates/module-runtime-story-compat/src/commands.rs new file mode 100644 index 00000000..0a0dd9fe --- /dev/null +++ b/server-rs/crates/module-runtime-story-compat/src/commands.rs @@ -0,0 +1,3 @@ +//! runtime story 兼容写入命令过渡落位。 +//! +//! 用于表达旧剧情动作解析、战斗动作、锻造动作和 NPC 互动等输入。 diff --git a/server-rs/crates/module-runtime-story-compat/src/domain.rs b/server-rs/crates/module-runtime-story-compat/src/domain.rs new file mode 100644 index 00000000..29770c5d --- /dev/null +++ b/server-rs/crates/module-runtime-story-compat/src/domain.rs @@ -0,0 +1,4 @@ +//! runtime story 兼容领域模型过渡落位。 +//! +//! 当前 crate 用于旧运行时剧情桥的纯规则兼容。后续迁移时仍只能保留 JSON 规则、 +//! 选项生成和视图模型转换,不引入 Axum、LLM 或 SpacetimeDB。 diff --git a/server-rs/crates/module-runtime-story-compat/src/errors.rs b/server-rs/crates/module-runtime-story-compat/src/errors.rs new file mode 100644 index 00000000..3a4b536e --- /dev/null +++ b/server-rs/crates/module-runtime-story-compat/src/errors.rs @@ -0,0 +1,3 @@ +//! runtime story 兼容领域错误过渡落位。 +//! +//! 错误只表达兼容规则失败,不能直接绑定 HTTP 或数据库错误模型。 diff --git a/server-rs/crates/module-runtime-story-compat/src/events.rs b/server-rs/crates/module-runtime-story-compat/src/events.rs new file mode 100644 index 00000000..4abffdfc --- /dev/null +++ b/server-rs/crates/module-runtime-story-compat/src/events.rs @@ -0,0 +1,3 @@ +//! runtime story 兼容领域事件过渡落位。 +//! +//! 用于表达旧剧情快照变化、战斗表现变化和物品/成长待同步等事实。 diff --git a/server-rs/crates/module-runtime-story-compat/src/lib.rs b/server-rs/crates/module-runtime-story-compat/src/lib.rs index f1baf3c3..01752679 100644 --- a/server-rs/crates/module-runtime-story-compat/src/lib.rs +++ b/server-rs/crates/module-runtime-story-compat/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use serde_json::Value; use shared_contracts::runtime_story::{ RuntimeBattlePresentation, RuntimeStoryActionRequest, RuntimeStoryOptionView, diff --git a/server-rs/crates/module-runtime/src/application.rs b/server-rs/crates/module-runtime/src/application.rs new file mode 100644 index 00000000..c4edfd2e --- /dev/null +++ b/server-rs/crates/module-runtime/src/application.rs @@ -0,0 +1,3 @@ +//! 运行时应用编排过渡落位。 +//! +//! 这里只返回运行时快照、个人页投影和领域事件,不直接访问外部 adapter。 diff --git a/server-rs/crates/module-runtime/src/commands.rs b/server-rs/crates/module-runtime/src/commands.rs new file mode 100644 index 00000000..54d9ecfb --- /dev/null +++ b/server-rs/crates/module-runtime/src/commands.rs @@ -0,0 +1,3 @@ +//! 运行时写入命令过渡落位。 +//! +//! 用于表达保存快照、更新设置、写入浏览历史、调整钱包和保存存档等输入。 diff --git a/server-rs/crates/module-runtime/src/domain.rs b/server-rs/crates/module-runtime/src/domain.rs new file mode 100644 index 00000000..47ae17c6 --- /dev/null +++ b/server-rs/crates/module-runtime/src/domain.rs @@ -0,0 +1,4 @@ +//! 运行时领域模型过渡落位。 +//! +//! 后续迁移设置、快照、个人页状态、钱包流水、存档和浏览历史规则时, +//! 只保留纯运行时数据变化;SpacetimeDB client 与 HTTP response 不进入本文件。 diff --git a/server-rs/crates/module-runtime/src/errors.rs b/server-rs/crates/module-runtime/src/errors.rs new file mode 100644 index 00000000..3607fe24 --- /dev/null +++ b/server-rs/crates/module-runtime/src/errors.rs @@ -0,0 +1,3 @@ +//! 运行时领域错误过渡落位。 +//! +//! 错误保持运行时业务语义,例如快照版本非法、兑换码不可用或钱包余额不足。 diff --git a/server-rs/crates/module-runtime/src/events.rs b/server-rs/crates/module-runtime/src/events.rs new file mode 100644 index 00000000..1aa0bbc5 --- /dev/null +++ b/server-rs/crates/module-runtime/src/events.rs @@ -0,0 +1,3 @@ +//! 运行时领域事件过渡落位。 +//! +//! 用于表达快照已保存、设置已更新、钱包已记账和存档已变化等事实。 diff --git a/server-rs/crates/module-runtime/src/lib.rs b/server-rs/crates/module-runtime/src/lib.rs index 7104c4a8..63cbfeb6 100644 --- a/server-rs/crates/module-runtime/src/lib.rs +++ b/server-rs/crates/module-runtime/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::collections::HashSet; use serde::{Deserialize, Serialize}; diff --git a/server-rs/crates/module-story/src/application.rs b/server-rs/crates/module-story/src/application.rs new file mode 100644 index 00000000..bc78bf8a --- /dev/null +++ b/server-rs/crates/module-story/src/application.rs @@ -0,0 +1,3 @@ +//! 剧情应用编排过渡落位。 +//! +//! 这里只返回剧情快照、事件和待投影结果,不直接调用模型或数据库。 diff --git a/server-rs/crates/module-story/src/commands.rs b/server-rs/crates/module-story/src/commands.rs new file mode 100644 index 00000000..68630c5f --- /dev/null +++ b/server-rs/crates/module-story/src/commands.rs @@ -0,0 +1,3 @@ +//! 剧情写入命令过渡落位。 +//! +//! 用于表达开启剧情会话、继续剧情和归档会话等输入。 diff --git a/server-rs/crates/module-story/src/domain.rs b/server-rs/crates/module-story/src/domain.rs new file mode 100644 index 00000000..3e032785 --- /dev/null +++ b/server-rs/crates/module-story/src/domain.rs @@ -0,0 +1,4 @@ +//! 剧情领域模型过渡落位。 +//! +//! 后续迁移 `StorySession`、`StoryEvent` 和剧情推进规则时,只保留剧情聚合内部变化; +//! LLM 生成和 SpacetimeDB 写回由外层 adapter 处理。 diff --git a/server-rs/crates/module-story/src/errors.rs b/server-rs/crates/module-story/src/errors.rs new file mode 100644 index 00000000..a73a95a1 --- /dev/null +++ b/server-rs/crates/module-story/src/errors.rs @@ -0,0 +1,3 @@ +//! 剧情领域错误过渡落位。 +//! +//! 错误保持纯剧情规则语义,例如会话不存在、状态不允许或输入为空。 diff --git a/server-rs/crates/module-story/src/events.rs b/server-rs/crates/module-story/src/events.rs new file mode 100644 index 00000000..6e7fd89f --- /dev/null +++ b/server-rs/crates/module-story/src/events.rs @@ -0,0 +1,3 @@ +//! 剧情领域事件过渡落位。 +//! +//! 用于表达剧情会话已开启、剧情已推进和剧情事件已追加等事实。 diff --git a/server-rs/crates/module-story/src/lib.rs b/server-rs/crates/module-story/src/lib.rs index 19a2ebda..1b639d90 100644 --- a/server-rs/crates/module-story/src/lib.rs +++ b/server-rs/crates/module-story/src/lib.rs @@ -1,3 +1,9 @@ +mod application; +mod commands; +mod domain; +mod errors; +mod events; + use std::{error::Error, fmt}; use serde::{Deserialize, Serialize};