文件
hyb-oa/.trellis/tasks/archive/2026-10/09-07-e2e-auth-preconditions/design.md
T
wangsli和Claude Opus 5.5 314274b5a9 归档登录前置条件任务:已完成范围收口,后续阶段取消(09-07-e2e-auth-preconditions)
- 已完成:立项与认证状态合同、阶段 0 取证(用户独立复核批准,AC1)、在线对照
- 阶段 1 迁移、回归、矩阵验证与独立复核未获批未执行,按取消记录,AC2–AC6 不补勾
- 环境启动合同与登录后线上冒烟由发布门禁任务跟进

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 10:47:32 +08:00

26 KiB
原始文件 Blame 文件历史

E2E 认证前置统一 — 阶段化设计

2026-09-07 最新状态:阶段 0 与在线对照均已获用户复核认可;原 31+2 迁移继续暂缓。环境实现合同唯一入口为 .trellis/tasks/09-06-release-gate-integrity/design.md §10(待审),本任务保留取证,不平行维护另一套 runner 方案。207 浏览器清单已撤销决策资格,原始观测及脚本保留;这不是逐条认定 207 全为假失败,也不代表其他真实红项已查清。

1. 已有 trace:cookie 不是已证明的先因

本轮读取 trace-comparison-20260907-01 的 single 合同只读用例,未重跑浏览器。原件位于 artifacts/qa-flow/release-gate-integrity/trace-comparison-20260907-01/single/report/test-results/ 下的该用例目录;SHA-256 为 4b0f4c51736817f1e7035f553fbd9546a171a650ea88ab3dd9ce61a826027121。

检查 archive 的 21 条 network 记录及 browser trace 的 Route.fulfill 事件。相对首次 goto 起点:

事件 起始偏移 直接观测
GET /login +61.3ms 200;request Cookie header 不存在,cookies 数组没有 has_session=1;该响应未记录设置此标记
POST /api/auth/refresh +1129.3ms 200;request Cookie header 不存在,cookies 数组没有 has_session=1
Route.fulfill,call@28 +1145.3ms 参数 status=200 且 headers 指定 Set-Cookie: has_session=1;调用完成且没有错误
GET /api/me +1376.3ms 200;request Cookie header 和 cookies 数组均有会话标记
  • 全 trace 没有 /api/auth/login 请求,且只有上述一个包含会话标记的 fulfill 调用;payment-reviewer-permissions.spec.ts:194 的合并处理器在 :198 指定该标记。结合时序、调用和源码,首次可见设置动作对应 refresh 合成响应,不是 /login 前已经观察到的 cookie。
  • network 序列本身没有保留此 Set-Cookie header。必须写成“Route.fulfill 参数里观察到”,不能伪装成从 network response header 直接读到;请求开始时间也不等于响应完成时间。
  • 请求及处理器参数不是任意 JS cookie 写入的完整审计。本证据反驳“refresh 必然证明事先已有 cookie”的推导,不声称排除全部未记录写入。
  • AuthContext.tsx:365 在离线且有可用快照时走离线快照;:370 在无会话提示且在线时直接未认证。离线且无可用快照时,即使没有会话标记,也可能继续 refresh。
  • 旧 trace 未捕获 navigator.onLine、离线快照可用性或 JS 调用栈,不把“可能离线”定为根因,也不将未来观测追认成旧现场值。

2. 认证夹具状态模型

起点/事件 refresh 场景行为
guest,未显式登录 未认证 可驱动表单,不预先返回身份
guest → 登录成功 authenticated 登录及 /me 成功,后续刷新可恢复
authenticated 显式起点 成功恢复 直接进入业务入口,不再填表单
authenticated → 注销 guest 后续 refresh 未认证,旧身份不复活

参照 local-candidate-witnesses.spec.ts:199 的初始 false、:241 的登录、:252 的 refresh 判断和 :260 的注销。其状态合同正确不等于该文件的原失败通过,也不构成默认重写授权。

login-portal-ux 混合访客、Portal 登录及 bootstrap 恢复场景;mobile-approvals-offline 前两条使用本地真实 API,第三条才安装合成 mock。迁移以场景调用图为单位,不全文替换。

可采用共享有状态 helper,具体接口和写入范围在阶段 0 后交审。不得修改 AuthContext、覆盖 navigator.onLine、删除 full navigation 或不再检查 /me 以规避矛盾;PWA/offline 场景保留专用网络语义,不无差别关闭 Service Worker。

3. 阶段 0:本地取证与静态盘点(2026-09-07 已独立复核批准)

  1. 冻结候选、获准 21 文件摘要、24 文件清单及工具/构建条件。使用现有独占临时库、无外网本地合成通道,不接生产或 live。
  2. 优先复用可核验的现有构建和 runner;先检查源码绑定及资源归属。前提已清理或无法核实时按现有隔离流程重建,不冒称旧构建属于当前候选。
  3. 只预定一条代表性合同用例,1 worker、零重试、trace=on,原超时和业务断言不变。观察首次 bootstrap 周边的会话标记、navigator.onLine、离线快照可用性及 refresh 调用入口;不同时再启全套或追加重试。
  4. 仅输出布尔值、函数名、相对时序、路径/状态及摘要,不输出身份、credential 或存储内容。如需观测注入,只能在独占实验副本中添加观测,不改真实工作树、状态判定或 mock 返回;记录副本差异,不冒充未修改候选的普通门禁。
  5. 若一次观测仍不能区分入口或条件,保留未知并报告最小后续实验,不追加运行。首次问题取得证据后,再追踪非 manual spec 的 helper、TEST_IDS 和 route 注册,产出场景清单及拟写入清单。
  6. 此阶段不要求整条用例绿:认证前置仍失败如实报告;若越过前置而停在旧“更多”,也只报告该进展。原 trace、截图、日志和派生索引分列,清理失败不倒写为自动通过。

本阶段不修改真实工作树中的业务或测试源文件,不开展文件外 80 条的独立修复,不实现门禁。静态新发现仅是候选,不构成写入授权。

3.1 本轮观测结果与边界

证据目录为 artifacts/qa-flow/e2e-auth-preconditions/phase0-20260907-03/。source-before.json 绑定 HEAD=66f25b1、dirty 源码摘要及获准 21 文件;不是仅用 commit 冒充带工作树差异的候选。来源快照共 1052 文件(client 436、server 522、scripts 79、Trellis 15),收尾逐项核对未变。构建在独占临时副本中完成,未覆盖 client/dist;观测副本的差异单独保留。

首次入口 sessionHint navigator.onLine 可用离线快照
mount-effect false false 此调用未读取
bootstrap-entry false false false
bootstrap-primary-refresh false false false
runRefresh-entry false false 此调用未读取

网络依次为 GET /login 200(请求无会话标记)、POST /api/auth/refresh 200(请求无标记)、GET /api/me 200(请求有标记);全程没有 /api/auth/login 请求。这证明本轮是“无提示 + 离线 + 无快照”没有命中 AuthContext.tsx:365/:370 的两个早退条件,进入 bootstrap 主 refresh 分支,再被成功 mock 恢复身份。不是登录前已观察到 cookie,不是业务断言通过。

  • 观测只添加一个日志 helper 和 11 个调用;去除这些节点后 AST 与原 AuthContext 完全一致,回执位于 phase0-20260907-01/observation-ast-check.json。未改条件、返回值、mock 或原测试源码。
  • 后续还有第二组 mount/bootstrap 日志,但实际网络 refresh 只有一次;不把函数日志重复当成网络重试,也不无证据归因 StrictMode。
  • 本轮只在 loopback/无外网隔离环境实际观测到 online=false。未做网络环境的单变量对照,不宣称 unshare 必然导致该值;旧 trace 的 online 值仍未观测,不能倒填。修复目标仍是夹具状态合同,不是强行将 navigator.onLine 改成 true。
  • 唯一实际执行的原用例为 payment-reviewer-permissions.spec.ts:380,选择标题“合同只读人员看不到新增编辑续约和归档动作”,workers=1、trace=on、retries=0。原始结果 1 timedOut / retry 0 / 216617ms;错误仍指向 login-identifier 的 locator.fill,续约/归档断言没有到达。
  • 原始 Playwright JSON、trace.zip、observation-result.json 及静态清单分别保留和哈希;trace SHA-256 为 fc1bb04629f8dcba772959db1534ec1a24ffa2dee7a67c9def97275428150f00。观测副本回执固定无发布资格,harness exit 2 不表示测试通过。

两次准备错误不能隐去,也不能算作浏览器重试:phase0-20260907-01 缺 QA_DIAGNOSTIC_PWA_ROOT,在启动 Playwright 前退出;phase0-20260907-02 的锚定 grep 未匹配 qualified title,收集 0 条并报 No tests found。两者实际浏览器用例均 0,原错误及分类保留。03 改用已验证的无锚点标题选择器,先 --list 确认恰好 1 条,再执行唯一一次浏览器用例。未重试任何业务断言。

资源按各次 private 归属记录定点核验:3 个独占容器和 3 个临时副本目录均已不存在,未遍历或操作生产容器。01/03 有独立的剩余库计数 0;02 只有原阶段 cleanupExit=0,没有单独计数文件,不补造数字。最终来源/资源回执为 closeout-receipt-v2.json;首版校验错误地要求每次都有计数文件而返回 false,原件保留,修正版明确区分证据类型。

3.2 静态分母与历史迁移清单(暂缓,不是缺陷数)

下表及 static-census.json 保留阶段 0 的静态标签和提案来源。在线对照已证明代表性用例在原生在线时无需改变 mock 即可完成登录与会话恢复,因此“成功 refresh 与表单共存”本身不足以认定内在矛盾。执行端撤回默认迁移 31 文件的建议;原件不覆盖,最新结论以 §6.1 为准。

static-census.json 从文件系统枚举当前 65 个非 manual spec,追踪静态 import/export、局部函数、场景/钩子调用、route 和 TEST_IDS;33 个 spec 直接出现 refresh 路由。依赖闭包记录 42 个非 spec 模块,本地 import 无未解析项,未发现动态 import/require,依赖模块内未发现 refresh 路由或间接 route 注册。函数调用索引只是审阅导航,不是任意 JavaScript 数据流的完备证明;条件分支、动态拼接和将来新增文件仍需审查,不把“未命中”写成运行通过。

分类 文件数 本次提案
成功 refresh 与驱动登录表单存在同场景矛盾 30(原 23 + 新 7) 仅迁移矛盾合成路径,保留原表单及业务断言
成功 refresh 与访客提示页存在矛盾 1 单列 wecom-first-bind,不并入“30 个填表单”口径
状态合同正确 / 显式已认证起点 2 local-candidate-witnesses、PWA 不迁移
恢复建模缺项,非相同成功身份恢复 2 user-onboarding、visual-portal 延后核对,不列入拟写入清单
仅业务 mock / 访客供应商入口 mock 2 leave-team-calendar、wecom-entry 不迁移
spec 及静态依赖没有 route 注册 28 保留原本后端、live 入口或纯源码断言,不宣称正常或授权运行 live

以下路径均位于 client/tests/e2e/。表中列出需改的认证处理器与表单入口坐标;完整场景/钩子、函数调用及依赖锚点见 static-census.json。默认方案是保持现有登录 helper,guest 起步,成功登录后才允许 refresh 和 /me 恢复该场景身份,不批量改成默认管理员或直接跳过登录。行号以当前源码摘要为准。

spec refresh 处理器行 入口/场景锚点 来源及局部边界
biz8-ap-ledger-project.spec.ts 105 202/208/217 原 23;仅合成认证路径
contract-detail-workspace.spec.ts 123 232/234/246 原 23;不改详情业务断言
dg7-mobile-information-dedupe.spec.ts 501 753/760/898 原 23;保留按场景角色
internal-readiness-ui.spec.ts 163 297/301/318 原 23
login-portal-ux.spec.ts 81 mockPasswordLogin:33 / Portal:554 / prepareEmployeePortal:628 原 23 的混合文件;仅该 helper 的表单调用链
mobile-approvals-offline.spec.ts 291 第三场景:184 / 表单:322 原 23;不动前两条真实 API 场景及离线语义
payment-reviewer-permissions.spec.ts 194 341/343/384 原 23;旧“更多”及续约/归档仍归门禁阶段 B
pc-core-workflow-visual-wave2.spec.ts 148 306/315/307 原 23
pc-detail-mobile-visual-wave3.spec.ts 679 1217/1219/1233 原 23
pc-finance-admin-visual-wave4.spec.ts 489 1001/1004/1041 原 23
r100-design-baseline.spec.ts 66 188/190/252 原 23
r101-mobile-wip-closeout.spec.ts 134 319/321/368 原 23
r102-reimbursement-main-flow.spec.ts 148 346/348/357 原 23;不改“编辑”相关业务断言
r103-cross-page-ui-consistency.spec.ts 318 609/611/688 原 23
r111-invoice-reimbursement-guard.spec.ts 310 681/687/799 原 23
r124-mobile-entry-matrix.spec.ts 168 425/432/492 原 23
r125-invoice-reupload-after-delete.spec.ts 190 355/361/383 原 23
r5-real-device-feedback-mobile-ux.spec.ts 75 243/249/365 原 23
r6-mobile-responsive-system-hotfix.spec.ts 90 415/421/534 原 23
r6-mobile-unified-design-rollout.spec.ts 143 492/498/623 原 23
r6-wecom-mobile-rendering-hardening.spec.ts 101 363/375/523 原 23
r89-mobile-login-navigation.spec.ts 223 438/440/471 原 23;保留真实登录导航意图
visual-shell.spec.ts 87 340/343/365 原 23
announcements-policy-ack.spec.ts 148(fulfillJson:29 默认 200) 282/293/303 → helpers/auth.ts:96 新 7;保留登录后 currentUser 切换
global-search.spec.ts 46/48 180/208/228/248 → helpers/auth.ts:96 新 7
leave-flow.spec.ts 132(fulfillJson:16 默认 200) 302/317 → helpers/auth.ts:96 新 7;保留 activeUser 选择及注销
r92-mobile-invoice-usability.spec.ts 53(fulfillJson:10 默认 200) 286(TEST_IDS)/300/319/345 新 7;间接 testid 命中
system-action-confirmation.spec.ts 338/340 615 起 → helpers/auth.ts:96 新 7
workflow-action-confirm-ui.spec.ts 150/152 301 起 → helpers/auth.ts:96 新 7
workflow-quick-approve.spec.ts 97/99 218 → helpers/auth.ts:96 新 7
wecom-first-bind.spec.ts 60/62,me:74 180/181 新增访客提示路径,不填表单;固定 guest

wecom-first-bind 的成功 refresh 和 /me 会满足 GuestOnly(client/src/router/guards.tsx:48)的重定向条件;/login 的 wrapper(client/src/router/index.tsx:103)没有 wecom query 例外。它与待看见的 login-wecom-notice 有静态前置矛盾,但本轮没有用新运行给其旧失败定因。

保留与延后项具体合同:

  • login-portal-ux 的 mockGuestAuthChrome 访客场景、邮件验证码及找回密码场景保留;:776 的显式会话提示 + refresh 首次 500 后 200 + 直接 /portal 是产品 bootstrap 恢复回归,不替换成永久 401,也不把产品内部恢复重试等同于 Playwright retry。只迁移 mockPasswordLogin 所服务的表单路径。
  • mobile-approvals-offline 只处理第三场景内的合成认证;PWA 的 :509 显式 addCookies 和 :516 直接 /portal 属于合法已认证起点,不迁移,不改 Service Worker 或专用输入供给。
  • user-onboarding 只 mock login 和 /me,未 mock refresh,不能计入无条件成功 refresh;visual-portal 的全 API fallback 在 :185 返回 200/空 data,不含恢复身份的 accessToken,也不能并入同一类。两者只是静态可见的恢复建模缺项,另列待核对,不借本次范围顺手修复。
  • 28 个无 route 文件逐个登记 import、helper、TEST_IDS 及场景/钩子。business-detail-routing、interaction-pattern-unification、management-navigation-contract、reimbursement-content-consistency 是不依赖浏览器登录的源码/纯函数断言;其余保留现有真实后端或受环境开关控制的入口,未授权开启 live。
  • 原 23 文件的 133 条观测(127 失败、6 通过)及文件外 80 条保持历史口径。新 7/访客提示/延后项没有从 80 中扣除,也没有把 207 转成已归因的产品缺陷数。

4. 后续批准边界

  • 阶段 1:阶段 0 结论、精确清单及 helper 接口单独获批后,先补状态合同回归,再实施最小迁移;保留正常访客、恢复会话和真实 API 样本。
  • 阶段 2:按届时批准的固定矩阵验证,零重试和默认全套并发不变;定向认证前置与整套诊断结果分列。全套需完整前提、资源归属和独立回执;中断不补造状态、不自动重跑。
  • 认证前置解释清楚后,文件外 80 条和新增红项再单列同类候选、独立问题、前置阻断或证据不足。仅再获批清单可写,不承诺清空所有失败。
  • 本任务负责认证前置;release-gate-integrity 阶段 B 仍负责合同详情入口和续约/归档断言。机制推进遵循原任务批准范围,本轮不启动其他阶段 A 内容。

4.1 阶段 1 原接口与写入提案(已暂缓,非推荐默认路径)

拟新增 client/tests/e2e/helpers/syntheticAuth.ts 和 client/tests/e2e/synthetic-auth-contract.spec.ts;连同 §3.2 的 31 个现有 spec,共 33 个代码/测试文件。仅当前任务的 PRD/设计/执行记录随结果更新;不改已有门禁 21 文件、产品源码、helpers/auth.ts、配置、依赖或发布入口。新增合同 spec 放在非 manual 集合内,不借新增测试缩减原 65 文件分母。

helper 采用每次安装独立的闭包状态,不用模块级可变会话或共享 storageState:

  1. createSyntheticAuthSession({ initialState }) 必须显式指定 guest 或 authenticated。本次 30 个表单矛盾路径使用 guest,wecom-first-bind 的提示场景也保持 guest;已有正确的 authenticated/PWA/恢复场景不迁移。
  2. loginSucceeded() 只在场景原有的登录身份选择和成功判定之后切为 authenticated;logout() 清为 guest。原有角色选择、计数、失败注入和响应数据继续由场景提供,helper 不默认赋角色、不存储或输出凭据。
  3. refresh 与 /me 通过同一闭包的认证检查:guest 返回既有 AUTH_001/401 结构且不种会话提示;authenticated 调用场景提供的成功响应函数。登录成功保留会话提示,注销清除提示,随后 full navigation 可恢复或保持未认证。refresh 不是永久 401。
  4. 接入现有 route 分支;拆开 login/refresh 共用成功分支,不额外注册能被 catch-all 覆盖的竞争处理器。选择性 route 的 login-portal-ux 仍保留原优先级和 :776 自有恢复处理器;不得覆盖该场景。
  5. 新合同 spec 先覆盖状态隔离、登录前拒绝、成功登录后 refresh、失败登录不认证、注销后 refresh 拒绝及显式 authenticated;再按获批矩阵验证真实导航/表单/恢复。沿用现有 Playwright,不新引入单测框架,不修改 navigator.onLine 凑绿。

推荐下一批先批准这份 31+2 清单和接口,再实施;浏览器矩阵另批。针对性建议选新合同 spec、合同权限、间接 shared login、角色切换、login-portal-ux 的访客/Portal/恢复、wecom-first-bind 六类边界,固定每条次数、零重试、trace=on。新合同的纯状态断言不启动浏览器;需要浏览器的观测仍应逐条写清授权。后续全套诊断必须绑定迁移后摘要,默认并发不变,不把局部 PASS 当整套结果。

5. 验收、回滚及风险

  • AC1/AC2 先验收观测与范围,AC3/AC4 后验收获批实施,AC5/AC6 保持剩余问题及发布边界。阶段 0 完成不等于任务完成。
  • 普通 full-local 全绿耗时及稳定性仍未知;旧 197 分钟和中断运行不进入发布成本估算。本任务完成不启用 R1。
  • 回滚仅涉及本任务以后获准的差异,不回退他人或门禁任务已批准改动。提交、push、归档及部署各自授权。
  • 防止把文件内共现误当场景关系,或把恢复会话永久改成 401:使用场景清单、四类状态合同和正确样本,不以重试或弱化断言收口。

6. 已批准的在线对照(2026-09-07,仅实验,不迁移)

  • 用户批准阶段 0,暂缓阶段 1,仅授权一次在线定向实验。复用原合同单条用例和观测构建,在相同隔离、数据、mock、断言及零重试条件下比较认证前置;不运行整个合同文件的其他用例、不启动全套。
  • 网络隔离实际存在于证据目录中的 run-isolated.sh(unshare -Urn)与 run-inner.sh,不在用户列出的受管 runner 内;不能因此推断宿主机本身离线,也不能将外层包装条件漏记。数据库容器继续 network=none,仅使用本轮独占 Unix socket。
  • 唯一拟改变的启动前提:在本轮独占网络命名空间内增加一对 up 的 veth 及文档保留地址,不接宿主网卡、不配默认路由、不开放公网。不修改 navigator.onLine,也不通过 CDP 强制在线来替代原生测量。
  • 业务用例启动前使用空白页读取原生 online,必须为 true,否则停止、不运行用例。同一浏览器的两个独立 context 中,仅对其中一个 setOffline(true),验证另一个仍 online=true;关闭后再创建新 context,验证在线状态及合成 cookie 隔离。此项是无业务请求的前置检查,结束并关闭浏览器后才运行原用例;不能外推为全仓自定义 fixture 已完全排除泄漏。
  • 正式用例固定 payment-reviewer-permissions.spec.ts:380 的原标题,workers=1、retries=0、trace=on;先 --list 确认恰好一条。仍用未改变条件的观测副本,记录实际用例首个 bootstrap 的 online/hint/快照值及 refresh/login 顺序,不只信前置探针。
  • 判据按阶段拆分:在线时是否命中 guest-ready、出现 login 请求并越过登录前置;原整条用例最终结果另列。已知旧“更多”断言仍可能超时,不能把该下游红项判成认证实验失败;同样,一条认证前置通过不能证明其余 30 文件均无需修改。阶段 1 的方向仍由用户按结果决定。
  • 旧 trace 中登录成功不单独证明当时没有 refresh 或 online=true,历史未观测条件继续保留未知。实验原件、候选/构建摘要、外层脚本差异、context 探针及资源清理分别留痕;不修改产品、测试源或旧 21 文件。

6.1 在线对照结果(已获用户复核认可)

证据目录:artifacts/qa-flow/e2e-auth-preconditions/online-20260907-01/。本轮只运行一次原合同用例;prepare.mjs、用例选择、mock、产品判定、断言及观测副本均与阶段 0 相同,1052 份来源文件和 114 份观测构建文件摘要一致。外层差异在 wrapper.diff:仅在独占命名空间内增加 up 的 veth 对及保留地址,并追加在线/context 前置检查和本次授权标签。没有默认路由、宿主外网接口或 navigator 属性改写;原生 online=true 不等于公网可达,也不是一次普通发布绿路径运行。

实际用例首个 bootstrap 阶段 0 离线对照 本轮在线对照
sessionHint false false
navigator.onLine false true
可用离线快照 false false
入口 bootstrap-primary-refresh bootstrap-guest-ready
登录请求前 refresh 数 1,且没有登录请求 0
/api/auth/login 未调用 1 次,200
登录/合同前置 登录表单等待超时 通过,到达旧“更多”
整条结果 timedOut / retry 0 timedOut / retry 0

本轮实际网络顺序为 GET /login → POST /api/auth/login → GET /api/me → GET /contracts-registry → POST /api/auth/refresh → GET /api/me。首个文档及 login 请求不带会话标记;标记出现在登录后。第二次完整文档导航才通过 refresh 恢复身份,这正是该 mock 在在线条件下被真实使用的会话恢复路径,不是应当永久禁止的请求。

trace 中 sourceLine 387/388/389/390/396 的断言均完成且无错误:合同 URL、标题、新增/编辑不可见及合同行可见;:397 的“更多”点击超时。整条原始结果为 1 timedOut / retry 0 / 214570ms,commandExit=1,harness exit=2 / PARTIAL,无发布资格。续约、归档仍未到达,不计入权限验收通过,也不在本轮修改。

原生 online 与 context 隔离前置结果:两个新 context 初始均 true;第一个 setOffline(true) 后该 context 为 false,第二个仍 true;关闭后新 context 仍 true,合成探针 cookie 没有泄漏。检查只使用空白页,不执行额外业务用例。network-preflight.json 的 externalRequests=0 是探针未主动发起外部导航的声明,不是浏览器后台请求的仪表计数;无外网边界由独立命名空间及无外连路由维持。不能据此宣称全套所有自定义 fixture 已排除状态复用。

原始全套诊断的隔离也有明确出处:artifacts/qa-flow/release-gate-integrity/diagnostic-run-20260906-01/run-isolated.sh:43 调 unshare -Urn,:45 只启 loopback。它处于受管 runner 外层;仅搜索 full-local-diagnostic/run-web-gates 看不到这层包装,并不能归因宿主机网络常态。本轮不观测宿主真实网络,也不倒填该旧运行的 navigator 值。

结论与下一项:

  • 对这条代表性合同用例,改变原生在线启动条件即可越过认证前置,无需改它的认证 mock;这足以否定“必须先批量迁移 31 文件才能恢复它”的判断。
  • 一条用例不能证明全部 30/31 文件均无需修改,也不能凭完整用例仍红就判迁移必要。127/207/80 的旧统计保持不变,没有重新分配或扣减。
  • 原 31+2 方案暂缓,不再作为默认建议。下一项建议先定环境启动合同:普通在线验收在实际 context 入口验证 online;有意置离线的场景必须保留自己的语义。此处只提后续方向,尚未实现、未授予门禁或外层环境修改权限。
  • 长期规则暂存当前任务,不修改受冻结的模块 spec 或门禁 21 文件;待修复对象与范围获批后再将可复现的执行合同沉淀到对应规约。

closeout-receipt.json 已核对:原 21 文件及 1052 来源文件未变、114 构建文件相同,启动后实验脚本摘要未变;原 cleanupExit=0、剩余独占库计数 0,本轮容器和临时副本按归属定点确认不存在。原始 trace SHA-256:069f15ae266f052898ed41853a56e135ce1e2cc5b1149dc956244694a431ab96。无提交、push、归档、部署或生产操作,场景 8、经理缺口和 R1 继续挂起。