收敛半自动平台为登录获取 CK 流程

移除角色绑定对客户页、状态展示和完成门禁的阻塞;虎牙与微博统一保存并直接导出 CK;同步精简客服工作台、配置项和权威文档。
This commit is contained in:
yml
2026-11-14 01:13:00 +08:00
parent 8a54c41476
commit d178556f03
22 changed files with 526 additions and 732 deletions
+3 -2
View File
@@ -30,9 +30,10 @@ updated_at: 2026-11-08
- 半自动迁移已收敛为单个 `161_semi_auto_fulfillment.sql`,不得在已应用 main `158–160`
的库上重新引入 `153–156` 或 `162–165`。
- `161` 一次新增账号级 Cookie JSON 凭证表、`semi_auto_tasks.credential_id`、
最终 Connector 来源约束和 `semi_auto.credential.export` 权限;
最终 Connector 来源约束和兼容保留的 `semi_auto.credential.export` 权限记录;
该权限不再参与 CK 导出判定,导出由后台登录、禁止缓存和审计控制;
不迁移或清理订单、退款、资金流水等 A 级事实。
- 迁移完成后至少验证 `semi_auto_credentials` 表、任务外键、索引和导出权限存在;
- 迁移完成后至少验证 `semi_auto_credentials` 表、任务外键和索引存在;
用测试库完成 `001 → 161` 空库迁移,并在隔离库验证 `151 → 161`。
- 该增量仍包含迁移,普通停机发布不能使用 `deploy/ubuntu-deploy.sh` 在旧后端运行时直接换库;
必须沿用本手册的停写、最终备份、隔离恢复验证、迁移、新后端健康检查和验收流程。
@@ -43,14 +43,14 @@ updated_at: 2026-11-13
每一层只能回答一个问题:
| 层 | 唯一问题 | 唯一真源 |
| --- | --- | --- |
| 订单接入 | 平台实际发生了什么 | `orders` / `order_items` / 原始报文 |
| 商品身份 | 业务上这是什么商品 | `internal_skus` |
| 履约路由 | 这个商品默认由谁履约 | `sku_channel_routes` |
| 履约执行 | 当前实际执行到哪一步 | `fulfillments` / `fulfillment_attempts` |
| 财务商品 | 收入与成本归到哪个标准商品 | `product_catalog` / `channel_product_mappings` |
| 财务核算 | 应该记多少钱 | `cost_snapshots` / `sales_daily_facts` / `journal_*` |
| 层 | 唯一问题 | 唯一真源 |
| -------- | -------------------------- | ---------------------------------------------------- |
| 订单接入 | 平台实际发生了什么 | `orders` / `order_items` / 原始报文 |
| 商品身份 | 业务上这是什么商品 | `internal_skus` |
| 履约路由 | 这个商品默认由谁履约 | `sku_channel_routes` |
| 履约执行 | 当前实际执行到哪一步 | `fulfillments` / `fulfillment_attempts` |
| 财务商品 | 收入与成本归到哪个标准商品 | `product_catalog` / `channel_product_mappings` |
| 财务核算 | 应该记多少钱 | `cost_snapshots` / `sales_daily_facts` / `journal_*` |
任何页面、接口、任务和报表都必须从各自真源读取,不得根据另一层的字段反推。
@@ -276,7 +276,8 @@ fulfillment_issues
```text
manual fulfillment
→ semi_auto_tasks
→ 平台登录 / 角色绑定 / 浏览器辅助操作
→ 平台登录 / 获取账号 CK
→ 客服使用 CK 在平台侧手动处理
→ confirmManualFulfillment
```
@@ -285,32 +286,37 @@ manual fulfillment
- `fulfillments.channel` 仍为 `manual`;成本、销售与总账口径不变。
- 是否启用半自动履约由 `manual_fulfillment_configs.semi_auto_*` 显式配置,不能按商品名或平台前缀猜测。
- 半自动任务必须绑定 `order_item_id`、`fulfillments.id` 和人工履约配置,不得伪造接单平台工单。
- 登录状态、绑定状态、执行状态必须正交保存于 `semi_auto_tasks`;不得写入 `material_json` 作为正式状态。
- 当前阶段半自动平台接入的唯一职责是让客户完成平台登录并取得账号 CK。角色绑定、换绑、
角色校验和绑定失败处置属于后续业务流程,不进入当前客户页、主状态机或完成门禁。
- 登录状态和执行状态保存于 `semi_auto_tasks`,不得写入 `material_json` 作为正式状态。
`binding_status`、`bind_game_*` 和 `bound_at` 仅作历史兼容字段保留,当前登录、客服处理和完成主流程
不读取、不写入、不作为任何门禁。
- 平台 CK 是账号级凭证,唯一持久化真源为 `semi_auto_credentials`。Cookie 集合按平台 UID 唯一保存,
以 Cookie JSON 写入 `credential_payload_json`,并记录来源、更新时间、健康状态和最近检查错误。
以未加密 Cookie JSON 写入 `credential_payload_json`,并记录来源、更新时间、健康状态和最近检查错误。
`semi_auto_tasks.credential_id` 只引用账号凭证,任务表不保存 CK 明文。
- Connector 会话仍是进程内短期缓存,但不再是唯一真源。进程重启、会话过期或实例切换后,
执行器必须从账号级密文凭证恢复会话;恢复前校验平台 UID,恢复失败时更新凭证健康状态并要求重新登录。
支持恢复的执行器必须从账号级 Cookie JSON 恢复会话;恢复前校验平台 UID,
恢复失败时更新凭证健康状态并要求重新登录。
- 平台明确返回 CK 失效或账号不一致时,当前任务必须退出“已授权”状态,清空当前 Connector 会话并回到
`waiting_customer / waiting_login / not_started`;账号级凭证和历史事件保留用于审计。客服可对该任务
执行“重新发送授权”,重置当前任务并复制客户 `/c/<平台订单号>` 链接,客户重新登录后再绑定新凭证。
执行“重新发送授权”,重置当前任务并复制客户 `/c/<平台订单号>` 链接,客户重新登录后更新 CK。
- CK 不得进入普通任务 DTO、客户页面、任务事件、错误日志或审计明细。人工后台默认只展示平台 UID、
凭证来源、健康状态和更新时间;仅持有 `semi_auto.credential.export` 权限的角色可受控导出单个任务的
账号 Cookie,导出响应必须禁止缓存,审计只记录任务、凭证 ID 和平台,不记录 Cookie 内容。
凭证来源、健康状态和更新时间;已登录后台的管理员、运营或客服均可导出任务账号 CK,
不受 Connector 模式、任务领取人或额外权限限制。导出响应必须禁止缓存,审计只记录任务、
凭证 ID 和平台,不记录 Cookie 内容。
- 微博登录必须保留完整域名/路径 Cookie Jar,不能在跨域跳转后把所有同名 Cookie 合并成单个字符串。
浏览器注入只下发与目标 URL 匹配的 Cookie;账号级凭证保存完整集合,以便后续会话恢复和跨域重放。
浏览器注入只下发与目标 URL 匹配的 Cookie;账号级凭证保存完整集合,以便导出、会话恢复和跨域重放。
- 微博手机号登录首次发码返回 `mfa_1` 时,客户必须在浏览器完成网易易盾安全验证,再使用同一会话的
`mfa_id` 重发短信;服务端不尝试绕过或伪造人机验证。
- 半自动任务通过 `connector_mode` 显式记录 Connector 来源:
`embedded` 为 order_site 内置真实实现并作为默认值,`external` 为显式配置的远程真实实现,
`mock` 为 order_site 内置开发 Mock 且仅在非生产环境可用。开发 Mock 造单时默认选择 `embedded`,
只有需要完全脱离虎牙接口联调页面时才显式选择 `mock`。
只有需要完全脱离虎牙接口联调页面时才显式选择 `mock`。三种模式都必须能导出统一 Cookie JSON。
- 虎牙二维码登录有效期 `5` 分钟;登录成功后的 Connector 内存会话有效期 `24` 小时,
账号级 CK 由内部凭证表保存并通过健康检查判定有效性;角色绑定二维码 `5` 分钟;
浏览器一次性注入票据 `2` 分钟且消费后立即失效。重新登录前必须撤销旧 Connector 会话。
- 虎牙账号已经绑定游戏角色时,客户必须确认当前角色是否为本次需要的角色:选择“使用当前角色”时
不再调用虎牙换绑接口;选择“角色不对,重新扫码换绑”时重新生成绑定二维码,并在确认新角色时
调用换绑接口。未绑定账号和角色时直接走确认绑定。换绑冷却、未到可换绑时间等上游业务拒绝必须原样提示客户。
账号级 CK 由内部凭证表保存并通过健康检查判定有效性;浏览器一次性注入票据 `2` 分钟且消费后立即失效。
重新登录前必须撤销旧 Connector 会话。
- 虎牙客户登录成功后,无论账号此前是否已有角色,都立即保存 CK 并进入等待客服处理。
角色绑定、换绑和角色状态查询在后续独立流程实现,不能阻塞当前 CK 获取。
- 浏览器扩展复用 live-hub-py 的 `web/extension/huya-exchange-helper`,不新增第二个扩展;
扩展只允许消费一次性注入票据,页面不得直接读取 CK。
- 客服完成半自动任务必须与 `confirmManualFulfillment` 在同一数据库事务中提交:
@@ -361,25 +367,25 @@ finance_journal_* -- 总账凭证,可重建
## 四、单一真源矩阵
| 信息 | 唯一写入方 | 唯一真源 | 明确禁止 |
| --- | --- | --- | --- |
| 平台订单与订单项 | 订单接入服务 | `orders` / `order_items` | 财务或履约服务改写平台事实 |
| 平台原始报文 | 各平台适配器 | `order_source_snapshots` / 首次 `raw_payload_json` | 覆盖历史报文 |
| 中文内部 SKU | 商品身份服务 | `internal_skus` | 各业务表各自发明同义 SKU |
| 平台字段到内部 SKU | 映射服务 | `internal_sku_mappings` | 按名称猜测渠道 |
| 主渠道与兜底 | 路由服务 | `sku_channel_routes` | UI 根据商品前缀筛选 |
| 当前履约状态 | 履约状态服务 | `fulfillments` | 多服务直接更新订单项 |
| 执行尝试 | 履约尝试服务 | `fulfillment_attempts` | 用最大 ID 猜当前任务 |
| 当前异常 | 履约异常服务 | `fulfillment_issues` | 自由 JSON 字符串代替问题模型 |
| 半自动任务 | 半自动任务服务 | `semi_auto_tasks` / `semi_auto_task_events` | 把登录/绑定/执行状态写进 `material_json` |
| 客户平台 CK | 半自动凭证服务 | `semi_auto_credentials.credential_payload_json` | 写日志、普通接口返回或未审计导出 CK |
| 标准商品 | 商品主数据服务 | `product_catalog` | 用商品来源反推渠道 |
| 平台商品到财务商品 | 商品归一服务 | `channel_product_mappings` | 人工在多个页面重复维护 |
| 成本规则 | 成本中心 | `cost_versions` | 业务表直接改金额 |
| 成本事实 | 成本快照服务 | `cost_snapshots` | 改价覆盖历史 |
| 销售事实 | 事实服务 | `sales_daily_facts` | 报表直接从订单表现算另一套 |
| 总账 | 总账服务 | `finance_journal_*` | 业务端直接写凭证 |
| 页面投影 | 只读投影 | `v_*` / materialized view | 页面自行拼口径 |
| 信息 | 唯一写入方 | 唯一真源 | 明确禁止 |
| ------------------ | -------------- | -------------------------------------------------- | ---------------------------------------- |
| 平台订单与订单项 | 订单接入服务 | `orders` / `order_items` | 财务或履约服务改写平台事实 |
| 平台原始报文 | 各平台适配器 | `order_source_snapshots` / 首次 `raw_payload_json` | 覆盖历史报文 |
| 中文内部 SKU | 商品身份服务 | `internal_skus` | 各业务表各自发明同义 SKU |
| 平台字段到内部 SKU | 映射服务 | `internal_sku_mappings` | 按名称猜测渠道 |
| 主渠道与兜底 | 路由服务 | `sku_channel_routes` | UI 根据商品前缀筛选 |
| 当前履约状态 | 履约状态服务 | `fulfillments` | 多服务直接更新订单项 |
| 执行尝试 | 履约尝试服务 | `fulfillment_attempts` | 用最大 ID 猜当前任务 |
| 当前异常 | 履约异常服务 | `fulfillment_issues` | 自由 JSON 字符串代替问题模型 |
| 半自动任务 | 半自动任务服务 | `semi_auto_tasks` / `semi_auto_task_events` | 把登录/绑定/执行状态写进 `material_json` |
| 客户平台 CK | 半自动凭证服务 | `semi_auto_credentials.credential_payload_json` | 写日志、普通接口返回或未审计导出 CK |
| 标准商品 | 商品主数据服务 | `product_catalog` | 用商品来源反推渠道 |
| 平台商品到财务商品 | 商品归一服务 | `channel_product_mappings` | 人工在多个页面重复维护 |
| 成本规则 | 成本中心 | `cost_versions` | 业务表直接改金额 |
| 成本事实 | 成本快照服务 | `cost_snapshots` | 改价覆盖历史 |
| 销售事实 | 事实服务 | `sales_daily_facts` | 报表直接从订单表现算另一套 |
| 总账 | 总账服务 | `finance_journal_*` | 业务端直接写凭证 |
| 页面投影 | 只读投影 | `v_*` / materialized view | 页面自行拼口径 |
## 五、当前系统的问题证据
@@ -540,12 +546,12 @@ has_active_cost
客户页 `/c/<平台订单号>` 统一展示:
```text
平台登录 → 角色绑定 → 客服处理 → 完成
平台登录 → 获取 CK → 客服处理 → 完成
```
页面只能展示客户完成操作所需的最小信息,不得展示 CK、内部成本或其他订单。后台默认只展示平台 UID、
绑定角色、凭证来源、健康状态、更新时间和一次性注入入口;持有独立导出权限的角色可按任务受控查看
账号 CK,导出动作必须留审计且不得复用普通详情接口。
凭证来源、健康状态、更新时间、CK 导出和一次性注入入口。CK 导出不依赖角色绑定、任务领取人或
额外权限;导出动作必须留审计且不得复用普通详情接口。
## 八、存量数据处理方案
@@ -605,14 +611,14 @@ has_active_cost
## 九、目标迁移路线
| 阶段 | 状态 | 是否改生产数据 |
| --- | --- | --- |
| 0 口径冻结与文档收口 | 已完成 | 否 |
| 1 只读审计与领域约束 | 本地完成 | 否 |
| 2 建立目标身份与投影 | 本地完成 | 只新增结构 |
| 3 迁移路由与商品配置 | 本地完成,生产未执行 | 是,需备份 |
| 4 重建履约模型 | 本地完成,生产未执行 | 是,需备份 |
| 5 重建财务派生数据 | 本地完成,生产未执行 | 是,需备份与对账 |
| 阶段 | 状态 | 是否改生产数据 |
| -------------------------- | ------------------------ | ---------------- |
| 0 口径冻结与文档收口 | 已完成 | 否 |
| 1 只读审计与领域约束 | 本地完成 | 否 |
| 2 建立目标身份与投影 | 本地完成 | 只新增结构 |
| 3 迁移路由与商品配置 | 本地完成,生产未执行 | 是,需备份 |
| 4 重建履约模型 | 本地完成,生产未执行 | 是,需备份 |
| 5 重建财务派生数据 | 本地完成,生产未执行 | 是,需备份与对账 |
| 6 停止旧写路径并删除兼容层 | 履约侧已完成,全局未开始 | 是,需观察期结束 |
### 阶段 0:口径冻结与文档收口
@@ -745,7 +751,7 @@ assigned 且 carrier_status=missing 必须进入异常队列
2. 历史任务和工单补齐到 `fulfillment_attempts`,不再从订单项回调状态。
3. `transitionFulfillmentStateWithExecutor`、渠道分配和配置关联全部改写正式表。
4. `v_fulfillment_item_state` 只投影 `fulfillments + fulfillment_attempts +
fulfillment_issues + sku_channel_routes`。
fulfillment_issues + sku_channel_routes`。
5. 全部业务读 SQL 切到 `v_order_item_current`,禁止直接读取订单项旧状态列。
6. 状态事件、任务尝试、工单尝试和配置变化触发器统一围绕正式履约表工作。
7. 真实 PostgreSQL 集成测试覆盖状态写入、幂等、事件留痕、当前尝试和配置关联。
@@ -952,7 +958,8 @@ docs/archive/
截至 2026-11-13,生产基线为 `151`,集成分支开发基线为 `161`。迁移 `152` 保护订单来源快照,
迁移 `158–160` 收口寄卖登记人同步、寄卖平台与自动匹配设置;
迁移 `161` 一次建立人工渠道半自动任务、内置 Connector 默认值、账号级 Cookie JSON 凭证、
任务凭证引用、受控导出权限和最终约束。
任务凭证引用和最终约束。迁移中保留的 `semi_auto.credential.export` 权限仅作兼容记录,
不再作为 CK 导出门禁。
1. 生产升级只按 [生产升级操作手册](生产升级操作手册.md) 执行。
2. 升级前备份必须完成隔离恢复验证;恢复验证未通过时禁止迁移。
@@ -961,7 +968,6 @@ docs/archive/
4. 执行 `finance:rebuild-derived` 的 dry-run,核对 A 级数据守恒后,
再按窗口执行 `--execute --confirm=REBUILD_DERIVED`,并验证第二次重建幂等。
5. 观察一个完整财务期间,确认页面、履约、事实和总账持续对平。
6. 半自动履约继续完善微博手机号登录、易盾二次验证、完整域名 Cookie 保存、会话恢复和受控导出;
所有平台继续复用账号级凭证模型,不把平台专用 CK 状态写回订单或商品字段。
6. 半自动平台当前只负责客户登录和账号 CK 获取;继续完善微博手机号登录、易盾二次验证、
完整域名 Cookie 保存和会话恢复。角色绑定与换绑后续独立设计,不阻塞 CK 获取和客服处理。
7. 观察期结束后,再单独发布兼容表、旧脚本别名和 `legacy_*` 字段的删除迁移。