e401963d3a
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 1/2 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust lane 2/2 (pull_request) Has been cancelled
端到端实测(54 项里唯一红的那条):`GET /api/game-distribution/themes?cursor=abc` 回 400,但
`error.code = "BAD_REQUEST"`——技术方案 §3.4 与主题 e2e 脚本承诺的稳定码 `THEME_INVALID_CURSOR`
在 HTTP 面上拿不到,客户端只能去匹配中文文案。
根因:`map_spacetime_error` 的 `THEME_` 分支前置条件是「消息含 `THEME_`」,而模块侧游标解析只回
中文串「主题列表游标格式无效」⇒ 落兜底分支成 400 + 通用 `BAD_REQUEST`;契约常量与那条映射分支
因此是死代码。且 api-server 原有单测**明确要求**文案不含 `THEME_`(口径留了两套)。
口径二选一,选**让码可达**(模块产出前缀),删掉「要求不含 `THEME_`」的断言:
- `module-game-distribution/src/errors.rs`:新增 6 个主题码常量
`GAME_DISTRIBUTION_THEME_{NOT_FOUND,BAD_REQUEST,INVALID_CURSOR,IDEMPOTENCY_CONFLICT,MEMBER_NOT_ROOT,MEMBER_GAME_NOT_FOUND}_CODE`,
并把 `Display` 从字面量改为**复用同一批常量**(消灭「常量改了、`Display` 没改」这类只有真栈才发现的漂移)。
- `theme.rs`:`parse_game_distribution_theme_cursor` 产出 `THEME_INVALID_CURSOR: 主题列表游标格式无效`;
文档注释更新为「只保留 `FORK_` 这个排在 `THEME_` 分支之前的子串禁忌」(其余子串已抢不到)。
- `lib.rs`:导出新增的 6 个码常量。
- 测试:
· `domain.rs::theme_errors_are_prefixed_with_their_machine_code` 改为**枚举全部 6 个主题码**(含唯一
不走领域变体的游标路径——正是当初漏掉它的原因),并加「任何新增码都必须进这张表」的覆盖完整性断言;
· `theme.rs::invalid_cursor_message_stays_in_the_bad_request_bucket` 增加「必须以稳定码开头」;
· api-server 新增 `theme_error_codes_are_reachable_from_module_messages`:用**模块真实产出的消息**
逐码断言 `(状态码, 稳定码)` 可达,并比对模块常量与 `shared-contracts` 常量是同一组字符串;
· api-server `theme_list_invalid_cursor_maps_to_bad_request` 改为断言映射出 `THEME_INVALID_CURSOR`,
只把 `FORK_` 留在禁忌列表里(并写明理由)。
门禁:`cargo test -p module-game-distribution` **100 passed**;`cargo test -p api-server game_distribution`
**86 passed**;`cargo check --all-targets` 0;DTO parity 58 组 / 10 构建器;`check:encoding` 0;
`cargo fmt --all -- --check` 0;`git diff --check` 0。
server-rs 工作区说明
更新时间:2026-05-15
server-rs/ 是当前唯一后端工作区,承载 Rust api-server、SpacetimeDB module、领域模块、平台副作用适配和共享契约。旧 server-node、Express、PostgreSQL、Go 服务端和 maincloud 口径均为历史残留,不再作为当前实现目标。
当前职责
crates/api-server:Axum HTTP / SSE / BFF 门面、鉴权、中间件、外部服务编排和 DTO 映射。crates/spacetime-module:SpacetimeDB 表、reducer、procedure、事务 adapter、row mapper 和迁移。crates/spacetime-client:后端访问 SpacetimeDB 的 typed facade。crates/module-*:领域模型、命令、应用规则、领域事件和领域错误。crates/platform-*:OSS、LLM、语音、认证等外部平台能力。crates/shared-contracts:前后端共享 DTO 与公开契约。crates/shared-kernel、crates/shared-logging、crates/tests-support:跨模块基础能力、日志和测试支撑。
开发规则
server-rs/Cargo.toml是 workspace 成员和依赖版本事实源;第三方依赖和 workspace 内 crate path 优先放在[workspace.dependencies]。module-*不直接依赖 Axum、SpacetimeDB table/reducer/procedure、reqwest、OSS、LLM、spacetime-client、tokio或文件系统。api-server不承接领域真相;发现领域规则时优先沉到对应module-*。- SpacetimeDB schema 变化必须同步
spacetime-module/src/migration.rs、生成绑定和当前后端架构文档的表目录。 - 人工命令、本地联调和文档示例不要使用
spacetime --root-dir。
常用命令
cargo check -p api-server --manifest-path server-rs/Cargo.toml
cargo test -p api-server --manifest-path server-rs/Cargo.toml
npm run check:server-rs-ddd
npm run check:spacetime-schema
npm run spacetime:generate
npm run dev:api-server
涉及 API smoke 时用 npm run dev:api-server 启动后端并检查 /healthz,不要使用旧 api-server:maincloud。
当前文档
- ../docs/【后端架构】server-rs与SpacetimeDB数据契约-2026-05-15.md:DDD 边界、API 分组、schema 变更规则和表目录。
- ../docs/【开发运维】本地开发验证与生产运维-2026-05-15.md:本地启动、检查、SpacetimeDB 操作和生产运维。