feat: add software entitlement foundations

This commit is contained in:
QiuSW
2026-07-21 09:51:29 +08:00
parent 11c0d63ac8
commit 7b80ae3a7a
12 changed files with 1191 additions and 13 deletions
+1 -1
View File
@@ -104,7 +104,7 @@
| T-623 | 图片生成任务单图 / 多图筛选 | T-614, T-620 | 已完成:`ImageGenerationTaskAdmin` 的列表右侧新增“输入图片类型”筛选,提供“单图生图”和“多图生图”。数据库聚合计数识别 1 条子输入的单图、2 条及以上的多图;无子输入且历史 `input_image` 非空的任务兼容归单图;无输入图任务不归类。筛选可与既有状态 / 日期过滤叠加,结果不重复;未改模型、迁移、任务状态、计费、API、worker、媒体文件或详情页缩略图。已通过 6 条目标 admin 测试、`check`、迁移一致性和 `init.ps1`。 | DONE |
| T-624 | 蝦皮圈设备登记与会话观测 | T-301, T-401 | 已完成:新增 `apps.licensing`、`ClientDevice` / `DeviceSession` / `DeviceBindingAudit` 与 `licensing.0001_initial`。设备登记用 API Key 鉴权、心跳用短期 `X-Device-Session`;重复登记不重复建设备并轮换旧会话,设备/公钥/会话只存摘要或 hash,活跃时间默认每日节流。admin 只读展示设备、会话和审计摘要,不回显敏感值。现有生成、余额、模型目录、异步任务和通用 API Key 语义未改变。已通过本地迁移、21 条目标回归测试、`check`、迁移一致性和 `init.ps1`。 | DONE |
| T-625 | 蝦皮圈设备使用关联与迁移观测 | T-624, T-613, T-614, T-615 | 已完成阶段 1 关联观测:有效 `X-Device-Session` 仅在标题、同步图片、异步图片提交、vision 的预扣 `CallRecord` 写入服务端解析的可空 `client_device`;无头旧调用保持原返回、扣点、提交和轮询。新增 `billing.0010_callrecord_client_device_and_more` 与 `(client_device, created_at)` 索引;admin 支持展示 / 按设备筛选。`generation_route_usage` 新增 `product_code`、内部 `client_device_id`、`device_session_present` 白名单字段,不记录设备摘要、公钥、令牌、Key、prompt 或图片。伪造/过期会话在预扣前返回 401,吊销/跨账号会话返回 403;仍不做订阅授权拦截。已通过 4 条新增入口/兼容/安全/遥测测试及 14 条 licensing/生成回归、迁移、`check` 和一致性验证。 | DONE |
| T-626 | 软件套餐、权益与设备席位基础模型 | T-624, T-401 | **阶段 2 的数据与后台基础,不接购买页、不改生成授权。** 新增 `SoftwarePlan`、`SoftwareEntitlement`、`LicenseSeat`、`LicenseEvent` 模型及 django-admin;套餐保存 `product_code`、名称、时长、价格、设备数、状态,权益保存用户、产品、购买时套餐快照、状态、开始/到期/宽限时间;席位按权益和序号唯一,事件记录人工授予、续期、撤销、解绑等原因。建立单一 licensing service,提供手工授予、续期、撤销、分配/释放席位的事务方法;续期从 `max(now, expires_at)` 计算,禁止直接改钱包或 `points_balance`。后台人工操作必须填原因并生成审计事件,历史权益不可被套餐后来编辑反向篡改。测试覆盖套餐快照、同一权益并发占用席位不超限、续期计算、撤销、审计和 admin 权限;同步数据模型、运营流程与迁移说明。 | TODO |
| T-626 | 软件套餐、权益与设备席位基础模型 | T-624, T-401 | 已完成阶段 2 基础模型:新增 `SoftwarePlan`、`SoftwareEntitlement`、`LicenseSeat`、`LicenseEvent` 和 `licensing.0002_softwareentitlement_licenseseat_licenseevent_and_more`。授予时复制套餐名称/价格/时长/设备数/宽限期快照并预创建固定席位;`(entitlement, seat_number)` 唯一。服务层以事务锁权益和席位执行授予、续期、撤销、绑定与解绑,所有人工操作原因必填并写事件;续期从 `max(now, expires_at)` 起算,不触碰钱包。admin 提供套餐维护及权益授予/续期/撤销专用入口,权益/席位/事件只读。未接购买、支付、迁移凭证或生成授权。已通过套餐快照、续期、撤销、审计、后台权限及双连接单席位并发测试、迁移和 `check`。 | DONE |
| T-627 | 存量用户迁移权益、网页确认与设备凭证 | T-624, T-626, T-501 | 实施“自动迁移权益 + 网页确认当前设备”而非旧 API Key 自动抢占设备。新增 `LegacyMigrationGrant` / 一次性 `MigrationRequest` 和产品专用 `DeviceCredential`(均只存 hash/摘要);提供后台按资格快照批量或受控创建迁移权益,默认设备数和迁移到期日由明确配置/管理动作决定,新注册用户不得自动领取。客户端以旧 API Key 仅可为当前设备创建短时迁移请求;网页登录的 portal 页面确认同账号、同设备和未占用席位后,在事务内绑定席位并签发仅本次显示的设备凭证。重复确认、客户端轮询重试、浏览器刷新和响应丢失均幂等;复制旧 API Key 不能绕过网页登录确认。支持受审计的自助/客服解绑,吊销旧凭证;不改变旧生成接口,迁移窗口内旧客户端仍可用。测试覆盖资格边界、跨账号拒绝、过期/重复请求、并发确认只占一席、凭证 hash 与吊销、旧接口兼容;同步 portal 路由、API 契约、迁移与隐私文档。 | TODO |
| T-628 | 蝦皮圈专属授权入口与影子校验 | T-625, T-626, T-627, T-613, T-614 | 新增蝦皮圈**专属**产品调用入口或明确的产品认证分流,使用 `DeviceCredential + X-Device-Session` 解析产品、用户和设备;不得在通用 `/api/v1/generate/*` 上给全部 API Key 强加订阅校验。实现统一 `licensing` 授权服务/permission,区分“可新提交生成”和“可读取本人已接受任务”,返回稳定结构化错误码(如 `device_not_bound`、`device_mismatch`、`license_required`、`license_expired`),但本任务先以影子模式记录 `would_reject`,不实际阻断已迁移或旧客户端。蝦皮圈专属 title、vision、异步 image submit 接入该服务;已接受任务的查询/下载始终按任务归属可读。测试覆盖通用 API 完全不回归、专属凭证认证、跨用户拒绝、影子结果日志脱敏、过期权益的 would-reject、已接受任务读取和点数账本不被授权检查重复修改;同步 API、架构、部署开关和桌面端对接文档。 | TODO |
| T-629 | 软件套餐购买、续订订单与权益入账 | T-626, T-627, T-628, T-304, T-305 | 新增与 `RechargeOrder` **分离**的 `SoftwareOrder`,实现蝦皮圈套餐选择、创建待支付订单、支付回调/主动查单后的幂等权益发放与续期;不得把软件订阅金额兑换为点数,也不得改动充值订单或既有点数回调契约。订单须锁定套餐名称、价格、时长、设备数等快照,回调必须验签、校验订单金额/通道、按订单号幂等;同一订单重复回调最多延长一次。portal 提供订阅状态、套餐购买/续订入口和订单只读记录,支付失败/取消保持 pending/failed 语义并保留审计。复用现有支付网关的微信路径但不假设自动续费协议;第一版“月订阅”是用户每月主动续订,自动代扣仅登记后续任务。测试覆盖订单快照、重复回调、金额不匹配、并发回调、续期起算、退款/撤销后的权益状态、充值链路回归;真实生产支付验收依赖既有微信回调闭环修复,未提供商户条件时仅按 mock/SDK 契约测试。 | TODO |