Files
chengma df9da63841
Tests / Python 3.11 / Windows (push) Has been cancelled
feat: 接入远程订阅策略门禁 T-705
2026-07-28 15:42:19 +08:00

8.4 KiB
Raw Permalink Blame History

id, title, phase, deps, status, created
id title phase deps status created
T-705 cmhub 远程订阅策略开关与分类门禁提示 8
T-700
T-701
DONE 2026-07-28

T-705 cmhub 远程订阅策略开关与分类门禁提示

问题 / 背景

当前客户端通过本地常量控制启动订阅检测和强制门禁,cmhub 无法在灰度上线、接口维护或异常期间远程切换。每次调整都需要重新修改并打包客户端。现有强制模式已经能限制业务 Tab、拦截新提交,并对缺少 Key 和套餐过期提供窗口,但未开通套餐、套餐撤销、账号禁用、Key 无效和接口异常仍缺少与原因匹配的独立窗口。

不能把远程开关放进订阅状态接口,否则客户端必须先请求该接口才能知道是否应跳过它。客户端门禁也不能成为服务端授权的唯一安全边界,cmhub 产品接口仍必须独立校验 API Key 和套餐。

外部契约(已交付)

cmhub 已按 Obsidian《cmhub-cmshopee客户端订阅策略接口契约》完成 T-635。客户端复用现有 HTTPS 启动版本接口:

最低要求是在客户端启动时已经请求的 HTTPS 版本接口中增加可选 client_policy:

{
  "client_policy": {
    "policy_version": 1,
    "subscription_check_enabled": true,
    "subscription_enforcement_enabled": true,
    "updated_at": "2026-07-28T10:00:00+08:00"
  }
}

cmhub 内部只配置 CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY=off|observe|enforce,对客户端仍输出上述两个布尔字段。订阅状态成功响应另提供顶层严格布尔字段 real_entitlement_allowed;强制模式必须只按该字段放行,不得使用展示用 status 或兼容 allowed 推断。当前成功状态为 active/grace/required/expired,账号禁用使用 HTTP 403;revoked 只保留客户端兼容处理,不属于当前服务端承诺状态。

cmhub 保证无论客户端门禁是否开启,付费产品接口仍独立执行服务端授权;客户端开关不是授权凭据。

方案

1. 远程双开关

  • check=false:跳过 SubscriptionCheckWorker,不显示会员激活/过期/异常窗口,不锁定业务 Tab;生成前订阅预检直接放行,设置页重新检测入口显示“服务端暂未启用会员检测”并禁用。
  • check=true, enforcement=false:执行真实查询并展示账号、套餐、有效期和观察状态,但不禁用业务功能、不拦截新提交、不弹强制处理窗口。
  • check=true, enforcement=true:保持现有强制门禁;仅 real_entitlement_allowed=true 放行业务功能,该值只能与 active/grace 同时出现。
  • check=false, enforcement=true 属于非法组合,客户端归一化为两者均关闭并写脱敏诊断,不允许在没有检测结果时强制锁定。

2. 启动策略获取与兼容

  • 优先复用启动版本接口返回的 client_policy,不得为了读取开关再调用订阅状态接口,也不增加独立同步阻塞请求。
  • 缓存最近一次结构合法的非敏感策略和取得时间到 data/config/ 独立文件;不包含 API Key、账号、套餐或订阅结果。
  • 当前响应有效时覆盖缓存;接口不可达、字段缺失或非法时使用最近一次有效缓存。缓存额外记录本地取得时间。无有效缓存时回退为“检测开启、强制关闭”的观察模式,避免控制面异常锁死正常用户;cmhub 产品接口继续作为最终授权边界。
  • 旧 cmhub 响应不含 client_policy 时按上述兼容规则处理,不影响启动版本检查和强制升级。
  • 只在启动时确定本次运行策略;服务端开关变更下一次启动生效。设置保存和“重新检测会员状态”只重查套餐,不偷偷改变本次策略。

3. 分类窗口

  • not_configured:复用会员 API Key 激活窗口。
  • required:新增“尚未开通会员套餐”,提供“前往会员中心”“重新检测”“退出程序”。
  • expired:保留现有“会员套餐已过期”窗口及会员中心入口。
  • revoked:保留兼容窗口“会员套餐已失效”,不得使用含糊的技术错误;当前 cmhub 不承诺返回该状态。
  • account_disabled:新增“会员账号当前不可用”,提示前往会员中心或联系处理。
  • key_invalid:打开可重新填写 API Key 的激活窗口并聚焦输入框,不使用泛化订阅窗口。
  • unavailable:显示“暂时无法验证会员状态”,提供“重新检测”“打开设置”“退出程序”;不得误导用户未付费或要求重复订阅。
  • 同一运行期间同一状态只显示一次;状态恢复为允许后再次进入无效状态才可重新提示。重复检测、保存设置和陈旧 worker 结果不得造成弹窗循环。
  • 会员中心地址继续使用 subscription.safe_manage_url() 的 HTTPS 安全结果;无有效地址时禁用入口并显示中文原因。

4. 门禁边界

  • 强制模式查询期间和明确无效状态只保留“设置”Tab;AI生成、AI帮写和商品套图的新提交继续经过主窗口统一预检。
  • 不改变已经运行任务的协作取消策略,不删除本地结果、不修改 SQLite 业务数据、不关闭 Chrome。
  • cmhub 托管生成接口仍必须服务端校验套餐;自定义网关和客户端本地功能是否受门禁影响沿用当前产品规则,本任务不扩张授权范围。

验收要点

  • 服务端双开关三种合法组合分别得到关闭、观察、强制三种稳定行为,非法组合不会锁死客户端。
  • 明确关闭时启动不请求订阅状态;观察模式查询但不限制;强制模式保持现有门禁。
  • 策略响应、缓存、旧响应、接口失败和无缓存回退均有测试,不记录敏感信息。
  • required/expired/revoked/account_disabled/key_invalid/unavailable/not_configured 使用对应中文窗口或激活流程,不把技术异常说成未订阅。
  • 分类窗口按状态转换去重,会员中心 URL 安全校验、重新检测、设置和退出操作可用。
  • 服务端仍是授权最终来源;修改客户端开关不能绕过 cmhub 生成接口套餐校验。
  • 不修改 Chrome、CDP、蝦皮采集、封面上传、拖拽或线上更新逻辑。

测试与文档

  • 扩展 tests/test_update_check.py:策略字段解析、非法组合、旧响应和策略透传。
  • 新增或扩展订阅策略缓存测试:有效缓存、损坏缓存、接口失败和无缓存观察回退。
  • 扩展 tests/test_gui.py:关闭/观察/强制模式、七类状态窗口、去重、重检和门禁。
  • 扩展 tests/test_subscription.py:状态与窗口动作映射所需的纯逻辑契约。
  • 更新 docs/04-architecture.md、docs/api.md、docs/routes.md 和打包/发布说明。

验证

py -3.10 -m unittest tests.test_update_check tests.test_subscription tests.test_gui
py -3.10 -m unittest discover -s tests
py -3.10 -m ruff check app tests main.py
py -3.10 -m compileall app main.py
git diff --check

边界(不改什么)

  • 不把客户端开关当成服务端授权凭据。
  • 不在订阅状态接口中返回“是否调用本接口”的开关。
  • 不新增同步启动阻塞请求,不把网络故障等同于未付费。
  • 不提交 API Key、账号、套餐响应、配置、数据库、日志或业务数据。

执行记录

  • 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 全部通过。