Files
ft/CodexOutput/upserver/B3BatchMigration/M2/M2-CP2B-T独立方案审查.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

7.8 KiB
Raw Blame History

M2 CP2B-T独立方案审查:正式KV普通业务请求恢复(含第6–8项补审)

日期:2026-09-29。审查者:ZCode会话(M2全链审查者)。本轮只读+hash重算+源码核对。

受审hash核对

M2-CP2B-T受审基线.json:7/7全部一致。

总裁决

通过。 可批准CP2B-T实施(主会话裁决后)。无P1/P2;P3三条不阻塞。

五问逐答

1. 同一Context租约与运输就绪时序:闭合

  • 正式模式通过PlayerKVAccountLease扩展(区别于验证两路由),复用同一CookieContainer与Close排水——无第二HttpClient、无第二登录;
  • 运输就绪时点正确定义为CP3A三原实例交接后——不是Apply前(BindKVForGame时仍标未就绪),也不是GameLoaded即刻(须等CP3A绑定成功)。这防止了加载期间业务副作用;
  • 路线B正确(A丢所有权/C新增第四传输面)。

2. 路径校验与专用路由保护:充分

  • 规范相对路径校验列表全面(空/绝对/跨源////?/#/%/控制字符/./..);
  • 保留__kv_validation/*、account/Login、playerdata/*拒绝——防绕过验证路由/重认证/绕过专用KV传输;
  • "不能以'只列Mail/Friend'再造临时禁用门"——正确的避免碎片化门控原则;
  • 方案诚实声明"客户端路由字符串不冒充线上响应合同"——运输可用≠线上验证。

3. 401/Logout/旧响应闭合:闭合

  • 401/403→同步撤销就绪+身份+原handle→再交Coordinator关闭——与CP2A/CP3A撤销顺序一致;
  • Logout/Quit→任何await前同步禁用+递增SessionVersion→租约排水——正确时序;
  • 旧响应不发布/不覆盖新身份——同epoch检查;
  • UserService.cs不在白名单能否只靠UserService.KVLoad.cs完成:能——401事件处理/Logout逻辑/EnableKVBusiness调用均可在此文件实现,不需要改UserService.cs的公开签名或构造。

4. 合成独立验收:可行且充分

  • 合成handler可完整验证:就绪前零发送→就绪后正常路径发送→验证租约仍限两路由→路径校验→401/退出/旧epoch→Cookie/SessionVersion;
  • 不能证明的(方案如实声明):线上响应合同、公开身份发布、真实Player编译、SignalR真实连接——均留后续。

5. 白名单/回归/闲置清理:足够

3文件白名单精确到方法/入口。无新增闲置接口——EnableKVBusiness由UserService.KVLoad消费、租 lease扩展由CustomServerMgr消费、Cookie交接由RTService将来消费(G5)。最终清账在CP4/5统一。

P3

  • P3-1:§3.5的Cookie对RTService开放——建议实现时在Cookie返回前加日志("Formal KV Cookie released to RTService")便于G5 SignalR连接调试时追踪;
  • P3-2:§3.1的路由校验建议用一个static readonly HashSet<char>或类似结构表达禁止字符集,防实现时遗漏;
  • P3-3:§5验收用例中建议加"验证租 lease尝试发送普通业务路径被拒绝"的显式断言(方案已隐含,落为独立用例更清晰)。

结论

通过CP2B-T方案。 主会话核hash(已代验7/7)裁决后按3文件白名单实施。这是打通"正式业务API可用"的关键一步——CP2B首场景/身份发布/SignalR留后续。


第6–8项补审(同批追加,与原五项合并裁决)

6. formal/validation模式传递与路径/超时兼容

模式传递安全:PlayerKVControlledLoadCapability已有readonly bool formal字段(:339–340),构造时固定。PlayerKVAccountLease可通过同一capability获取formal标志来区分路由策略:

  • 验证模式→仅两精确路由(原语义不变)
  • 正式模式→规范相对路径,但拒绝__kv_validation/*(防验证入口暴露于正式)+拒绝account/Login+playerdata/*(保持专用传输)
  • 三向隔离闭合

已知合法调用误拒风险:源码核实CustomServerMgr.cs:124使用Timeout = TimeSpan.FromSeconds(15)。方案要求租约保持此超时。当前PlayerKVLoginContext中lease的HttpClient尚未设置显式Timeout——P3级:实施时须为正式模式lease的HttpClient设置15秒超时(与旧CustomServerMgr一致)。超时返回空结果/错误事件,不误判为401。

?查询参数:方案§3.1拒绝?——但现有业务调用如mail/fetch可能含查询参数。P2级:需在实施前核查全部现有CustomServerPost/GetStringAsync调用点的实际路径模板,确认无?形式的合法调用被误拒。如有,最小修订为允许?后的有效字符但拒绝%/#。

结论:模式传递安全;超时需补设置(P3);路径校验需核查?兼容(P2)。

7. GameLoaded后发布运输就绪时的实际调用者

这是"普通请求运输可用"而非"首场景业务可用"——方案已明确。

源码核实(UserService.cs:110):IsLogin => !kvControlledInstance && !IsFormalKV && PlayFabClientAPI.IsClientLoggedIn() && IsAuthorized。正式KV下IsFormalKV=true→IsLogin恒false→ApiPlayerId(依赖IsAuthorized即apiSession!=null)也为null。

实际调用者风险:

  • PFLoginAct停在登录页(CP2A双闸)→不会自动发业务请求
  • FishingStage被LoginStage阻断→Mail/Survey/排行榜/Friend等不可达
  • 但:任何后台协程/事件订阅可能通过CustomServerMgr.CustomServerPost发送请求——CP2A已排除PF组件和旧回调

结论:三文件白名单足够。IsLogin/ApiPlayerId的正确身份发布属CP2B(首场景),本批仅开放运输层。当前无实际调用者会提前发请求——阶段闸保障了这一点。

8. Cookie/SignalR失效与Close双重关闭

RTService消费核实(:69–77):

var session = _serverMgr.SessionVersion;
var cookies = _serverMgr.Cookie;
// ... version/session检查 → new HubConnectionBuilder().WithUrl(..., option => option.Cookies = cookies)

RTService在Connect时读取Cookie和SessionVersion,每次连接前核版本——SessionVersion递增后旧连接的CloseConnection()+新Connect用新Cookie。失效路径成立。

双重Close风险:

  • PlayerKVAccountLease.CloseAsync负责租 lease级排水
  • CustomServerMgr可能也调用清理
  • 方案§3.4已明确"任何await前同步禁用普通请求、递增SessionVersion、触发SessionChanged"——同步禁用先于任何异步操作,不存在双关窗口
  • Close幂等(4A合同已验证)

401回调线程:CustomServerMgr.SendAsync在HttpClient响应后调用事件——回调可能在.NET线程池非主线程执行。LogoutFormalKV的同步撤销部分(禁用businessReady/清handle)不涉及锁内await,可安全从任何线程执行。后续Coordinator关闭(含await)应在主线程或配合同步上下文调度——P3级:建议实施时在401处理中用SynchronizationContext.Post或等效方式调度到主线程。

旧响应撤销新会话:SendAsync返回后核"响应仍属同租约/版本/epoch"——方案§3.3已覆盖。

结论:三文件白名单足够,不需要改RTService.cs或UserService.cs。401回调线程需注意调度(P3)。


更新后总裁决

通过(维持原裁决,附加一项P2和三项P3):

  • P2-1:实施前核查全部现有CustomServerPost/GetStringAsync调用点的路径模板,确认方案§3.1的路径校验(含?拒绝)不误拒已知合法调用。
  • P3-1:正式模式lease的HttpClient须设置15秒超时(与旧CustomServerMgr:124一致)。
  • P3-2:401回调建议调度到主线程后执行撤销。
  • P3-3(原P3-3保留):验证租 lease拒普通路径的独立断言。

原五项结论不变。三文件白名单确认足够。"无线上业务合同也能独立实施运输层、同时阻断FishingStage"成立。