修复(会员错误码): 修正 ProductIdUnparseable 拼写

- module-runtime 变体 ProductIdUnparsable 改名为 ProductIdUnparseable,wire 串 product_id_unparsable 同步改为 product_id_unparseable(本 PR 未上线,不留兼容)
- 同步 spacetime-module 拒绝点、spacetime-client mapper 与 api-server 测试引用,并重新生成 SpacetimeDB 绑定
- 同步设计文档 §5.8 与决策日志
This commit is contained in:
2026-10-05 15:32:19 +08:00
parent 42c4cacf72
commit 0930e402be
7 changed files with 17 additions and 10 deletions
@@ -9687,7 +9687,7 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
## 2026-10-03 会员链路错误分类改为机器可读错误码(typed error)
- 背景:`api-server/src/runtime_profile.rs` 的 `is_runtime_profile_membership_domain_error` 用中文 `error_message` 前缀 / 精确匹配决定返回 400 还是 502;文案一改(或新增拒绝点)就静默退化,且分类逻辑与 module 的错误文案跨层重复。
- 决策(错误码随 procedure 结果透传):`module-runtime` 新增 `RuntimeProfileMembershipErrorCode`(`UpgradeRejected` / `NotMember` / `AlreadyActive` / `CycleKindLocked` / `MembershipExpired` / `StateChanged` / `PlanNotPurchasable` / `PlanCatalogMissing` / `ProductIdUnparsable` / `MembershipProductRetired` / `InvalidPlanConfig`)与内部 `RuntimeProfileMembershipDomainError { code, message }`;三个会员 procedure 结果(升级报价、充值中心 / 下单、后台档位 upsert)末尾追加 `error_code: Option<...>`,拒绝点显式赋码,不再做字符串分类。
- 决策(错误码随 procedure 结果透传):`module-runtime` 新增 `RuntimeProfileMembershipErrorCode`(`UpgradeRejected` / `NotMember` / `AlreadyActive` / `CycleKindLocked` / `MembershipExpired` / `StateChanged` / `PlanNotPurchasable` / `PlanCatalogMissing` / `ProductIdUnparseable` / `MembershipProductRetired` / `InvalidPlanConfig`)与内部 `RuntimeProfileMembershipDomainError { code, message }`;三个会员 procedure 结果(升级报价、充值中心 / 下单、后台档位 upsert)末尾追加 `error_code: Option<...>`,拒绝点显式赋码,不再做字符串分类。
- 决策(客户端错误类型):`spacetime-client` 新增 `SpacetimeClientError::ProcedureRejected { code, message }`;`api-server` 据此返回 400(provider `runtime-profile`),基础设施错误保持 502。字段校验类错误不产码,仍落 502。
- 决策(行为变化):`会员目录缺少档位 ...` 与「已迁移的会员商品」原先落 502,现在明确 400;兑换码链路本轮未改造,仍保留一个文案匹配函数。procedure result 新增字段属 wire 契约变更,要求 module 与 api-server 同版本部署。
- 影响范围:`server-rs/crates/module-runtime/src/domain.rs`、`server-rs/crates/spacetime-module/src/runtime/active/profile.rs`、`server-rs/crates/spacetime-client/src/{active.rs,active/mapper/runtime_profile.rs}`、生成绑定、`server-rs/crates/api-server/src/{runtime_profile.rs,asset_billing.rs,editor_project.rs}`、`docs/technical/【技术设计】泥点三池与会员计费后端设计-2026-10-02.md` §5.8、本文件。
@@ -9750,3 +9750,10 @@ CI 上 `background_agent_runtime_recovers_stale_running_before_pending_task` 在
- 决策:只给**响应** DTO 的 token 字段挂 `#[serde(deserialize_with = "...")]` 做前向兼容,未知取值 fail-open 兜底到已知最高档(plan→`max`、status→`active`、cycle→`yearly`、model_access→`full`;真实权益 / 下单金额以后端重算为准,避免把付费会员显示成非会员后引导重复购买)。**入参** DTO 不改,非法 token 仍在反序列化即拒;不改枚举本身的 `Deserialize`,避免 `Unknown` 变体污染入参与穷尽 match。
- 影响范围:`server-rs/crates/shared-contracts/src/runtime.rs`(4 个 helper + `ProfileMembershipPlanResponse` / `ProfileMembershipResponse` / `ProfileMembershipUpgradeQuoteResponse` 的 8 个字段)、`docs/technical/【技术设计】泥点三池与会员计费后端设计-2026-10-02.md` §2.5。后台 DTO(`AdminProfileMembershipPayload` / `AdminMembershipOrderChangePayload`)只有 TS 消费方,不做 Rust 侧处理。
- 验证:`cargo test -p shared-contracts --lib` 106 passed(含 `membership_response_tokens_tolerate_unknown_values_from_newer_backend`、`membership_request_tokens_stay_strict_for_unknown_values`)。
## 2026-10-03 会员错误码 `ProductIdUnparsable` 拼写修正(未上线,直接破坏性改名)
- 背景:`RuntimeProfileMembershipErrorCode::ProductIdUnparsable` 拼写有误,生成绑定与对外 `error.code = "product_id_unparsable"` 同错。
- 决策:该 PR 尚未上线,不留兼容,直接改名为 `ProductIdUnparseable`,wire 串同步改为 `"product_id_unparseable"`;重新生成 SpacetimeDB 绑定。
- 影响范围:`server-rs/crates/module-runtime/src/domain.rs`、`server-rs/crates/spacetime-module/src/runtime/active/profile.rs`、`server-rs/crates/spacetime-client/src/{active/mapper/runtime_profile.rs,module_bindings/runtime_profile_membership_error_code_type.rs}`、`server-rs/crates/api-server/src/runtime_profile.rs`、设计文档 §5.8、本文件(含上文旧条目中的同名标识符同步更正)。
- 验证:`cargo test -p module-runtime --lib` 114 passed;`cargo test -p spacetime-client` 32 passed;`cargo test -p api-server runtime_profile::tests` 43 passed;`cargo test -p spacetime-module` 271 passed。