# M2 CP2A 独立方案审查主会话裁决与实施边界 日期:2026-09-29。受审件:[CP2A完整方案](M2-CP2A正式登录与原句柄交接完整方案-待独立审查.md)、[37项基线](M2-CP2A受审基线.json);报告:[原ZCode独立审查](M2-CP2A独立方案审查.md)。报告 SHA256:`47C412B6F8F29BB09979A5C95EAE31CFBA57DE0810C8FC4BAC6D9ACB9F36D521`。主会话重算受审长度及 SHA256 **37/37 一致**,清单自身 SHA256 `B36C685EB9E9571DEFA383395EAD61CB86143CB9762FAE4FF208CF49F44A411A`。报告未改受审方案/源码。按源码核对后,接受“CP2A可独立实施”的总裁决,批准下述**收窄后的**白名单;不等于批准CP2B首场景或M2整体上线。 ## 六项逐条裁决 1. **启动分流:接受**。`Boostrap.AfterAssetUpdateV2` 已持有 config,`SubBoostrap.RegisterServices` 现在无条件创建 PF 组件;捕获必须在创建前,KV 不创建 PF 组件,PF 默认顺序保持。Editor loop 在该方法后段写 `kv-loop`,正式捕获不能误拒已有许可路径;AGG 的 `kv` 在启动处显式失败。禁止运行中变更已捕获模式。 2. **账号与三传输:接受并限定**。请求前仅允许规范 101/102,响应再次核同 ID、`newCreate=false`、非空且31模块 Schema Valid;任何失败不自动建档/写入/回退。正式三 handler 各自拥有并共享单 CookieContainer,真实网络工厂与 Editor 验证工厂隔离,API 严格等于 `http://s101.local:18080/`。`Application.persistentDataPath` 为 CacheRoot,现有 `PlayerKVCacheIdentity` 已追加 API 指纹和玩家 ID,不再手工重复拼路径。 3. **正式实例与 CP1 接口:接受**。正式普通 UserService 准入与 `kvControlledInstance` 验证准入互斥。`LoadForGameAsync`、Coordinator 内 `TryAcquireGameHandle`、UserService 的 `TryGetCurrentGameHandle(epoch)` 均在 CP2A 消费;不得复制加载主体、另造 Owner 或全局当前 handle。Apply 前与成功后复核无旧 PF、未发布身份、同一 epoch;第31模块仅在正式加载窗口重置/替换。 4. **内部状态与双重闸:接受**。`KVHandoffReady` 是内部检查点,公开 `IsLogin`/`IsAuthorized` 和 `EvtAPISvrLoginSuccess` 留 CP2B;`PFLoginAct` 不注册待 API 登录的 RT 订阅、不初始化 Mail/IAP、不 Unload,`LoginStage.RequestNextAct` 再阻断跳场景。PF 旧路径不改;KV 失败不进原无限重试对话。`PFLoginAct.OnDestroy` 的 linked token **不等于** UserService 的 LoginLifetime,因此不能仅靠它保证 Coordinator 撤销;正式分支须在同文件销毁路径显式 Logout,且在 UserService 注册 `Application.quitting` 同步撤销兜底,二者幂等。无需新 MonoBehaviour 生命周期文件。 5. **正式租约:接受**。CP2A 只绑定同一 Context 的正式 lease,业务路由集合为空;旧 `CustomServerPost` 在 KV 模式仍拒绝,验证两路由原义不变。关闭先清内部 ready/handle,再 Revoke 与 Registry 排水;GameLoaded 后 Close 故障不得当作资源释放。由于 CP2A 不发业务请求,401/403 的正式业务分发在 CP2B 路由启用时评审,不为了合成测试开放正式路由。 6. **白名单与验收:接受并纠正计数**。报告称“12项”,而受审方案表按单个生产文件列有**12个既有/必需文件+1个条件新生命周期文件**,总上限13。主会话依据 P3-4 **不批准新增 `PlayerKVRuntimeLifetime.cs`**,改用既有 `PFLoginAct` 销毁路径和 UserService `Application.quitting`;本次批准的生产文件上限为下列 **12项**。测试宿主可在独立测试目录新增/调整,须命中真实生产源码,不使用正式账号作单测。Editor 和 Player 目标都要求0错误;历史 `_cheatingScore` 不得冒充通过或顺手越界修复。 ## P3逐条处理 | 项 | 裁决 | 实施限定 | |---|---|---| | P3-1 101/102注释 | 接受 | 在准入常量处注明本批受审范围,扩员需完整方案审查;不引入可运行时放宽的配置。 | | P3-2 版本令牌含创建时间/配置hash | **不采纳建议形式** | `PlayerKVSchemaSnapshot.Version` 当前只与本次传入的 `expectedVersion` 对比,且保存于 `PlayerKVDecodedSave.ConfigurationVersion`;创建时间会使重跑不稳定,配置hash前缀没有可验证的服务端协议含义。正式路径用固定、非空的本地 decoder 版本令牌(例如 `formal-v1`)并捕获当前真实 `cfg.Tables`;不宣称服务端 Schema 协议版本。若需配置指纹另起合同审查。 | | P3-3 KV错误码到UI | 限定接受 | 复用已有 `PlayerKVGameLoadError`/`KVLastError` 映射为可区分的失败呈现和诊断;不新增错误体系、不显示 Cookie/内部 handle。 | | P3-4 可复用生命周期 | 接受并收窄 | 不新增 RuntimeLifetime 文件;在已批准 `UserService` 和 `PFLoginAct` 中做退出/销毁撤销,合成测试验证一次、重复、Close失败与新 Context 阻断。如 Unity 生命周期验证证明二者无法保证,先补审,不直接扩白名单。 | ## 获批生产文件白名单(12项上限) 1. `Client/Assets/Scripts/AOTScripts/Boostrap.cs`:传递已加载 config。 2. `Client/Assets/Scripts/SubBoostrap.cs`:捕获模式、PF/KV 组件分流。 3. 新 `Client/Assets/Scripts/Services/PlayerData/PlayerKVRuntimeSelection.cs` 及必要 `.meta`:不可变模式、地址和101/102准入;不持有 Cookie/handle。 4. `Client/Assets/Scripts/Services/PlayerData/PlayerKVControlledLoadCapability.cs`:正式三传输工厂,与验证工厂隔离。 5. `Client/Assets/Scripts/Services/PlayerData/PlayerKVLoginContext.cs`:仅为正式现存档/身份检查所必需的最小受限入口;若无需改即保持原样。 6. `Client/Assets/Scripts/Services/PlayerData/PlayerKVGameLoadCoordinator.cs`:仅正式既有档门与原对象交接所需的最小变化;CP1/验证旧合同不变。 7. `Client/Assets/Scripts/Services/PlayerData/PlayerKVGameplayBindings.cs`:同一31模块绑定进入Player目标,Editor loop默认版本不变。 8. `Client/Assets/Scripts/Stages/LoginStage.cs`:缺少的实际注册及阶段双闸。 9. `Client/Assets/Scripts/Services/UserService.cs`:正式模式分流、内部ready/Logout/退出撤销,PF分支不变。 10. `Client/Assets/Scripts/Services/UserService.KVLoad.cs`:正式加载配置与既有验证分支隔离。 11. `Client/Assets/Scripts/Stages/PFLoginAct.cs`:KV登录停止点、失败呈现、销毁撤销;PF分支不变。 12. `Client/Assets/Scripts/Core/CustomServerMgr.cs`:正式空路由租约绑定/关闭,不开放业务API。 `PlayFabMgr.cs`、`KVMgr.cs` 四入口、Guard方法体、`AggUserService.cs`、`FishingStage`、Survey/Leaderboard、Editor permit/loop、正式账号配置/数据均不在本批。白名单外确需修改时停止编码,补方案与独立审查。CP2A 仅可在合成环境实施与验证;不自动真实访问 101/102。每检查点更新日志,保留原工作树;批末交原 ZCode 独立实施复核并由主会话核交付hash后才能限定关闭。最终 CP4/CP5 必须清闲置实现和旧Mgr运行调用,不打包。