# 阶段4B1限定代码自审 日期:2026-09-23。性质:实现主会话的限定自审,**不是外部独立实施复核**。范围为两个新增生产文件及KVLoginContextTests;实施依据《阶段4B1方案裁决与实施批准-2026-09-23.md》。 ## 本轮结论 已完成合同/并发/资源/错误/输出检查及必要补测,未发现剩余已确认P1/P2。最终23组合成用例通过,68项既有源码/项目文件hash未变,Unity编译成功。4B1仍待外部独立实施复核,不在此关闭阶段。 ## 逐项检查 | 检查点 | 结果及证据 | |---|---| | 单次准备与发布 | PrepareAsync在gate内发布唯一TCS和首token,锁外启动准备;重复调用相同任务,不换session;不同token固定Debug提示及internal计数。P3-C和B1-06通过。 | | Close-before-Prepare及并发 | Close在返回Task前撤销;从未Prepare时完成workSettled;后来首次Prepare等待已有Close并返回Cancelled。24轮多任务竞争验证两组任务引用各自一致,最多一次登录。 | | 不互等 | PrepareCore finally先完成workSettled,再等待统一Close;Close只等workSettled和Bridge,不等公开Prepare任务。认证/Get忽略取消、失败与Close同时发生均通过闸门测试。 | | 取消回调重入 | Close核心排到Task.Run,避免取消登记直接执行自身Dispose或用户回调;Close任务被保存并观察fault,等待方仍得到原fault。真实context lifetime回调重入与抛异常测试通过。 | | session所有权 | session/bridge/handle私有,无外部写端口;Bridge Close成功后才Dispose session。Bridge失败时保存引用和Close任务,session不提前Dispose;失败构造和session.Dispose异常均有反例。 | | 归属与快照 | 读通过4A句柄,读后和最终发布前复查外部epoch,发布时复查撤销标志;IsCurrent还检查认证/玩家/Cookie引用。结果深拷贝不可变,关闭后历史Prepared结果仍可读而IsCurrent=false。 | | 归属委托异常 | 自审发现Prepared后委托异常需主动清理,已按原方案§4.5补齐:记录异常类型并启动共享Close,永久撤销,不因委托恢复而复活。初始/读取中/Prepared后三条异常路径通过。 | | 错误证据 | 失败Data=null;错误字段可空,未发生阶段不假报None。初始Owner失败没有可读状态时SyncStatus保留null;非Ready句柄保留实际Conflict/Unknown/StorageError。CloseFailed与OriginalError、CleanupExceptionType同时保留。 | | 空档语义 | 成功空Get返回Prepared+IsEmpty;newCreate两态均零变更请求。没有游戏schema验证或默认初始化代码,成功不等于可玩。 | | 不变语义 | Close无Flush、Unknown不重试,pending只读合并。无PF/PlayerPrefs/GContext/Unity/业务初始化依赖;无UserService/PlayFabMgr接线。 | | 传输与输出 | 公开构造固定s101,默认实例仅构造并Close,未Prepare;全部实际请求注入synthetic.invalid Handler并断言路径。结构化结果扫描0敏感命中;原构建/失败日志留本地诊断,不冒充脱敏报告。 | | 构建与范围 | 新测试显式链接12份生产源码,无改旧csproj;KVLiveTests仅build;Unity Success=true、0错误、274其他文件警告、新模块0。68项基线文件当前hash一致。 | ## 本轮发现与处理 1. 首轮21组中的重入测试失败:注册对象是HttpClient完成请求后已解除链接的临时token,而非context生命周期。改为context本身token后通过;原失败run及完整输出保留,未伪称首轮全过。 2. Prepared后外部归属委托异常只返回false的遗漏:在修改前写入实施记录检查点2,按已审§4.5补齐安全关闭,新增用例通过。 3. 脱敏初扫曾以Cookie/Token任意子串命中测试名称;最终按敏感JSON字段名和真实值/路径标记扫描。测试描述中的cookie/token单词不是凭据,不删除测试名掩盖结果。 ## 明确保留的限制 - 外部独立实施复核尚未完成。无Unity PlayMode或真实登录验证,技术编译不代替游戏场景验收。 - 调用方必须先await旧context.Close成功再创建新context;本类不是全局单例调度器,不能阻止调用者故意绕过跨实例屏障。 - 底层忽略取消可导致Prepare/Close长期等待,故障Close永久阻塞该实例;不提供重置、超时强制释放或自动恢复。 - `isCurrent`只允许轻量身份判断;禁止I/O、同步等待和主动触发登录/Close。异常会触发安全清理,但不会让不合规的阻塞委托变成可安全调用。 - Prepared是历史读取结果,必须另外判断当前归属;没有业务档完整性验证、初始化副作用处理、旧玩法内存隔离或实际保存入口。这些仍属于4B2/4B3。 - 4A P3-1(86套件偶发失败)的历史根因未定;本轮86/86不等于该待查项已解决。