文件
hyb-oa/.trellis/tasks/archive/2026-07/07-16-system-multidimensional-audit/research/engineering-review.md
T

7.1 KiB
原始文件 Blame 文件历史

工程、测试、性能与运维审查

本文件保留原发现基线的分域证据。当前 HEAD 增量、唯一分级和生命周期状态 分别以 research/current-head-delta.md 与 research/findings.md 为准。

测试资产与实测覆盖率

  • 后端:153 个 Vitest 文件、786 个用例;普通回归与 V8 coverage 运行均为 153/153、786/786 PASS。
  • coverage 实跑耗时 196.80 秒;统计范围为 198 个源码文件,lines/statements 57.34%、functions 71.03%、branches 57.93%。
  • 前端:Playwright 默认清单为 144 tests / 56 files;client/src 没有独立 unit/component spec,纯函数和组件合同主要依赖 TypeScript、静态门禁与 E2E 间接覆盖。
  • server/vitest.config.cjs 配置 coverage 报告,但没有最低阈值;因此 npm run test:coverage 即使整体或关键目录覆盖下降也不会失败。
  • 低覆盖集中在作业编排、部分管理/财务 route 和运行脚本。例如 delegation revoke、invoice archive、integration outbox、ERP master-data sync 等 job 的 lines 覆盖约 6%–13%;src/index.js、src/worker.js 及多项生产运维脚本为 0%。这不说明实现错误,但说明“全部用例通过”不能覆盖启动、调度与恢复行为。

候选 finding:测试通过不等于核心运行面已覆盖

  • 建议级别:P2 / CONFIRMED。
  • 影响:回归能够发现大量 route/service 逻辑问题,但无法通过阈值防止覆盖率缓慢退化;作业入口和运维脚本的回归更多依赖 mock/手册,生产调度错误可能较晚暴露。
  • 建议:按风险设分层阈值而非一次追求全仓高数字;优先给认证恢复、资金状态、worker/job 注册、迁移/备份脚本设置关键文件阈值和负路径测试。前端先为权限显隐、路由映射和共享页面模板补小型 unit/component 合同,不必把所有页面复制成 unit spec。

流程覆盖扫描可信度

执行 node scripts/qa/check-flow-coverage.mjs --json:

  • 报告摘要为 68 条前端路由、5 个业务域、68 个后端 route 文件、highRiskGapCount=0。
  • 实际 68 条前端路由中只有 29 条映射到业务域,39 条标为 unmapped;未映射包括合同、项目、资产、票据、付款、差旅、人员及绝大多数 /system/* 页面。
  • 矩阵使用 /system/*,而 routeTokenMatches 只处理完全相等、参数路由或 path prefix,不实现 * 通配,因此整组系统页面无法映射。
  • specMatchesRoute 在精确路径之外使用整个业务域的宽泛关键词;认证域含 login / mobile 等高频词,导致每条认证/移动路由都被匹配到全部 63 个 spec,并全部显示 WeCom、visual、flow 已覆盖。
  • 扫描还把默认 Playwright 配置会排除的 manual/ live spec 纳入覆盖证据。
  • scripts/qa/run-release-gate.sh 生成该报告时没有传 --fail-on-gaps;即使扫描识别出缺口也只写报告,不阻断门禁。

候选 finding:覆盖扫描产生系统性假阳性

  • 建议级别:P1 / CONFIRMED。
  • 影响:项目级发布证据可以在 39 条路由未映射、单路由无直接断言时仍显示“P0 缺口 0”;这会掩盖权限、视觉和业务流的真实测试缺口。
  • 建议:要求所有受支持路由显式映射;实现 * 语义;只认精确 route/test manifest 或测试内结构化标签,不以业务域关键词推断;默认排除 manual/live;发布门禁在 unmapped 或 P0 缺口时失败。

项目级发布门禁可执行性

scripts/qa/run-release-gate.sh project-wide 的静态阶段存在当前环境可确认的阻断:

  • 第 88–89 行固定要求历史 issues/2026-05-08_23-38-37-project-wide-qa-second-pass.csv。
  • 校验器硬编码为用户目录下旧 plan skill 的绝对路径;当前机器该文件不存在。
  • 因为脚本启用 set -euo pipefail,执行到该行会直接退出,后续 UI、移动路由、流程覆盖、迁移诊断和浏览器门禁均不会运行。
  • 这也与当前 Trellis-first / Trellis-only 入口冲突:历史 Issue CSV 可以保留审计,但不应重新成为新发布门禁的隐含执行合同。

候选 finding:项目级发布门禁依赖已不存在的个人工具

  • 建议级别:P1 / CONFIRMED。
  • 影响:当前 checkout 无法从仓库自身执行标准 project-wide 门禁,在新机器/CI 上同样不可移植,容易迫使发布者绕过标准路径。
  • 建议:删除历史 Issue/外部 skill 前置,改为仓库内 Trellis governance + 当前 task validate;需要 CSV 导出时使用仓库内受控脚本并作为显式可选步骤。

依赖与供应链边界

  • npm ls --depth=0 --json:server 35 个直接依赖、client 26 个直接依赖,均 exit 0 且无 missing/invalid/extraneous problem。
  • 按当前无公网边界未执行 npm audit,因此不能声称不存在已知 CVE。上线 checklist 要求 npm audit --omit=dev --audit-level=high;当前结论为 EXTERNAL_GATED,准入条件是允许访问 npm advisory registry 并记录锁文件对应结果。
  • 运行中仍出现 Node punycode 弃用提示;属于依赖维护观察项,尚无证据证明影响业务。

前端构建与性能观察

  • production build 总体约 2.8 MiB、94 个 asset 文件,页面主体采用 React.lazy 拆分。
  • index.html 初始 preload 包含 React、Query、UI、app-core、app-domain-shared;最大扫码依赖 chunk vendor-scan 约 411 KiB,但未被首页 HTML preload,按路由延迟加载。
  • 初始入口相关的未压缩 JS/CSS 约为:entry 127 KiB、React 166 KiB、UI 145 KiB、Query 41 KiB、app-core 72 KiB、app-domain-shared(较小)以及 CSS 89 KiB;另有 Material Symbols 字体约 479 KiB。当前没有基于网络/设备的 LCP、INP 或内存实测,不能据体积直接判定性能故障。
  • Topbar 和移动底栏各 30 秒轮询通知;OCR pending 时 3 秒轮询。代码证据表明 OCR 轮询按 pending 条件关闭,暂无“永久 3 秒轮询”证据。

性能结论

  • 当前无 P0/P1 性能 finding。
  • P2 观察:建立 build budget 和低端移动网络测量,重点关注图标字体、初始 UI chunk、通知双入口轮询以及 OCR 多页面重复查询;先测量再优化。

运维、迁移与恢复

  • 部署合同具备 Docker healthcheck、/ready、完整后端 SHA / 12 位前端 SHA、init migration、runtime smoke、external-deps smoke、live readiness、DB + 文件存储备份/恢复脚本和回滚手册。
  • 仓库内确有 scripts/backup-db.sh、backup-storage.sh、restore-db.sh、restore-storage.sh;运行手册引用不是悬空命令。
  • Prisma schema validate 通过;共有 58 个迁移目录。本任务未连接数据库,migrate status / drift、恢复演练和公网 source provenance 均为 EXTERNAL_GATED。
  • 旧 7 日试运行只完成 Day 1–Day 4;当前本地 commit 未部署。因此恢复、真实调度、告警和公网 readiness 只能报告“合同存在、行为待外部补证”,不能记为 PASS。

本轮生成物

  • server/coverage/ 由本轮 coverage 运行生成且被忽略,最终汇总取证后删除。
  • 不删除历史 artifacts/ 或其他任务的证据。