feat: 接入远程订阅策略门禁 T-705
Tests / Python 3.11 / Windows (push) Has been cancelled

This commit is contained in:
chengma
2026-07-28 15:42:19 +08:00
parent 593c6f77cb
commit df9da63841
15 changed files with 925 additions and 73 deletions
+21 -14
View File
@@ -3,7 +3,7 @@ id: T-705
title: cmhub 远程订阅策略开关与分类门禁提示
phase: 8
deps: [T-700, T-701]
status: BLOCKED
status: DONE
created: 2026-07-28
---
@@ -15,9 +15,9 @@ created: 2026-07-28
不能把远程开关放进订阅状态接口,否则客户端必须先请求该接口才能知道是否应跳过它。客户端门禁也不能成为服务端授权的唯一安全边界,cmhub 产品接口仍必须独立校验 API Key 和套餐。
## 外部前置条件
## 外部契约(已交付)
cmhub 先按 Obsidian《cmshopee-客户端订阅策略接口契约》交付并冻结启动策略字段、兼容规则和测试响应;未交付前本任务保持 `BLOCKED`,不得猜测字段或先写临时解析。
cmhub 已按 Obsidian《cmhub-cmshopee客户端订阅策略接口契约》完成 T-635。客户端复用现有 HTTPS 启动版本接口:
最低要求是在客户端启动时已经请求的 HTTPS 版本接口中增加可选 `client_policy`:
@@ -32,7 +32,9 @@ cmhub 先按 Obsidian《cmshopee-客户端订阅策略接口契约》交付并
}
```
cmhub 必须保证:`subscription_check_enabled=false` 时服务端产品接口的订阅策略与客户端关闭策略一致;无论客户端门禁是否开启,付费授权最终仍由服务端执行。
cmhub 内部只配置 `CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY=off|observe|enforce`,对客户端仍输出上述两个布尔字段。订阅状态成功响应另提供顶层严格布尔字段 `real_entitlement_allowed`;强制模式必须只按该字段放行,不得使用展示用 `status` 或兼容 `allowed` 推断。当前成功状态为 `active/grace/required/expired`,账号禁用使用 HTTP 403;`revoked` 只保留客户端兼容处理,不属于当前服务端承诺状态。
cmhub 保证无论客户端门禁是否开启,付费产品接口仍独立执行服务端授权;客户端开关不是授权凭据。
## 方案
@@ -40,14 +42,14 @@ cmhub 必须保证:`subscription_check_enabled=false` 时服务端产品接口
- `check=false`:跳过 `SubscriptionCheckWorker`,不显示会员激活/过期/异常窗口,不锁定业务 Tab;生成前订阅预检直接放行,设置页重新检测入口显示“服务端暂未启用会员检测”并禁用。
- `check=true, enforcement=false`:执行真实查询并展示账号、套餐、有效期和观察状态,但不禁用业务功能、不拦截新提交、不弹强制处理窗口。
- `check=true, enforcement=true`:保持现有强制门禁;仅 `active/grace/legacy` 放行业务功能。
- `check=true, enforcement=true`:保持现有强制门禁;仅 `real_entitlement_allowed=true` 放行业务功能,该值只能与 `active/grace` 同时出现。
- `check=false, enforcement=true` 属于非法组合,客户端归一化为两者均关闭并写脱敏诊断,不允许在没有检测结果时强制锁定。
### 2. 启动策略获取与兼容
- 优先复用启动版本接口返回的 `client_policy`,不得为了读取开关再调用订阅状态接口,也不增加独立同步阻塞请求。
- 缓存最近一次结构合法的非敏感策略和取得时间到 `data/config/` 独立文件;不包含 API Key、账号、套餐或订阅结果。
- 当前响应有效时覆盖缓存;接口不可达、字段缺失或非法时使用最近一次有效缓存。无有效缓存时回退为“检测开启、强制关闭”的观察模式,避免控制面异常锁死正常用户;cmhub 产品接口继续作为最终授权边界。
- 当前响应有效时覆盖缓存;接口不可达、字段缺失或非法时使用最近一次有效缓存。缓存额外记录本地取得时间。无有效缓存时回退为“检测开启、强制关闭”的观察模式,避免控制面异常锁死正常用户;cmhub 产品接口继续作为最终授权边界。
- 旧 cmhub 响应不含 `client_policy` 时按上述兼容规则处理,不影响启动版本检查和强制升级。
- 只在启动时确定本次运行策略;服务端开关变更下一次启动生效。设置保存和“重新检测会员状态”只重查套餐,不偷偷改变本次策略。
@@ -56,7 +58,7 @@ cmhub 必须保证:`subscription_check_enabled=false` 时服务端产品接口
- `not_configured`:复用会员 API Key 激活窗口。
- `required`:新增“尚未开通会员套餐”,提供“前往会员中心”“重新检测”“退出程序”。
- `expired`:保留现有“会员套餐已过期”窗口及会员中心入口。
- `revoked`:新增“会员套餐已失效”,不得使用含糊的技术错误。
- `revoked`:保留兼容窗口“会员套餐已失效”,不得使用含糊的技术错误;当前 cmhub 不承诺返回该状态。
- `account_disabled`:新增“会员账号当前不可用”,提示前往会员中心或联系处理。
- `key_invalid`:打开可重新填写 API Key 的激活窗口并聚焦输入框,不使用泛化订阅窗口。
- `unavailable`:显示“暂时无法验证会员状态”,提供“重新检测”“打开设置”“退出程序”;不得误导用户未付费或要求重复订阅。
@@ -71,13 +73,13 @@ cmhub 必须保证:`subscription_check_enabled=false` 时服务端产品接口
## 验收要点
- [ ] 服务端双开关三种合法组合分别得到关闭、观察、强制三种稳定行为,非法组合不会锁死客户端。
- [ ] 明确关闭时启动不请求订阅状态;观察模式查询但不限制;强制模式保持现有门禁。
- [ ] 策略响应、缓存、旧响应、接口失败和无缓存回退均有测试,不记录敏感信息。
- [ ] `required/expired/revoked/account_disabled/key_invalid/unavailable/not_configured` 使用对应中文窗口或激活流程,不把技术异常说成未订阅。
- [ ] 分类窗口按状态转换去重,会员中心 URL 安全校验、重新检测、设置和退出操作可用。
- [ ] 服务端仍是授权最终来源;修改客户端开关不能绕过 cmhub 生成接口套餐校验。
- [ ] 不修改 Chrome、CDP、蝦皮采集、封面上传、拖拽或线上更新逻辑。
- [x] 服务端双开关三种合法组合分别得到关闭、观察、强制三种稳定行为,非法组合不会锁死客户端。
- [x] 明确关闭时启动不请求订阅状态;观察模式查询但不限制;强制模式保持现有门禁。
- [x] 策略响应、缓存、旧响应、接口失败和无缓存回退均有测试,不记录敏感信息。
- [x] `required/expired/revoked/account_disabled/key_invalid/unavailable/not_configured` 使用对应中文窗口或激活流程,不把技术异常说成未订阅。
- [x] 分类窗口按状态转换去重,会员中心 URL 安全校验、重新检测、设置和退出操作可用。
- [x] 服务端仍是授权最终来源;修改客户端开关不能绕过 cmhub 生成接口套餐校验。
- [x] 不修改 Chrome、CDP、蝦皮采集、封面上传、拖拽或线上更新逻辑。
## 测试与文档
@@ -107,3 +109,8 @@ git diff --check
## 执行记录
- 2026-07-28:完成客户端任务定义;等待 cmhub 启动策略接口契约与测试响应交付后解除阻塞。
- 2026-07-28:cmhub T-635 与线上契约已交付,确认 `client_policy`、服务端单枚举配置及 `real_entitlement_allowed` 语义,任务解除阻塞并开始实现。
- 2026-07-28:新增 `app/client_policy.py`,接入版本响应策略解析、非法组合归一化、`data/config/client_policy.json` 非敏感原子缓存和无缓存观察回退;启动流程把本轮策略传入主窗口。
- 2026-07-28:订阅状态改为只按 `real_entitlement_allowed` 放行;完成关闭/观察/强制三模式、设置页关闭态、七类中文处理流程和恢复前按状态去重,不修改 Shopee/CDP 链路。
- 2026-07-28:线上版本接口实测 HTTP 200、`Cache-Control: no-store`、策略 `off`;线上订阅接口脱敏实测返回 `active` 且真实权益允许。
- 2026-07-28:验证通过:策略/版本/订阅/GUI 定向测试 260 项;全量 `unittest discover` 717 项;`ruff check app tests main.py`、`compileall app main.py`、`git diff --check` 全部通过。