文件
hyb-oa/.trellis/tasks/archive/2026-08/08-10-session-fallback-failure-classification/prd.md
T

9.0 KiB
原始文件 Blame 文件历史

会话回落失败定性

Goal

在与 2026-08-07 历史记录一致的本地 Playwright runner 下,稳定复现并定性 8 条“完整导航或二次返回后落到登录页”的失败,给出可审计结论:测试 fixture/session mock 问题、真实会话行为问题、二者混合,或证据仍不足而保持 PAUSED。任务价值是消除唯一尚不明确且可能影响真实用户登录态的 Residual,不以让 8 条测试变绿作为终点。

Confirmed Facts

  • 父任务 Residual Register(.trellis/tasks/archive/2026-08/08-05-product-interaction-consistency/prd.md:76-81)记录:r103-cross-page-ui-consistency.spec.ts 7 条、global-search.spec.ts 1 条失败,统一症状为多次完整导航或二次返回后落到登录页;现有证据不能排除真实会话续期行为。
  • 历史同 runner 命令为 cd client && npx playwright test tests/e2e/procurement-flow.spec.ts tests/e2e/assets-flow.spec.ts tests/e2e/r103-cross-page-ui-consistency.spec.ts tests/e2e/pc-detail-mobile-visual-wave3.spec.ts tests/e2e/global-search.spec.ts --workers=1 --reporter=list;其中目标两份 spec 当时分别为 4 passed / 7 failed 与 3 passed / 1 failed。
  • 两份目标 spec 都拦截 /api/auth/login、/api/auth/refresh 与 /api/me,因此它们自身不能直接证明真实后端 refresh rotation 正常或异常。
  • AuthContext 在完整页面重建时先检查可读的 has_session=1;无 session hint 时不会请求 refresh,而是按未认证状态完成 bootstrap。真实后端登录和 refresh 会同时写 refresh cookie 与 has_session cookie。
  • 现有前端规约还记录另一条真实会话风险:本地 Vite proxy 若把浏览器 Host 从 127.0.0.1:5173 改写成后端 Host,refresh 的 Origin/Referer 校验会返回 AUTH_005,完整刷新后丢失会话。因此诊断必须同时取证 cookie/hint、refresh 请求与 runner origin/host,不能只看最终 URL。
  • 仓库已有独立证据面:login-portal-ux.spec.ts 覆盖带 session hint 的 bootstrap refresh 重试;auth.login.test.js 覆盖后端 refresh rotation;它们可作为对照,但不能单独替代目标 runner 的复现。

Scope

  • 两份目标 Playwright spec 的原样复现、逐条失败账本和安全诊断 ledger。
  • mock session fixture、真实前端 bootstrap、真实本地后端 session 三个证据面的对照实验。
  • 基于明确判据输出 FIXTURE、PRODUCT、MIXED 或 INCONCLUSIVE/PAUSED 分类。
  • 分类为 FIXTURE 后可选的最小 test-only 修复;任何认证产品改动、生产连接或部署均不在本任务范围。

Requirements

R1 同 runner 稳定复现

  • 先用历史命令的同一目标 spec、--workers=1 --reporter=list 复现;不得先改 fixture、断言、认证实现、Vite proxy 或 runner 配置。
  • 至少执行一次两份目标 spec 的原样组合;若结果不稳定,再对失败标题逐一、重复执行以区分顺序依赖、完整导航依赖和偶发 runner 状态。
  • 记录测试名、阶段、最终 pathname、cookie 名称/是否存在、是否发出 login/refresh/me 请求、响应状态与安全错误码。不得记录 cookie/token 值、密码、完整账号或原始认证 payload。

R2 证据隔离与分类实验

  • 建立三个彼此独立的证据面:
    1. mock fixture 面:目标 spec 的 login 响应后浏览器是否真的持有 has_session,完整导航时是否触发 mock refresh/me;
    2. 真实前端 bootstrap 面:显式存在 session hint 时 AuthContext 是否按设计请求 refresh 并保持路由;
    3. 真实后端 session 面:本地真实登录产生的 cookies、同源 refresh rotation 和完整导航是否成立,且 Vite proxy host/origin 符合规约。
  • 对照实验只允许使用 synthetic fixture 或经 target gate 确认为回环/本地回归库的账号与会话;禁止连接生产或复用生产凭据。
  • 为证明因果,可做最小的 test-side 控制变量(例如显式安装 session hint、记录安全 request ledger);在分类完成前不得修改产品认证代码。临时探针如不形成稳定回归价值,应在结论前移除。

R3 分类判据

  • FIXTURE:原样失败可复现;证据显示 mock 登录未建立 AuthContext 完整导航所需的浏览器 session contract,最小 fixture-only 控制变量消除同一失败;独立真实 bootstrap/backend 对照通过。
  • PRODUCT:使用真实本地 session contract、正确同源 runner 与无 mock 的 refresh/me 路径仍可复现相同会话回落,或真实认证对照出现同一根因。立即停止本任务内修复,登记独立认证缺陷任务;后续实现必须只读 reviewer。
  • MIXED:fixture 合同确有缺口,同时真实 session 对照也失败。分别登记测试债与认证缺陷,不在本任务合并修复。
  • INCONCLUSIVE / PAUSED:无法稳定复现、关键证据面不可用或 target gate 不通过。不得把未复现解释为 PASS,也不得猜测根因。

R4 修复边界

  • 任务终点是分类结论和证据链,不是测试全绿。
  • 若结论为 FIXTURE,可在分类检查点之后选择同任务内提交最小 test-only 修复,但它不是完成 AC 的必要条件;不得改变产品认证实现、弱化会话语义或扩大 mock 的默认放行。
  • 若结论为 PRODUCT 或 MIXED,必须在任何认证代码修改前停止并请求创建独立任务与实施批准。
  • 不得以删除断言作为默认修法。 不得删除目标用例、移除完整导航、跳过 refresh/session 检查、增加 retry 掩盖失败,或把登录页当作可接受结果。

Acceptance Criteria

  • AC1:在历史同 runner 参数下记录两份目标 spec 的原样结果,并能把 8 条历史失败逐条映射为当前 PASS/FAIL/未复现,不用套件总数代替逐条证据。
  • AC2:至少一个可复现失败拥有脱敏 request/cookie/navigation ledger,能回答 session hint 是否存在、refresh/me 是否发出、在哪一步进入 /login。
  • AC3:完成 mock fixture、真实前端 bootstrap、真实本地后端 session 三个证据面的对照;任何未执行项均有明确阻塞原因,不以另一层 PASS 顶替。
  • AC4:按 R3 输出且仅输出一个最终分类:FIXTURE、PRODUCT、MIXED 或 INCONCLUSIVE/PAUSED,并列出支持证据和反证。— 唯一分类 FIXTURE。
  • AC5:若为 PRODUCT/MIXED,认证产品代码保持未修改并停在独立任务批准前;若为 FIXTURE 且同任务修复,diff 仅限 test fixture/harness,先有分类检查点,且不得删除或弱化断言。
  • AC6:原样保留并落实“不得以删除断言作为默认修法”;目标测试数量、关键完整导航与会话语义无静默减少。
  • AC7:所有自动化、typecheck(若 test code 有改动)、task/process/governance/sensitive 与 git diff --check 按范围通过;结果明确为本地诊断,未连接生产、未部署。

Out of Scope

  • 未完成分类前修复 AuthContext、refresh rotation、cookie、Vite proxy 或后端认证路由。
  • 生产登录、生产 session 查询、生产配置、部署、公网 smoke 或真实用户账号操作。
  • 合同 UI 验收、员工负向验收、管理员手册附件承诺,以及其他 Playwright 失败。
  • 为追求套件全绿而重写 8 条业务断言或扩大通用 mock 成功面。

Risks and Deferred Items

  • 当前源码证据更偏向 fixture/session hint 缺口,但这只是待验证假设,不是结论。
  • 真实本地 session 对照会创建/轮换本地测试会话;执行前必须 fail-closed 确认回环主机和本地回归库,结束后按既有测试清理合同处理。
  • 若最终需要认证产品修复,风险等级上升为生产登录态缺陷,必须新建独立任务、补真实数据库/浏览器回归并启动只读 reviewer。
  • 管理员手册的合同附件承诺应在首条真实合同出现前单独修订,不并入本任务。

Test Plan

  • 原样复现:cd client && npx playwright test tests/e2e/r103-cross-page-ui-consistency.spec.ts tests/e2e/global-search.spec.ts --workers=1 --reporter=list
  • 必要时按历史失败标题 --grep 单跑并 --repeat-each 验证稳定性;不以 retry 作为通过证据。
  • 前端对照:聚焦 login-portal-ux.spec.ts 中 bootstrap refresh 用例及新增/临时安全 ledger。
  • 后端对照:cd server && npm test -- tests/unit/routes/auth.login.test.js;若需真实本地 session,先运行本地 target gate,再执行最小浏览器/API witness。
  • 若修改测试:cd client && npm run typecheck,再运行两份目标 spec 与相关 auth 对照。
  • python3 ./.trellis/scripts/task.py validate 08-10-session-fallback-failure-classification
  • node scripts/qa/check-process-contract.mjs --baseline --json
  • node scripts/qa/check-trellis-governance.mjs --json
  • node scripts/qa/check-sensitive-content.mjs
  • git diff --check

Open Questions

  • 无。分类目标、四种停止状态、生产边界和修复分叉均已明确;技术未知由本任务实验回答。