Files
ft/CodexOutput/upserver/B3BatchMigration/M2/M2-CP2B-T正式KV普通业务请求恢复完整方案-待独立审查.md
Liubing\LB 6813da149a feat(upserver): 保存M2客户端KV迁移至本人统计写检查点
保存独立KV用户服务、固定会话存档与原业务接线,以及C3d资料缓存和C3e本人统计写。
保留原PF/AGG路线、业务公式和时序;榜单读取、好友资料、公告、匹配及首场景闸仍待完成。

验证:ServiceHost两条件各33组646断言;Unity CLI Loop编译0错误269警告。
包含相关方案、评审裁决、测试及状态文档。未操作服务器、正式账号或打包。
2026-09-30 19:19:05 +08:00

8.0 KiB
Raw Blame History

M2 CP2B-T 正式 KV 普通业务请求恢复完整方案(待独立审查)

日期:2026-09-29。本文只批准评审输入,不是编码批准。 用户明确:kvOnly 对普通请求的拒绝是移植期临时处理,正式 KV 应像原业务流程一样走正常请求。按“同合同一次批级前审、批内连续实施、一次批末复核”减少审核往返;受审 hash 见同目录基线清单,报告落盘后主会话复算、逐项裁决、冻结白名单,再动生产代码。现有工作树保留,本机服务器源码不访问或修改。

1. 已核事实与批次边界

旧 f40a816cc 的 CustomServerMgr.CustomServerPost/GetStringAsync 以一个 HttpClient 发送普通业务请求。迁移提交 0eb43b2b4 加入 kvOnly,把普通 SendAsync 拒绝在入口;当前 BindKVForGame 复用此模式,PlayerKVAccountLease.SendAsync 只接受 __kv_validation/ok 和 __kv_validation/unauthorized。这证明拒绝是迁移门,不是线上 API 的产品合同。

正式 KV 登录已经通过同一 S101AccountSession 的 CookieContainer 创建互不共享的认证、KV、租约 handler;租约归 PlayerKVLoginContext,有 epoch/current、活动请求排水及 Close 屏障。租约在 31 模块 Apply 之前就绑定到 CustomServerMgr;因此不能在 BindKVForGame 时立刻开放普通请求。CP3A 的原 handle 与 Setting/Club/Notification 交接完成之后,才有可作为本批“运输就绪”的时点。

本批目标:在正式 KV 已 GameLoaded、原 handle 和三原实例交接均成功时,现有 ICustomServerMgr 的 GetStringAsync、CustomServerPost 及 Account/Event/Club/Friend/...Request 包装方法可以通过同一个账号租约和 Cookie发送规范相对路径,并沿用现有“HTTP 200 返回正文,否则空结果/错误事件”的公共合同;旧会话、退出和 401/403 必须同步失效。非 KV/PF 分支行为不变。验证租约仍只准两个验证路由。本批不开放 FishingStage,不调用正式 101/102,不声称任何业务 route 已在线上验证,也不迁 Survey/排行榜/首场景身份。 运输可用与某个业务接口在当前线上存在是两个验收结论。

2. 路线比较与选择

路线 收益 问题 裁决建议
A. 去掉 kvOnly,给旧 client 填登录 Cookie 改动少 租约与第二 HttpClient 分离,退出排水/epoch/handler 所有权无法沿用;Apply 中可过早发送 不采用
B. 扩展既有账号租约的正式模式,由普通包装方法转发 同一次认证与 Cookie、已有关闭屏障及会话版本;无第二登录 需区分正式/验证路由、运输就绪与公开授权,并补退场/401 竞态测试 推荐
C. 为业务另建第四 transport/租约 职责可分 新 handler 所有权、Cookie/Close/版本并发面和基线回归增加;当前无必要 暂不采用

3. 合同与时序

  1. PlayerKVControlledLoadCapability 已有 formal/validation 不可变模式。在现有 PlayerKVAccountLease 内据此区分路由:验证模式保持原精确两路由不变;正式模式接受 GET/POST 的规范相对业务路径,拒绝空、绝对/跨源 URL、以 / 或 \\ 开头、//、?、#、% 编码、控制字符、./.. 段及反斜线。正式模式也拒绝 __kv_validation/*、account/Login 和 playerdata/*,避免重认证、绕过专用 KV 传输。路由大小写保持客户端原值,不自动改名。不能以“只列 Mail/Friend”再造一个临时全局禁用门;所有合规普通路由走相同运输合同,业务语义另按批审。
  2. CustomServerMgr.BindKVForGame 仍在 Apply 前绑定并废弃旧空闲 PF transport,但将正式普通请求标记为未就绪。只在 LoginKVFormalAsync 核同 epoch 的 GameLoaded、CP3A 三原实例绑定成功、原 handle 仍当前后,由 UserService.KVLoad 一次调用内部 EnableKVBusiness(epoch);管理器只核自身 formal 租约、固定 API、相同 epoch、尚未关闭及单次发布,不反向依赖 UserService/Coordinator。验证实例从未启用。PFLoginAct 仍停在登录页,现阶段不会自动发业务请求。
  3. CustomServerMgr.SendAsync 在 KV 就绪时捕获原 lease 与 SessionVersion,通过其 SendAsync 发请求;HTTP 200 且响应仍属同租约/版本/epoch 才返回正文。旧响应、取消、退出与会话替换返回空,不更新业务状态。401/403 用当前版本专用 KV 未授权事件使 PlayFabUserService 先同步撤销就绪与公开身份/原 handle,再交 Coordinator 关闭;不走 PF 自动重登。其他状态/超时保留现有空结果和受控错误日志,不把响应体、Cookie 或存档写入日志。CustomServerMgr.UseAccountSession 在 KV 模式继续拒绝第二次认证。
  4. LogoutFormalKV、Quit、加载/绑定失败与 ClearKVForGame 在任何 await 前同步禁用普通请求、递增 SessionVersion 并触发 SessionChanged,随后租约排水关闭;旧回包不能发布未授权或覆盖新身份。PlayerKVAccountLease.CloseAsync 仍负责活动请求取消/排水;失败保留关闭屏障。PF 分支的 transport 与事件语义不变。
  5. ICustomServerMgr.Cookie 是现有 RTService.Connect() 的会话输入。正式 KV 运输就绪且租约仍当前时可返回同一账号 CookieContainer;未就绪/已撤销仍拒绝。SessionChanged 与 RTService 已有 SessionVersion 检查必须使旧 SignalR 连接失效。本批不声称 SignalR 真实连接完成,G5 另验;但不能留下“普通 HTTP 已开而现有 Cookie 永远抛异常”的隐藏冻结。

4. 精确实施边界

生产文件 允许的修改
Client/Assets/Scripts/Services/PlayerData/PlayerKVLoginContext.cs 在既有 capability/租约中区分正式与验证模式、规范路由检查、仅向当前就绪租约交接原 CookieContainer 引用;不改变登录、KV cache/owner、验证两路由、Close 先后
Client/Assets/Scripts/Core/CustomServerMgr.cs KV 普通请求在明确就绪后转发同一租约;同步禁用、版本和 Cookie/401 处理;PF 旧分支不改
Client/Assets/Scripts/Services/UserService.KVLoad.cs CP3A 成功交接后一次启用、KV 未授权与 Logout/失败先失效再关闭;不公开旧 UserId 或跳场景

测试仅可增改 CodexOutput/upserver/KVGameLoadTests 与固定 Unity CLI Loop Editor 验证入口中实际必要的合成用例;不得顺手改 LoginStage、FishingStage、PFLoginAct、UserService.cs、KVMgr/Guard/Owner/Coordinator、Schema、场景/Prefab、服务端或配置。若实施证明白名单不够,先补审精确增量,不以测试绿灯倒推代码许可。

5. 验收与批末复核

合成 handler 必须证明:一次账号认证、三 handler 同 Cookie 且不同实例;正式就绪前普通 GET/POST 零发送,就绪后 mail/fetch、friend/GetInvitedListCount、club/GetSelfClub 等仅作为路径/正文示例由原租约发送且保持 JSON/Content-Type;验证租约仍只认两个验证路由。异常/绝对/编码路径、专用认证及 KV 路由零发送。200/非200、401/403、取消、退出中的旧响应、同账号新 epoch、账号切换、Close 失败逐项验证无 PF 回退、无旧结果/身份污染;Cookie 与 SessionVersion 只在当前就绪租约有效。再跑既有 CP2A/CP3A/B01/B02 回归和 Unity CLI Loop Editor 编译,记录正式请求 0;真实 Player 编译仍按工具限制标未验。批末封存 hash、一次独立复核和主会话裁决,每检查点更新日志。

FishingStage 仍保持 LoginStage 阶段闸,直到 Mail/Survey/排行榜/Friend/AntiCheat/活动、公开身份/授权和真正线上响应合同另批完成,并按最终门控清单销账。固定正式地址 http://s101.local:18080/;仅 Unity CLI Loop,不用 UnitySkills,暂不打包。