修复(会员契约): 响应 token 反序列化前向兼容
- shared-contracts 为会员响应 DTO 的 plan / status / cycle_kind / model_access 字段加 deserialize_with,未知取值 fail-open 兜底到已知最高档,避免 AGC Tauri shell 等旧 Rust 客户端因后端新增 token 整包解析失败 - 入参 DTO 保持严格拒绝,不改枚举自身 Deserialize,避免 Unknown 变体污染入参 - 补响应兼容与入参严格测试;同步设计文档 §2.5 与决策日志
This commit is contained in:
@@ -153,8 +153,12 @@ pub struct ProfileMembershipPlan {
|
||||
- `shared-contracts` 新增 wire 侧 `ProfileMembershipPlanToken` / `ProfileMembershipCycleKindToken` /
|
||||
`ProfileMembershipStatusToken` / `ProfileMembershipModelAccessToken` / `ProfileMembershipChangeKindToken`,
|
||||
把 DTO 里原来的裸 `String`(后台 upsert 请求、后台会员详情、订单变更快照、会员 / 档位 / 报价响应)
|
||||
收口为 typed enum;与模块枚举通过 `From` 双向映射,JSON wire 值仍是小写 token,未知 token 在
|
||||
反序列化阶段被拒。这 5 个 token 枚举统一 `#[cfg_attr(feature = "ts-bindings", derive(ts_rs::TS))]`
|
||||
收口为 typed enum;与模块枚举通过 `From` 双向映射,JSON wire 值仍是小写 token。**入参** DTO
|
||||
(`ProfileMembershipUpgradeQuoteRequest`、`AdminUpsertProfileMembershipPlanRequest`)反序列化保持严格,
|
||||
未知 token 即拒;**响应** DTO 的 token 字段挂 `deserialize_with` 做前向兼容,未知取值按 fail-open
|
||||
兜底到已知最高档(plan→`max`、status→`active`、cycle→`yearly`、model_access→`full`),
|
||||
避免 AGC Tauri shell 等 Rust 客户端因后端新增一个 token 就整包解析失败(权益与下单金额仍以后端重算为准)。
|
||||
这 5 个 token 枚举统一 `#[cfg_attr(feature = "ts-bindings", derive(ts_rs::TS))]`
|
||||
导出到 `packages/shared/src/contracts/generated/`,前端只 re-export,不再手写字符串联合类型。
|
||||
- **删除** `RuntimeProfileMembershipTier { Normal, Month, Season, Year, Starter, Basic, Pro, Ultimate }`
|
||||
及其 `as_str()`(会员侧零存量,用户已授权破坏性变更)。
|
||||
|
||||
Reference in New Issue
Block a user