Files
cmhub/docs/tasks/T-636.md
T

5.4 KiB

T-636 客户端订阅策略 django-admin 运营开关

背景

T-635 已经通过公开版本检查接口向新版 cmshopee 客户端发布启动订阅策略, 但策略只能通过修改 .env 后重启 Web / Generate 服务变更。该方式不适合日常 运营,也无法在 django-admin 中留下明确的变更原因和操作者。

客户端策略和 CMSHOPEE_SUBSCRIPTION_MODE 的服务端授权仍是两件事:前者只 决定新版客户端是否检查 / 展示会员门禁,后者才决定产品专属生成接口是否按真实 权益拦截。本任务不得混淆或合并这两套开关。

目标

  1. 让超级管理员在 django-admin 中用单一枚举切换 off、observe、enforce。
  2. 每次变更必须留存原因、操作者、前后值和时间。
  3. 公开版本检查接口在下一次请求立即发布后台策略,无需重启服务。
  4. 未配置后台策略时完全保留 T-635 .env 行为,保证上线不改变当前客户端。

实施范围

数据模型与策略来源

  • 新增全局单例 ClientSubscriptionPolicy,仅保存一个固定主键记录;字段至少有 mode、updated_by、created_at、updated_at。
  • 模式只能是 off|observe|enforce,输出继续复用 T-635 的统一映射: off -> false/false、observe -> true/false、enforce -> true/true。
  • 新增不可修改的策略审计记录,保存 previous_mode、mode、必填 reason、 changed_by、changed_at。审计不保存 API Key、用户权益、点数、订单、prompt 或图片。
  • 迁移只创建空表,不写预置策略记录。策略解析顺序固定为:数据库单例存在时优先 使用其 mode + updated_at;记录不存在时回退 CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY 与 CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY_UPDATED_AT。
  • 公开接口每次请求读取单例,不使用进程内缓存;因此 admin 保存成功后下一次请求 即生效。数据库不可用仍按既有 Django 请求失败语义处理,不得静默发布错误策略。

django-admin

  • 日常导航只增加“客户端订阅策略”一个入口;审计仅作为该详情页的只读 inline, 不单独出现在导航。
  • 仅超级管理员可新增或编辑;不允许删除。首次创建后禁止新增第二条记录。
  • 表单除 mode 外必须填写“变更原因”。服务层负责事务内写单例与审计,禁止通过 admin 直接 save() 绕过审计。
  • 展示当前 CMSHOPEE_SUBSCRIPTION_MODE 为只读信息,明确它是服务端授权模式; 本页不得修改该环境变量,也不得修改权益、套餐、席位、凭证、订单、钱包或点数。
  • 相同模式不应制造伪变更审计;要求运营选择不同模式后再保存。

API 与兼容

  • GET /api/v1/client/releases/latest?platform=windows 顶层 client_policy 结构、 policy_version=1、字段类型和 Cache-Control: no-store 保持 T-635 合约。
  • 有发布、release:null 和无下载地址路径均使用同一策略来源;既有 force_update、size_bytes 等发布字段不回归。
  • 此接口仍匿名只读、无账号上下文,不读取 SoftwareEntitlement、套餐、点数、 订单、API Key 或生成模型;新增的仅是全局策略配置读取。
  • 不修改 CMSHOPEE_SUBSCRIPTION_MODE,不改变通用或专属生成接口、计费预扣 / 确认 / 退款、支付回调、软件订单、异步图片任务或旧客户端行为。

部署与回滚

  1. 备份生产应用和数据库,发布代码并执行 migrate;迁移不会创建策略记录。
  2. 首次部署后确认 .env 兜底策略仍为 off,公开接口保持 subscription_check_enabled=false、subscription_enforcement_enabled=false。
  3. 超级管理员可创建单例并按 off -> observe -> enforce 灰度;每次保存立即以新的 updated_at 发布,无需重启。
  4. 需要紧急取消客户端门禁时,在后台将模式改为 off;若后台记录尚未创建,继续 使用 .env 兜底。不要把此操作误认为取消服务端授权。
  5. 若需恢复到纯 .env 来源,必须先在维护窗口以受控数据操作移除单例记录;本任务 的 admin 不提供删除入口,避免误删和审计丢失。

验收条件

  1. 无后台记录时三种合法 .env 配置保持 T-635 映射与启动校验。
  2. 后台记录存在时优先于 .env;保存 observe / enforce 后下一次公开请求立即 返回正确双布尔值与稳定、带时区的 updated_at。
  3. 模型层和后台均不能创建第二条记录,后台不能删除;非超级管理员不能新增或编辑。
  4. 每次有效变更都写一条只读审计,包含前后模式、非空原因、操作者和时间;相同模式 被表单拒绝,不写伪审计。
  5. 审计不出现在 admin 日常导航,策略页可只读查看历史;服务端授权模式只读展示。
  6. 版本检查接口继续匿名、Cache-Control: no-store,且发布字段和无发布路径不回归; 不查询或泄露用户、权益、套餐、点数、订单、API Key 或密钥。
  7. 同步更新 docs/api.md、docs/env.md、docs/deployment.md、 docs/04-architecture.md、docs/current-state.md、任务状态、progress.md 和 Obsidian 客户端契约。
  8. makemigrations --check --dry-run、migrate、check、目标 API / licensing / admin 测试、init.ps1 与 git diff --check 通过。

状态

TODO。