--- id: T-696 title: 会员订阅真实检测观察模式 phase: 7 deps: [T-686] status: DONE created: 2026-07-23 --- ## 问题 / 背景 T-686 已完成 cmhub 账号订阅状态查询、顶部会员信息、工作流门禁和新提交预检,但为方便完整功能测试,当前通过 `SUBSCRIPTION_CHECK_ENABLED = False` 同时暂停了真实查询和客户端限制。 2026-07-23 使用本机已配置且未输出的 cmhub API Key 实测 `GET /api/v1/cmshopee/subscription/status`:接口已返回 `active`,套餐名为“测试”,账号、有效期、宽限期、会员中心地址和通知标识均能被现有客户端正确解析。服务端表示已为现有用户配置可正常使用的测试套餐,但单个账号实测不能证明所有存量账号都已配置 Key、均被套餐覆盖,也不能消除启动时网络或接口临时异常。 若直接恢复 T-686 的强制门禁,未配置 Key、Key 失效、套餐漏配或一次网络失败都会只保留“设置”Tab,可能影响存量用户。需要先用一个发布周期的观察模式验证真实覆盖情况,再单独决定何时启用强制门禁。 ## 方案 ### 1. 拆分检测与强制门禁 - 启用真实订阅检测:启动升级检查完成并显示主窗口后,继续通过现有 `SubscriptionCheckWorker` 异步请求订阅接口;保存 cmhub 设置后立即重新检查。 - 增加独立的客户端强制开关。当前任务固定为“检测启用、强制关闭”,不能再用一个布尔值同时暂停两件事。 - 观察模式不是授权结论:cmhub 产品接口仍是最终授权方,客户端不得伪造有效套餐或把观察结果写入 SQLite。 ### 2. 观察模式访问行为 - 启动查询期间不禁用任何工作流 Tab;用户可继续使用本地功能。 - `active`、`grace`、未配置 Key、Key 无效、未订阅、到期、撤销、账号禁用、网络失败、非法响应和旧服务兼容状态,在观察模式下都不禁用 Tab、不自动切换“设置”、不阻止 AI生成、AI帮写、商品套图或自定义网关的新提交。 - `ensure_subscription_for_new_submit()` 在观察模式始终放行;不得因查询尚未完成而中止用户操作。 - 已有异步任务查询、下载、历史、导出以及蝦皮采集/更新边界保持不变。 ### 3. 状态展示与干扰控制 - 有效或宽限状态继续在顶部显示“账号名 · 套餐名 · 有效至/宽限至日期”,不得展示 API Key。 - 其他状态在顶部和状态栏显示中文、脱敏的观察结果,并明确“当前不影响使用”;网络失败不能误报为无订阅或 Key 无效。 - 观察模式不显示 T-686 的“已启用会员订阅”模态通知框,不因新的 `notice_id` 打断存量用户;正式门禁启用后再恢复一次性通知逻辑。 - 不记录原始响应、完整接口路径、API Key、账号凭据或支付信息。 ### 4. 为正式门禁保留单一切换点 - 强制模式仍复用 T-686 已验证的规则:有效、宽限和旧服务兼容允许使用;明确无效状态限制工作流;服务暂时不可用的最终失败策略留给后续正式门禁任务确认。 - 观察与强制分支集中在主窗口订阅协调层,不把模式判断散落到 AI生成、商品套图或 Worker。 - 后续启用正式门禁必须另建任务,基于观察结果确认存量 Key 覆盖率、测试套餐覆盖率、网络失败策略和发布回滚方案,不能只改常量后直接发布。 ## 验收要点 - 启动程序会真实请求已上线订阅接口,不再显示“订阅检测已暂停”。 - 当前测试套餐账号返回有效状态后,顶部正确显示账号、套餐“测试”和有效期。 - 查询期间以及任一非有效/异常状态下,六个工作流仍可访问,新提交预检仍放行。 - 观察模式不自动切换“设置”,不弹出会员订阅模态通知框。 - 保存设置后会重新检查;陈旧线程结果不会覆盖较新的检查结果。 - 切换到后续强制模式时,T-686 的限制逻辑仍可由测试覆盖,不需要修改各业务 Tab。 - 自动验证: - `py -3.10 -m unittest discover -s tests -p "test_subscription.py"` - 主窗口订阅观察/强制模式定向 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` ## 边界(不改什么) - 不实现服务端套餐、支付、续费、退款、订单、账号登录或会员中心页面。 - 不启用正式客户端强制门禁,不把一次本机账号成功宣称为全量存量用户验收完成。 - 不修改订阅接口路径、响应 schema、状态解析模型或 cmhub 产品接口最终授权。 - 不修改 Chrome/CDP、蝦皮采集、上传、拖拽或线上更新逻辑。 - 不提交本地 API Key、配置、数据库、日志、图片或接口原始响应。 ## 执行记录 - 2026-07-23:将订阅查询和客户端强制门禁拆为 `SUBSCRIPTION_CHECK_ENABLED = True` 与 `SUBSCRIPTION_ENFORCEMENT_ENABLED = False`。程序显示主窗口后会异步查询真实订阅接口,保存 cmhub 设置后立即重新查询。 - 观察模式在查询中及任一订阅结果下都保持六个工作流和新提交入口可用;非有效状态只显示“当前不影响使用”的中文观察结果,不自动切换设置。有效/宽限状态继续展示账号、套餐和日期,观察期不显示 `notice_id` 模态通知。 - 保留 T-686 正式门禁分支和回归覆盖;后续启用门禁只需单独评审并切换协调层开关,不需要修改各业务 Tab。 - 使用本地已配置但未输出的 API Key 通过真实 `SubscriptionCheckWorker` 联调成功:状态 `active`、套餐“测试”、有效期 `2026-08-21`,账号字段存在;未记录原始响应或敏感信息。 - 验证通过:订阅解析测试 6 项、主窗口观察/强制定向测试 4 项、`py -3.10 -m unittest discover -s tests`(682 项)、`py -3.10 -m ruff check app tests main.py`、`py -3.10 -m compileall app main.py`、`git diff --check`。