diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 00000000..2dcfcd13 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,69 @@ +# server-rs DDD 一次性重构方案 + +## Summary + +当前仓库已不再存在 `server-node`,本次只针对现有 `server-rs` 做一次性 DDD 化。 + +目标是把 Rust + SpacetimeDB 后端统一成清晰边界:领域规则在 `module-*`,事务和持久化在 `spacetime-module`,HTTP/BFF 在 `api-server`,外部能力在 `platform-*`,共享值处理和 DTO 分别在 `shared-kernel` / `shared-contracts`。 + +## Target Architecture + +- `module-*`:领域模型、值对象、聚合方法、领域服务、命令、领域错误、领域事件、纯应用编排结果;禁止直接依赖 Axum、reqwest、OSS、LLM、文件系统、SpacetimeDB table 操作。 +- `spacetime-module`:SpacetimeDB adapter,只保留 table、reducer、procedure、row/snapshot mapper、事务内查询写回、event table;核心规则必须调用 `module-*`。 +- `api-server`:HTTP/BFF adapter,只保留路由、鉴权上下文、请求响应映射、SSE、SpacetimeDB client 调用、平台服务调用。 +- `platform-*`:JWT/SMS/微信/OSS/LLM/HTTP client 等外部能力实现。 +- `shared-kernel`:跨领域纯值处理;`shared-contracts`:HTTP/前端契约 DTO。 + +## Required Refactor + +- 为所有业务上下文统一目录: + - `domain.rs` 或 `domain/*`:聚合、值对象、领域方法。 + - `commands.rs`:写入用例输入。 + - `application.rs`:用例处理函数。 + - `events.rs`:领域事件与跨上下文事件。 + - `errors.rs`:领域错误。 + - `mapper.rs` 仅允许出现在 adapter crate。 + +- 一次性处理混合边界: + - `module-auth` 拆出认证、会话、验证码、微信绑定领域;内存 store / 文件持久化移出领域核心。 + - `module-assets` 拆出资产对象确认规则;OSS head、reqwest、fallback store 移出领域核心。 + - `spacetime-module` 全量拆分 table、reducer/procedure、mapper、跨上下文事务编排。 + - `api-server` 中 handler 只保留 transport 逻辑,业务分支迁移到领域或应用层。 + - `runtime_story`、`custom_world`、`puzzle`、`big_fish`、`inventory`、`quest`、`npc`、`combat`、`progression` 全部对齐同一结构。 + +- 表结构硬约束: + - 默认保持现有 SpacetimeDB 主表兼容。 + - 表结构变更采用最小必要原则。 + - 只有为修正聚合边界、读写分离、事件化、查询索引或生命周期独立性不可避免时,才新增或调整表。 + - 优先新增 optional 字段、投影表、事件表,不做破坏性 rename/delete/type change。 + - 任何 table 变更必须同步 `migration.rs`、SpacetimeDB 表目录、相关 reducer/procedure 测试。 + +- 统一跨上下文协作: + - 单聚合内部变化由聚合方法完成。 + - 跨聚合流程由应用服务或 SpacetimeDB 事务 adapter 编排。 + - 战斗奖励、任务奖励、成长记账、画廊投影、agent 操作进度等副作用必须显式表达为事件或应用结果。 + +- 统一查询策略: + - 写模型不复用给复杂查询。 + - 每个前端场景有独立 query/result DTO。 + - SpacetimeDB private table 默认不暴露;public table 只服务明确订阅读模型。 + +## Documentation + +- 新增 `docs/technical/SERVER_RS_DDD_FULL_REFACTOR_2026-04-28.md`,写清 DDD 规则、依赖方向、crate 职责矩阵、每个上下文的聚合/命令/事件/读模型、SpacetimeDB adapter 映射、表结构变更约束。 +- 更新现有后端基线、SpacetimeDB 表目录、API 路由索引、相关模块技术文档。 +- 表结构或 reducer/procedure 变化同步 `migration.rs`。 + +## Acceptance Criteria + +- `server-rs` 所有业务模块通过统一 DDD 目录和依赖边界检查。 +- `spacetime-module/src/lib.rs` 不再承载大段业务流程,拆到上下文 adapter。 +- 默认不破坏现有 SpacetimeDB 主表;确需改表时有文档、migration 和测试。 +- 所有领域规则都有纯 Rust 单元测试。 +- 所有 reducer/procedure 有事务适配测试或最小 smoke。 +- HTTP contract shape 不发生未记录 breaking change。 +- 执行并通过: + - `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` + - 仓库编码检查 diff --git a/test-code.ps1 b/test-code.ps1 new file mode 100644 index 00000000..ea29c595 --- /dev/null +++ b/test-code.ps1 @@ -0,0 +1,27 @@ +$response =(Invoke-RestMethod ` + -Method Post ` + -Uri "http://127.0.0.1:8082/admin/api/login" ` + -ContentType "application/json" ` + -Body '{"username":"admin","password":"123456"}') +$adminToken = $response.token + +Invoke-RestMethod ` + -Method Post ` + -Uri http://127.0.0.1:8082/admin/api/profile/redeem-codes ` + -Headers @{ Authorization = "Bearer $adminToken" } ` + -ContentType 'application/json' ` + -Body '{ + "code": "TEST100", + "mode": "public", + "rewardPoints": 100, + "maxUses": 1, + "enabled": true + }' + + $userToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2F1dGguZ2VuYXJyYXRpdmUubG9jYWwiLCJzdWIiOiJ1c2VyXzAwMDAwMDAxIiwic2lkIjoidXNlc3NfNWVhMWU3NWIxOTUxNGU2ZTg5ZTdmYWFkZDEyYTE0NTEiLCJwcm92aWRlciI6InBhc3N3b3JkIiwicm9sZXMiOlsidXNlciJdLCJ2ZXIiOjIsInBob25lX3ZlcmlmaWVkIjp0cnVlLCJiaW5kaW5nX3N0YXR1cyI6ImFjdGl2ZSIsImRpc3BsYXlfbmFtZSI6IjE1OCoqKiozNTMzIiwiaWF0IjoxNzc3MzU0NjA4LCJleHAiOjE3Nzc5NTk0MDh9.O6US67MOVD62kPliBlp7qDV3Pyo3pJlnBoGv0fFuGfA" + Invoke-RestMethod ` + -Method Post ` + -Uri http://127.0.0.1:8082/api/profile/redeem-codes/redeem ` + -Headers @{ Authorization = "Bearer $userToken" } ` + -ContentType 'application/json' ` + -Body '{"code":"TEST100"}'