feat: add client subscription startup policy
This commit is contained in:
@@ -48,6 +48,8 @@ T-629 已完成:`SoftwareOrder` 属于 `apps.licensing`,与 `RechargeOrder`
|
||||
|
||||
T-630/T-632 已完成:蝦皮圈产品授权从设备凭证改为账号订阅。`evaluate_account_authorization(user, product_code)` 只计算数据库真实 `SoftwareEntitlement` 状态,不读取 `DeviceCredential`、`LicenseSeat` 或 `DeviceSession`;`evaluate_subscription_access()` 再按 `CMSHOPEE_SUBSCRIPTION_MODE=open|shadow|enforce` 计算最终访问结果。`open` 和 `shadow` 不写虚假权益,前者提供开发测试访问,后者保留访问并记录真实权益覆盖;`enforce` 才将无订阅/过期结果映射为 403。同一用户可从多台设备调用,过期设备会话不会阻断账号订阅;通用生成入口继续保持原 API Key + 点数语义。
|
||||
|
||||
T-635 在公开版本检查接口顶层增加无账号上下文的 `client_policy`,由 `CMSHOPEE_CLIENT_SUBSCRIPTION_POLICY=off|observe|enforce` 和其带时区更新时间生成,成功及错误响应均 `Cache-Control: no-store`。这只控制新版客户端是否检查 / 展示会员门禁,不覆盖 `CMSHOPEE_SUBSCRIPTION_MODE` 的服务端授权;订阅状态接口新增 `real_entitlement_allowed`,仅真实 `active` / `grace` 权益为真,客户端强制门禁必须使用它而非 `open` / `shadow` 的兼容 `allowed`。
|
||||
|
||||
T-632 同时简化软件授权 admin:应用索引只展示“会员套餐” (`SoftwarePlan`) 与“用户会员” (`SoftwareEntitlement`)。软件订单、授权事件、设备观测和历史设备授权模型仍注册并保留直接管理地址、权限及历史数据,只是不出现在日常导航;该显示策略不改变数据库结构和授权判定。
|
||||
|
||||
T-627 已建立存量迁移闭环:运营在 admin 显式创建 `LegacyMigrationGrant`,它关联一项套餐快照权益及资格快照,新注册用户不会自动创建。客户端必须以旧 API Key 加服务端验证的当前设备会话申请 `MigrationRequest`;请求只短时有效,生成的设备凭证明文只在该 API 响应出现一次。portal 仅允许请求所属账号确认,确认事务内分配席位、按请求中已存 token hash 签发 `DeviceCredential`,重复确认只返回既有结果。用户自助解绑会吊销凭证、写授权事件并释放对应席位。原始凭证、机器标识、公钥和 API Key 都不写入迁移记录 / 事件;T-628 才会用凭证参与专属接口影子校验。
|
||||
@@ -253,7 +255,7 @@ CREATE TABLE import_template (
|
||||
);
|
||||
```
|
||||
|
||||
T-102 已实现 `AiModel` / `ModelAlias` 的 Django models、admin、迁移与别名解析。T-103 已补 `AiConfigAuditLog`,admin 里保存/删除模型配置或能力别名时自动写审计日志。T-202 已实现 `PricingRule` / `ExchangeRate` 与 `apps.billing.pricing` 计算函数:定价按 `operation_type + alias + resolution` 查 active 规则,优先 exact resolution,再回退到空 resolution 默认价;缺规则抛 `NoPricingRuleError(code="no_pricing_rule")`。T-203 已实现 `apps.billing.services`:`precharge_call()` 锁 `UserWallet` 行预扣并写 pending 调用与 consume 流水;`mark_call_success()` 确认成功不再改余额;`refund_call_points()` 锁调用记录并幂等退点,写 refund 流水。T-401 已在同一计费层新增 `adjust_wallet_points()`,供 admin 手工调点使用。T-606/T-609/T-617/T-618 已实现 `DownloadRelease`,admin 可上传安装包或填写 `external_url`、标记当前版本、配置是否强制更新和文件大小字节数;T-618 起 admin 新增 / 编辑发布版本时 `sha256` 与 `size_bytes` 必填,但数据库仍保留空值兼容历史记录;`external_url` 优先于 `file.url`,每平台仅一个当前版本由模型 `save()` 在事务内把同平台旧 current 置为 false。T-610 已新增 `ImportTemplate`,admin 可上传导入模板或填写 `external_url` 并标记当前模板;`external_url` 优先于 `file.url`,当前模板互斥同样由应用层事务处理,不使用 MySQL 不支持的条件唯一约束。T-607/T-609/T-617 版本检查接口只读取 `DownloadRelease(platform, is_current=True)`;响应 URL 是外部可访问 URL,不暴露本地 `MEDIA_ROOT`,并把 `force_update` 和 `size_bytes` 作为公开发布元数据返回。导入模板下载不新增对外 JSON API,首页直接渲染当前模板下载链接。默认别名唯一性由 model validation、admin 与导入器保证;MySQL 不支持通用 partial unique index,若后续要强制数据库层默认别名唯一,可另评估触发器或约束表。
|
||||
T-102 已实现 `AiModel` / `ModelAlias` 的 Django models、admin、迁移与别名解析。T-103 已补 `AiConfigAuditLog`,admin 里保存/删除模型配置或能力别名时自动写审计日志。T-202 已实现 `PricingRule` / `ExchangeRate` 与 `apps.billing.pricing` 计算函数:定价按 `operation_type + alias + resolution` 查 active 规则,优先 exact resolution,再回退到空 resolution 默认价;缺规则抛 `NoPricingRuleError(code="no_pricing_rule")`。T-203 已实现 `apps.billing.services`:`precharge_call()` 锁 `UserWallet` 行预扣并写 pending 调用与 consume 流水;`mark_call_success()` 确认成功不再改余额;`refund_call_points()` 锁调用记录并幂等退点,写 refund 流水。T-401 已在同一计费层新增 `adjust_wallet_points()`,供 admin 手工调点使用。T-606/T-609/T-617/T-618 已实现 `DownloadRelease`,admin 可上传安装包或填写 `external_url`、标记当前版本、配置是否强制更新和文件大小字节数;T-618 起 admin 新增 / 编辑发布版本时 `sha256` 与 `size_bytes` 必填,但数据库仍保留空值兼容历史记录;`external_url` 优先于 `file.url`,每平台仅一个当前版本由模型 `save()` 在事务内把同平台旧 current 置为 false。T-610 已新增 `ImportTemplate`,admin 可上传导入模板或填写 `external_url` 并标记当前模板;`external_url` 优先于 `file.url`,当前模板互斥同样由应用层事务处理,不使用 MySQL 不支持的条件唯一约束。T-607/T-609/T-617/T-635 版本检查接口只读取 `DownloadRelease(platform, is_current=True)` 与无状态环境配置;响应 URL 是外部可访问 URL,不暴露本地 `MEDIA_ROOT`,并把 `force_update`、`size_bytes` 和 `client_policy` 作为公开元数据返回。`client_policy` 有独立的配置更新时间且在 `release:null` 时仍返回,不读取用户、订阅、套餐或点数。导入模板下载不新增对外 JSON API,首页直接渲染当前模板下载链接。默认别名唯一性由 model validation、admin 与导入器保证;MySQL 不支持通用 partial unique index,若后续要强制数据库层默认别名唯一,可另评估触发器或约束表。
|
||||
|
||||
> 可选增强(接口预留、MVP 不实现):`account_alias_permission`(按账号授权可用别名,防止调用方点用未授权/昂贵模型);别名按比例分流到多个模型(灰度/AB/故障转移)。适配器接口需为此留口子。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user