文件
hyb-oa/.trellis/tasks/archive/2026-08/08-07-local-database-migration-readiness/implement.md
T

13 KiB
原始文件 Blame 文件历史

实施计划

当前状态:迁移、接口基线、只读 review、收口门禁与工作提交均已完成;数据库结论 PASS,浏览器回归为 PASS_WITH_FINDINGS(16/10/0),待归档。

1. 执行前固定现场

  • 记录当前 HEAD、当前 task、git status --porcelain;发现非本任务脏文件时停止确认。
  • 确认 08-05-contract-detail-workspace 仍为 planning,未提前开始 schema 实施。
  • 确认 artifacts/qa-flow/08-07-local-database-migration-readiness/ 为 gitignored 本地证据目录。
  • 复读 prd.md、design.md、.trellis/spec/hyb-oa/backend-fastify-prisma.md 和 docs/试运行与自动化验证手册.md 的 migration drift 边界。

2. Pre-status 只读基线

  • 运行: MIGRATION_DRIFT_REPORT_DIR=artifacts/qa-flow/08-07-local-database-migration-readiness/pre bash scripts/qa/check-local-migration-drift.sh
  • 从原始输出记录 Prisma 实际退出状态;不得把 wrapper 的最终退出 0 当作“无 pending migration”。
  • 只记录脱敏目标结论,确认 datasource 为预期回环本地开发数据库。
  • 逐项记录 pending migration ID,并复读对应 migration.sql。
  • pending 集合属于以下已核查 allowlist 子集;本次实际集合为全部六条:
    • 20260717120000_auth_challenge_trusted_proxy_hardening
    • 20260718120000_add_system_admin_role
    • 20260718123000_small_team_payment_cancel_reason
    • 20260727153000_allow_employee_phone_null
    • 20260801120000_reimbursement_travel_summary
    • 20260802143000_corporate_bank_account_payment_order
  • 运行 cd server && npm run prisma:validate,结果 PASS。

强制停止条件

  • 目标非回环、目标不明或不是预期本地开发库 → PAUSED,零写入;本次未触发,已确认 loopback=true。
  • status 显示 failed migration、history divergence、applied migration 异常或 allowlist 外 pending → PAUSED,回来确认。— 第一次 pre-status 发现 3 条原 allowlist 外 pending 后已暂停;用户已复核 SQL并明确批准扩展到全部 6 条,继续前须再次确认 pre-status 未变化。
  • 实际 SQL 包含删除表、删除列、清空数据、重置或其他未规划破坏性操作 → PAUSED,回来确认;六条均未命中,本次未触发。
  • status 已是最新但 /api/me 仍缺列 → 不运行 deploy,转只读诊断并 PAUSED;本次 deploy 后 status current,未触发。

3. 唯一迁移写入

  • pre-status 非 current,未记录 SKIPPED_ALREADY_CURRENT。
  • 存在允许的 pending migration,仅运行一次: cd server && npm run prisma:migrate:deploy
  • 记录退出状态和应用的六个 migration ID,不复制数据库连接信息;命令退出码为 0。
  • 若命令失败,立即保存输出并只读重跑 status;本次未失败,且未运行 migrate dev/reset/db push/resolve、手工 DDL 或迁移历史修改。

4. Post-status 与接口基线

  • 运行: MIGRATION_DRIFT_REPORT_DIR=artifacts/qa-flow/08-07-local-database-migration-readiness/post MIGRATION_DRIFT_STRICT=1 bash scripts/qa/check-local-migration-drift.sh
  • 确认 strict 退出 0、同一目标、无 pending/failed/diverged migration;原始 post-status 已保存。
  • cd client && npm run build PASS,并使用当前 checkout 的前端产物启动本地服务;第一次启动缺少必需的字段加密配置,所对应的回归结果作废,随后已用回环 host、JOBS_ENABLED=false、SERVE_CLIENT_DIST=true 重启并完成有效验证。
  • 通过现有认证链路确认 /api/me 返回 200;employee、manager、finance、finance manager、admin 五类 fixture 均为 login=200、me=200,未再出现缺列错误。

5. 五个用例补跑

  • 运行(第二轮、有效服务配置): 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:
    • procurement-flow.spec.ts:0 passed / 1 failed / 0 skipped;创建采购后审批摘要仍期待历史英文 Employee,实际页面已返回中文申请人摘要。
    • assets-flow.spec.ts:0 passed / 1 failed / 0 skipped;创建 API 成功后页面仍停留 /assets/new,未跳到预期 canonical 详情路由。
    • r103-cross-page-ui-consistency.spec.ts:4 passed / 7 failed / 0 skipped;失败集中在合同标题、采购/资产详情及未保存/中等宽度场景,多个上下文回到登录页。
    • pc-detail-mobile-visual-wave3.spec.ts:9 passed / 0 failed / 0 skipped。
    • global-search.spec.ts:3 passed / 1 failed / 0 skipped;canonical path 用例第二次回到 portal 后搜索触发器等待超时并落到登录页。
  • 记录第二轮总数:16 passed / 10 failed / 0 skipped(26 tests);第一次缺少本地服务必需加密配置时的 17/9 结果明确作废,不计入最终证据;记录不含凭据、token、原始 payload 或完整本地路径。
  • 明确采购、资产真实流产生的本地合成测试记录属于获批副作用;未执行清理、seed 或 reset。

6. 失败分流

  • migration/status/缺列导致的失败:本次未发生;post strict 与 /api/me 均通过,数据库基线层结论为 PASS。
  • /api/me 已 200 后的路由、页面行为或选择器失败:全部归为产品路由/页面契约或测试桩会话夹具问题,登记为 08-05-business-detail-routing follow-up 候选;本任务未改代码/测试。
  • 业务前置数据不足:本次未据此归因,也未自动 seed;真实流失败均有可复现的页面/断言首个失败证据。
  • 本地服务/端口问题:第一次服务启动配置不完整,已仅恢复当前 checkout 的安全启动条件;未修改产品功能。
  • 任何 spec 失败时,未把“数据库基线恢复”写成“五个用例全绿”;已分别记录数据库 PASS 与浏览器 PASS_WITH_FINDINGS(16/10/0)。

7. 只读 Review

  • 启动只读 reviewer,明确 reviewer 不修改文件。
  • Reviewer 核对:回环目标、pre/post status、pending allowlist、唯一 deploy 命令、禁用命令未执行、无业务代码/schema/test 改动、失败分类真实;结论 PASS,未修改文件、未运行长测试。
  • Reviewer 核对合同任务仍未在迁移基线形成前启动;08-05-contract-detail-workspace 仍为 planning。

8. 收口门禁

  • python3 ./.trellis/scripts/task.py validate 08-07-local-database-migration-readiness PASS。
  • node scripts/qa/check-trellis-governance.mjs --json PASS,0 errors / 0 warnings。
  • git diff --check PASS。
  • 检查 git diff:git status --porcelain 仅包含当前 Trellis task 目录;artifacts/ 保持 ignored,无 server/client/schema/migration/test 改动。
  • PRD Acceptance Criteria 按真实证据勾选;非数据库失败保留 PASS_WITH_FINDINGS,未伪装为 PASS。
  • 使用中文 commit message 并引用 08-07-local-database-migration-readiness;工作提交 8f026b6,未 push、未部署。

9. 执行记录

规划阶段留空。任务启动后按以下字段回填:

  • HEAD:0124a2b
  • Pre status reportRef:artifacts/qa-flow/08-07-local-database-migration-readiness/pre/prisma-migrate-status.txt
  • Pre Prisma exit/status:Prisma status 1;wrapper 按设计返回 0,人工核读为 6 条 pending。
  • Loopback/target match:loopback=true,预期本地回归数据库匹配。
  • Pending migration IDs:
    • 20260717120000_auth_challenge_trusted_proxy_hardening(当前 allowlist 外;增加认证挑战字段/索引,并使本地未使用验证码失效)
    • 20260718120000_add_system_admin_role(当前 allowlist 外;增加 enum 值)
    • 20260718123000_small_team_payment_cancel_reason(当前 allowlist 外;增加可空字段)
    • 20260727153000_allow_employee_phone_null
    • 20260801120000_reimbursement_travel_summary
    • 20260802143000_corporate_bank_account_payment_order
  • Deploy:2026-08-07 执行一次 cd server && npm run prisma:migrate:deploy,exit=0;六条 pending 全部成功应用。
  • Post status reportRef:artifacts/qa-flow/08-07-local-database-migration-readiness/post/prisma-migrate-status.txt
  • Post Prisma exit/status:Prisma 原始 status exit=0(strict wrapper exit=0);输出为 Database schema is up to date!,同一 datasource、无 pending/failed/diverged。
  • /api/me:五类本地 fixture(employee、manager、finance、finance manager、admin)login=200、me=200;未出现 employees.bank_institution_id 缺列错误。
  • Five-spec result:26 tests,16 passed / 10 failed / 0 skipped;按 spec 数字见第 5 节。pc-detail-mobile-visual-wave3.spec.ts 全绿,其余四个含失败。
  • Failure classification:数据库迁移层 PASS;10 条失败均在迁移对齐和 /api/me 恢复后出现,归为路由/页面行为、E2E 断言契约或 mock 会话夹具问题,登记 08-05-business-detail-routing follow-up 候选;本任务未改产品代码、测试或数据。
  • Read-only review:PASS;bounded reviewer 只读完成,确认同一 loopback 目标、六条 allowlist、一次 deploy、post current、16/10/0 数字自洽、无业务代码/schema/migration/test/权限/生产配置改动;未修改文件。
  • Spec/docs update:无需新增稳定 spec;.trellis/spec/hyb-oa/backend-fastify-prisma.md 的 Local Regression Migration Drift 已覆盖 status → 显式批准 deploy → 缺列消失后将选择器/页面失败分流的完整规则,本任务仅补充当前 Trellis 证据。
  • Remaining PAUSED/NOT RUN:本地数据库迁移基线已恢复;浏览器回归为 PASS_WITH_FINDINGS,非迁移失败待后续 task;企业微信真机、生产/公网仍按 R10 保持 PAUSED,合同任务启动仍需独立批准。

10. 回归失败证据索引

  • client/test-results/assets-flow-E2E-资产流转主链路:建卡→领用归还→调拨→盘点/error-context.md:POST 创建返回成功,但页面停留 /assets/new,未完成 canonical 详情跳转。
  • client/test-results/procurement-flow-E2E-采购主链路:员工提单→经理审批→财务归档/error-context.md:审批详情已渲染中文采购摘要,断言仍要求 Employee。
  • client/test-results/global-search-E2E-全局搜索:采购与资产忽略旧-href-并使用实体-canonical-路径/error-context.md:第二次回到 portal 后 global-search-trigger 等待超时,页面为登录态。
  • client/test-results/r103-cross-page-ui-consist-2485f-务台账标题区保持一主操作加至多一个更多,列表工具不常驻/error-context.md:合同列表标题未出现。
  • client/test-results/r103-cross-page-ui-consist-bed95-cy-采购页使用安全格式上传并通过认证-Blob-下载/error-context.md、06cda-资产列表、详情各自只请求职责内数据并恢复-URL-筛选/error-context.md、aa8b7-与资产长表单详情对-403-404-使用同一安全错误态/error-context.md、c9ebc-ncy-采购长表单切回记录列表时支持取消保持与确认放弃/error-context.md、b8364-cy-共享未保存保护覆盖浏览器返回取消、确认与刷新拦截/error-context.md、b7ec9-ursements-在中等宽度下操作列可达且页面不横溢/error-context.md:均在页面契约断言前回到登录页,归为 mock 会话/页面环境问题,未归因于 migration。

Post-Archive Delta · 2026-08-07

  • 原 16 passed / 10 failed / 0 skipped 仍是迁移任务当时的历史证据,不回写为全绿。
  • 失败分类已由后续任务 08-07-business-routing-regression-repair 纠正:资产创建成功后停留 /assets/new 是产品回归(共享未保存保护竞态);采购摘要中的英文 Employee 是测试断言漂移;其余 8 条仍是独立登录态/mock 会话候选。
  • 修复后在同一回环本地数据库、当前 checkout 和完整服务配置下,真实 assets-flow.spec.ts 与 procurement-flow.spec.ts 合计 2 passed / 0 failed / 0 skipped;聚焦共享未保存保护用例 1 passed / 0 failed / 0 skipped。
  • 真实回归过程中发现的两个额外测试契约漂移(资产用例在 1024px 继续查找桌面侧栏入口、采购用例仍操作已迁移的常驻范围控件)已在目标测试文件内最小修正;未修改数据库、登录实现、其余 8 条会话夹具或产品范围外代码。
  • 数据库迁移层的结论仍是 PASS;本 delta 只更新失败归属和后续验证,不改变原迁移执行证据,也不宣称企业微信真机或生产/公网已验证。