文件
hyb-oa/.trellis/tasks/07-27-yang-jun-reimbursement-readiness/implement.md
T

66 KiB
原始文件 Blame 文件历史

杨俊报销就绪:执行计划

0.1 报销 UX 最小收口(本轮)

  • PC 报销列表和审批任务向报销详情传递受控来源;详情标题左上方提供明确返回并删除业务动作区重复列表入口。
  • displayFormat.ts 新增共享人民币金额格式,PC/移动报销详情统一复用。
  • 移动草稿底部固定栏删除重复“添加发票”,材料区入口和提交主动作保持可用。
  • 聚焦 Playwright 覆盖列表筛选返回、审批任务返回、直接打开降级、金额格式与移动单一入口;再运行 typecheck、build 和治理门禁。
  • 本轮只做本地实现与验证;未获部署批准前不发布、不修改生产配置或真实业务数据。

0.2 R5 移动契约与门禁收口(本轮)

  • 修正 R5 首页指标采集:从 mobile-action-grid 的直接入口动态取得 key 与布局,不再维护已经失效的旧 key 列表。
  • 对经理测试角色明确断言有序入口集合为 new-reimbursement / capture / leave / purchase,保留 44px、单行、SVG、边界和无重叠检查。
  • 将 R5 登记到 route-manifest.json 的 acceptanceSpecs,使 run-local-candidate.sh 的 list/focused/full 都能解析并执行该用例;不重复加入另一个门禁造成同轮双跑。
  • 运行 R5 双设备、flow coverage/本地候选资产解析、前端 typecheck/build 与 Trellis 治理门禁;记录约 18 个其他孤儿 spec 为后续治理,不在本轮扩范围。
  • 修正上一轮证据中的错误表述:页面实际仍有四个入口,只有旧采集器因 key 漂移看见两个;本轮未推送、未部署前不宣称线上已修复。

0.3 生产部署流程加固(本轮部署后)

  • 如实记录 5dac336 发布的首次错误根目录尝试、.env 原子恢复、第二次成功发布、独立构建身份和备份链验证;真实业务数据与审批状态不变。
  • 把远端仓库根、SYNC_ENV=0 env、existing PGDATA/storage 验证前移到 rsync 之前;错误合同必须在任何远端同步前停止。
  • 重排 Dockerfile,使基础包与两套 lockfile 依赖层不受 build SHA 变化影响,同时保留前端短 SHA和后端完整 SHA。
  • 收敛 deploy seed/external/runtime smoke 的账号、联系方式和外部配置标识输出,只保留 readiness、计数和状态。
  • 增加部署顺序、错误停止点、Docker 缓存顺序和日志最小化回归;更新 deployment spec 与 runbook。
  • 运行聚焦单测、环境/来源合同、shell 语法、敏感扫描、Trellis/process/docs/diff 门禁;单独提交本地加固,不在未获再次批准时部署。

1. 生产写入前门禁

  • 只读复核活动 server 构建标识、Compose 项目、4 个 systemd service 当前 BUILD_SHA、timer enabled/active、最近源端备份与 ARM 新鲜度;输出仅限状态和计数。
  • 使用活动部署的显式合同参数重装 automatic backup 的 daily/watchdog/drill-reminder units。
  • 使用活动部署的显式合同参数重装 WARCH3 unit。
  • 验证以下 4 个 service 的 BUILD_SHA 全部等于活动 server,相关 timers 为 enabled/active:
    • hyb-oa-automatic-backup-daily.service
    • hyb-oa-automatic-backup-watchdog.service
    • hyb-oa-automatic-backup-drill-reminder.service
    • hyb-oa-warch3-ops.service
  • 手工启动一次 automatic backup daily service;确认源端 Result=success、ExecMainStatus=0。
  • 在 ARM 只读验证新批次完成、manifest/文件完整性与新鲜度检查通过;任何失败均停止人员写入。

2. 杨俊单人导入

  • 从管理员导出的通讯录以管道/内存方式筛选杨俊一人,不生成持久化子集文件,不输出个人字段。
  • 在生产容器运行 dry-run,验收计数:输入 1、active 1、incomplete 0、planned create 1、conflict 0、skip 0、failure 0。
  • dry-run 符合预期,无需进入偏差处理分支。
  • 经本任务最终实施批准后,使用 docker-compose exec -T -e WECOM_DIRECTORY_EXPORT_APPLY ... --input=- --apply 写入唯一目标。
  • 只读验证杨俊 OA 员工为 active、企微绑定唯一、初始角色严格为 employee,且其余通讯录成员未进入本轮输入或写入。
  • 确认生产企微通讯录写回门禁关闭;本轮同步结果为 skipped,未调用企微成员写接口。

3. 设置真实直属主管

  • 写入前记录杨俊原 direct_manager_id 的脱敏状态,并确认马建勇为 active、不同员工且具有 expense.approve。
  • 通过现有 POST /api/users/batch/set-manager 仅将杨俊的主管设置为马建勇;不直写数据库、不调整任何人的角色。
  • 写后验证主管解析成功,并核对 SYSTEM_USERS_BATCH_SET_MANAGER 审计增量;该接口合同不递增目标员工 token version 或撤销会话。
  • 主管写入成功,未进入失败或误配回退分支。

4. 聚焦验证

  • 运行通讯录导入相关测试,覆盖手机号为空、单目标和 apply 双门禁。
  • 运行 users set-manager 路由测试,覆盖 active、自指、审计和权限边界。
  • 运行 workflow/reimbursement 聚焦测试,覆盖主管解析、expense.approve、无差旅申请和绑定票据提交门禁。
  • 运行 cd server && npm run prisma:validate;代码未变化时仍将结果作为当前合同基线记录。
  • 运行 Trellis task/governance、流程/文档、敏感扫描和 git diff --check。
  • 按项目规则对权限、workflow 和生产写入证据做一次只读 review;Codex inline 主代理复核通过,未发现角色扩权、企微反向写入、审批自审或生产测试业务数据。

5. 两个既有企微测试成员的受控验收

  • 从管理员通讯录以内存方式仅筛选“测试员工”和“测试主管”,验证二者唯一、active、资料满足导入合同;不输出或持久化原始字段。
  • 生产 dry-run 验收输入 2、计划创建 2、冲突/跳过/失败 0;偏差即停止。
  • 单独取得生产测试账号/业务写入批准后 apply,并确认两人 active、企微绑定各自唯一、没有导入其他成员。
  • 通过现有角色接口将角色收敛为:测试员工=employee,测试主管=employee + manager;核对 token version、会话撤销及角色审计。
  • 通过现有主管接口设置“测试员工 → 测试主管”,确认测试主管 active 且具有 expense.approve。
  • 两个测试成员均完成账号密码登录与首次改密,申请人可见报销入口、主管可见审批入口;企微 SSO 因不能冒充企微身份仍待人工确认。
  • 测试员工创建唯一一条描述含“系统测试、非真实业务、禁止付款”、总额 0.01 元的测试报销,并上传不含真实资料的安全 PDF。
  • 合成 PDF 经生产 mock OCR 自动生成测试字段并标记可用,绑定后成功提交;该结果同时暴露真实使用前必须移除 mock OCR 的门禁。
  • 测试主管确认待办可见并执行“退回”,未执行“通过”;报销回到 draft 且 workflow instance 终止,无需追加“撤回”。
  • 测试员工删除 draft 报销;票据解绑回到 available 后已手工归档。
  • 管理员停用两个测试 OA 账号并确认会话撤销、企微写回为 skipped;企微侧两个测试成员保持不变。
  • 只读收口确认:测试报销 0、pending 待办 0、测试票据唯一且为 manual archived、两个测试 OA 账号为 archived、活动会话 0、企微绑定保留 2;未产生测试付款。

5.1 真实发票路径门禁

  • 只读确认生产当前为 OCR_PROVIDER=mock,腾讯 OCR 凭证未配置。
  • 用户选定“关闭 mock 并采用财务查看 PDF 原件人工核对”;本轮不改代码、不部署新构建。
  • 生产 .env 已切换为 OCR_PROVIDER=off;现场无独立 worker 且 JOBS_ENABLED=true,因此仅强制重建 server。公网 /ready 正常,构建仍为 4886f9b081dd。
  • 重新启用两个测试 OA 账号并完成受控 API 闭环:新 PDF 直接 available,八个发票业务字段为空、OCR 尝试为 0,绑定、提交、主管退回均成功。
  • 复验后删除测试报销、归档测试票据、停用测试 OA 账号;最终活动会话 0、测试报销 0、pending 待办 0、未归档测试票据 0,企微同步均为 skipped。
  • 记录非阻断 schema finding:off 路径未显式写 provider,但 ocr_provider 因非空默认值仍存 tencent;请求/完成时间和 OCR 结果为空,当前 UI 不展示该字段。

6. 用户真实验收

  • 在杨俊提交前通过现有审批规则管理接口把三档规则收敛为唯一 [0,+∞) 规则,审批链固定为 department_manager → finance;不扩角色、不保留 CEO 重复节点。
  • 规则写入前后只读核对 499.99 / 500 / 5000 三个金额,确认解析结果完全相同且 active finance 有唯一实际处理人。
  • 杨俊本人从企业微信进入 OA,身份解析成功并能看到报销入口;用户后续确认该差旅报销已经走完整个业务链路。
  • 杨俊使用真实业务数据创建报销,至少添加一条费用明细并上传/绑定状态有效的真实票据后提交。
  • 马建勇已看到真实审批待办并按业务事实处理;完成状态由用户确认,并由后续生产只读闭环查询交叉验证。
  • 单据已完成王芝玲负责的财务处理链路、付款批次 maker-checker、真实付款和回单留存;只读查询确认存在关联的 executed 批次与已批准回单。
  • 用户验收记录与任务证据只保留脱敏状态、计数和结论,未写入票据、金额、银行资料或完整账号。

6.1 审批详情可达性修复

  • 保留移动待办列表卡片现有 handleTaskSelection 行为,不修改任务列表到审批任务详情的路由。
  • 在 MobileApprovalsPage 的审批任务详情报销摘要区增加“查看完整报销单”,复用 /mobile/reimbursements/:id 和现有 state.from 来源回跳约定。
  • 在 WorkflowTaskDetailPage 的报销摘要区增加“查看报销单”,复用 PC 报销详情路由。
  • 不修改后端、审批状态机、权限矩阵或生产数据;请假、采购、差旅同类入口缺口仅记录,不在本轮扩展。
  • 增加聚焦前端回归,验证移动进入/返回及 PC 入口;运行前端 typecheck、build、Trellis task/governance 和 git diff --check。

6.2 审批详情入口生产发布

  • 将工作提交 d2841b1 推送后,以 SYNC_ENV=0 按标准发布脚本部署;未覆盖生产 .env,未修改审批状态、真实业务数据或付款数据。
  • 第一次发布尝试在同步前因附件挂载目标解析不匹配停止,生产未变化;按活动容器的实际挂载目标修正输入后重新执行。
  • 发布来源校验、环境合同、远端 Compose 校验、Prisma migration status、/ready、external deps smoke、runtime smoke 与公网资源扫描均通过,活动构建为 d2841b166dc0。
  • 使用既有 unit 中的受控合同参数重装 automatic backup 三项 service/timer 与 WARCH3 service/timer;第一次读取活动容器时因未向 Compose 显式传入构建变量而在 unit 写入前失败,补齐目标构建参数后成功。
  • 4 个 service 的 BUILD_SHA 均与活动构建一致;4 个 timer 均为 enabled/active。
  • 手工触发 automatic backup daily,源端 Result=success、ExecMainStatus=0;随后源端 watchdog 同为 success/0。daily 只有在 ARM receiver 完成三文件、manifest 与 SHA-256 校验并原子 finalize 后才会成功。
  • ARM dead-man timer 保持 enabled/active,最近一次自动运行是 success/0;本次尝试立即手工复跑被已收口的最小权限策略拒绝,未恢复临时 sudo、未改 ARM。不得把该证据写成“独立 dead-man 已对新批次即时复跑”。
  • 公网 /ready 构建标识匹配,已发布的移动端和 PC 资源分别包含“查看完整报销单”和“查看报销单”;未读取、截图或输出真实报销内容。

6.3 报销详情时区与 KISS 收敛

  • 让共享日期时间格式化显式使用 Asia/Shanghai,PC/移动报销详情与 PC 审批任务详情移除本地字符串截取函数并复用共享实现。
  • PC 合并重复概况,收敛明细、发票、附件标题和解释;无关联或无预算/风险内容时隐藏对应辅助区块。
  • 移动概况删除重复状态、计数教学和冗余下一步文案;只读无动作时不渲染空操作卡,编辑能力保持不变。
  • 用合成数据补附件 UTC→上海时间和 KISS 信息层级聚焦回归;运行前端 typecheck、build 与相关 Playwright。
  • 运行 Trellis task/governance、流程合同、文档审计、敏感扫描和 git diff --check;生产部署另行批准。

6.4 企微 WebView 旧包刷新护栏

  • 在页面从后台恢复为可见时请求 /ready,比较规范化后的前端与 server 构建标识;一致、未知或请求失败时静默。
  • 构建不一致时复用现有 PWA 更新事件,在已登录 PC/移动壳显示“发现新版本,点击刷新”;不自动重载页面。
  • 点击刷新后清理旧 PWA runtime/precache 并重载;同一页面生命周期只提示一次。
  • 用合成 /ready 响应覆盖 mismatch、match 和 failure,运行 typecheck、build、聚焦 Playwright 与 Trellis 门禁。
  • 只提交并推送;生产部署和经理二次刷新另行执行,不在本步骤自动部署。

6.5 企业微信原生发票与附件预览

  • 增加企微 JSAPI ticket 获取/缓存和本站 URL 签名接口;覆盖缺配置、上游失败、跨 origin、fragment/凭据 URL 拒绝与脱敏返回。
  • 发票短时 URL 响应补准确文件元数据;移动企微用 previewFile,PC 用浏览器预览。
  • 为报销附件增加严格对象授权、理由门禁和实际取件审计的短时预览 URL;不扩大角色或通用下载权限。
  • 抽取 PC/移动共用材料预览调用,企微路径不使用异步 window.open(blob:);只读审批人看得到查看动作但看不到编辑、解绑、删除动作。
  • 用合成文件与 mock JS bridge 运行后端聚焦测试、前端 typecheck/build 和 PC/移动 Playwright 一致性回归。
  • 运行 Trellis 治理、流程/文档、敏感扫描、git diff --check,并对新增短时授权边界做只读 review;不在本步骤部署生产。

6.6 原生预览生产发布与运维对齐

  • 将提交 410d8cd 推送后以 SYNC_ENV=0 发布;未覆盖生产 .env,62 个 migration 无待执行项,公网 /ready 的 12 位构建标识匹配。
  • 如实记录两次发布尝试:第一次使用 runbook 示例发布目录和普通运维入口,来源/环境合同通过,但 rsync 因目录权限在同步前失败,生产未变化;随后从活动 Compose 标签解析实际发布根目录,复用既有受控 root 运维入口成功发布,未新增 sudo 或修改目录权限。
  • external deps、runtime smoke 与公网 bundle 扫描通过;公网包包含 previewFile、同源 JS-SDK 签名接口和附件短时预览入口,未登录请求签名接口返回 401。
  • 发布后从既有 unit 内部复用受控合同参数和运行时间,仅把 automatic backup 三项与 WARCH3 的构建标识刷新为 410d8cd;4 个 service 均匹配活动构建,4 个 timer 均为 enabled/active。
  • 手工触发 automatic backup daily 和源端 watchdog,二者均为 success/0;daily 成功以异机接收端完成文件、manifest、哈希校验和原子 finalize 为既有合同。
  • 记录非阻断依赖 finding:本次镜像构建审计报告 client 18 个风险(10 high),server 32 个风险(20 high、2 critical);未在发布窗口执行自动升级,留待独立依赖升级和回归任务。
  • 记录证据最小化 finding:既有 external/runtime smoke 输出仍包含不必要的配置标识和测试管理员联系方式;本任务不复述这些值,后续应独立收敛为状态与计数输出。
  • 用户已确认真实报销材料能够在企微查看;该报销后续已完成主管审批及完整业务闭环。

6.7 移动报销查看范围对齐

  • 在 MobileReimbursementsPage 读取 expense.view_all,仅对有权用户显示“我的 / 全部”范围切换;复用现有 Tabs/按钮样式,触控高度为 48px。
  • 范围默认和无权限回退均为 own;切换 all 时写入 URL 查询参数并纳入 React Query key,调用现有 fetchReimbursements({ scope }),不改后端或扩大权限。
  • 列表到详情的 state.from 保留当前 status 和 scope;普通员工不渲染“全部”入口,“全部”范围不显示仅限本人草稿的删除动作。
  • 增加聚焦 Playwright:管理员默认本人、切换全部后看到他人单据并进入详情;普通员工即使手工带 scope=all 也不显示范围切换且请求保持 scope=own。
  • 运行前端 typecheck/build、聚焦 Playwright、task/governance、流程/文档、敏感扫描和 git diff --check;部署另行批准。

6.8 移动范围生产发布

  • 将 20b20b1 和 8b376f4 推送后,以 SYNC_ENV=0 部署 8b376f4;未覆盖生产 .env,无待执行 migration,/ready、external/runtime smoke 与公网扫描通过。
  • 如实记录三次本地发布入口尝试:第一次因临时日志清理命令被本地安全护栏在进程启动前拒绝;第二次在来源校验阶段因未跟踪 portfolio review 导致 dirty worktree 停止;两次均未同步或改变生产。仅临时 stash 该目录后第三次发布成功,随后按 stash 标识原样恢复且未纳入提交。
  • 公网 /ready 为 8b376f413585,活动 server 中唯一移动报销 chunk 包含 mobile-reimbursements-scope-all 标识。
  • 复用既有 unit 合同参数与运行时间刷新 automatic backup 三项和 WARCH3;4 个 service 均匹配 8b376f4,4 个 timer 均 enabled/active。
  • 手工触发 automatic backup daily 与源端 watchdog,二者均为 success/0;未执行真实审批、财务审核、付款批次或付款写入。
  • 用户已用自己的企微管理员账号进入“报销 → 审批中 → 全部”,打开当前真实报销并确认能够查看材料;本项只记录查看验收,不代表主管审批或财务链路已完成。

6.9 报销明细与材料 KISS 对齐

  • PC 与移动端按 linkedItemId 在每条费用明细内展示关联发票摘要,并复用当前安全预览动作;未关联发票不归入明细。
  • 将原发票区和附件区收敛为单一“报销材料”区,显示分类计数,全部材料信息行可点击预览且不再重复显示“查看原件”按钮。
  • 保留草稿编辑态的添加/移除发票与上传/删除附件,不改后端合同、对象授权、审计、签名 URL、企微 JS-SDK 或审批状态机。
  • 更新聚焦 Playwright,覆盖关联/未关联发票、统一计数、PC/企微预览、编辑态动作、44px 触控目标和移动横屏无溢出;前端 typecheck/build 与 Trellis 质量门禁通过。
  • 用户明确批准后推送并部署生产;真人业务验收仍由用户在企微刷新后执行。

6.10 明细/材料 KISS 生产发布

  • 推送 665dcab 与 0e44aa7,从干净的已发布提交快照以 SYNC_ENV=0 部署 0e44aa7;不触碰未跟踪 portfolio review,不同步生产 .env。
  • 发布脚本的来源、环境合同、init、migration、/ready、external/runtime smoke 和公网资源扫描通过;公网构建标识为 0e44aa72f3f5,活动资源包含 PC/移动统一材料区标识。
  • 复用现有 unit 参数和运行时间刷新 automatic backup 三项与 WARCH3;4 个 service 构建身份一致,4 个 timer 均 enabled/active。
  • 手工触发 automatic backup daily 和源端 watchdog,二者均为 success/0;未执行真实审批、财务审核、付款批次或付款写入。
  • 用户验收后修正方向:不需要在费用明细内查看关联发票;现有逐份材料行仍然繁琐,需要一次进入连续查看全部材料。该反馈覆盖 6.9 的内联发票展示合同,已部署事实保留但不再作为目标体验。

6.11 票种摘要与整单材料预览

  • 只读核查生产真实报销:绑定票据 3 张,均为 bound、腾讯 OCR 已实际执行且无存储错误;号码/日期/金额完整。票种为 2 张电子火车票和 1 张数电发票,传统代码均不适用,火车票销售方字段不适用;未输出号码、金额、主体、文件名、UUID 或原始 OCR 结果。
  • 核查企微 SDK 合同:previewFile 仅接受单个 url/name/size;只有图片接口 previewImage 接受 urls[]。当前真实材料为 3 份 PDF 发票和 3 份 PNG 补充附件,总源文件小于 1 MiB,适合逐份 PDF 栅格化后组成有序图片包验证连续预览。
  • 用户批准采用服务端 PDF 栅格化 + 企微 previewImage,其余按统一材料入口、票种摘要和原件降级方案实施;不采用合并 PDF 或 PDF.js。
  • 删除 PC/移动费用明细中的关联发票 UI 和对应旧断言,保留后端 linkedItemId。
  • 报销详情 API 增加安全票种分类映射;共享票据格式化按普通增值税、数电发票和电子火车票显示适用字段,不重跑或改写当前真实 OCR 数据。
  • 在运行镜像加入固定 Poppler 工具,结合既有 sharp 实现有界、短时、对象授权的报销级图片预览 grant;企微一次 previewImage 原生滑动,PC/普通浏览器连续浏览,失败展开逐份原件预览降级。
  • 更新后端路由/授权/审计/超限/缓存失效测试与 PC/企微 Playwright;运行 Prisma validate、server 聚焦测试与全量基线、client typecheck/build、Trellis/governance/process/docs/sensitive/diff 门禁。
  • 稳定合同验收后再反向更新 reimbursement-invoice-ocr.md 与 wecom-boundary.md,覆盖当前“明细内发票、无聚合接口”的旧规范;提交、推送、生产部署和真实材料查看分别遵守既有批准门禁。

6.12 整单材料预览生产发布

  • 提交并推送 8a9279e,以 SYNC_ENV=0 发布;未覆盖生产 .env,未修改权限、审批状态机或任何真实业务数据。
  • 如实记录发布过程:首次从历史 Compose working-dir 标签解析路径,在同步前因普通用户权限停止,生产未变;一次临时 clone 长时间无进展后主动中止,未进入 deploy;一次后台日志方案在进程启动前被本地安全护栏拒绝,未改变生产。
  • 一次本地长构建连接被中断,但远程构建继续完成;当时仅源码已同步、活动容器未切换。最终复跑复用已完成的构建缓存并全流程成功。
  • 发布来源、环境合同、Compose/init、62 个 migration、external/runtime smoke 与公网资源扫描通过;公网 /ready 与活动容器均为 8a9279e,容器内 pdftoppm 可用,未认证材料包接口返回 401。
  • 发布后发现 automatic backup 三项与 WARCH3 的 unit 仍为旧构建身份;只读复用现有 unit 参数与运行时间重装后,4 个 service 全部匹配 8a9279e,4 个 timer 均 enabled/active。
  • 手工触发 automatic backup daily 与源端 watchdog,二者均为 success/0;未执行真实审批、财务审核、付款批次、银行回单或付款写入。
  • 构建耗时主要来自首次加入 Poppler 系统包后的基础层失效:系统依赖安装及 client/server/init 重新构建;migration 无待执行项,不是本次耗时主因。

6.13 生产真机验收缺口修正

  • 将移动端“查看全部材料”从报销明细区移到报销材料区;PC 保持现有正确位置。
  • 用 pdf-lib 实现确定性合并 PDF:显式排序、全部 PDF 页、图片各一页、固定元数据/保存选项、集合哈希缓存;不使用 ignoreEncryption。
  • 用 Node worker_threads 受限执行合并并设置材料数、源字节、页数、图片像素、输出大小和超时;不启用 Compose worker profile。
  • 将材料 bundle 签发改为单一 PDF URL + 准确 name/size,企微一次 previewFile、PC 浏览器原生预览;缓存缺失、加密/损坏/超限时整包失败并展开逐份原件。
  • 删除旧图片页 GET、共享图片浏览页和 previewImage 主路径;确认无其他用途后移除 Poppler 镜像依赖。
  • 新增报销差旅事由/地点/开始/结束四个 nullable 列和加法迁移,更新 PATCH/GET/submit 合同,不回填或改写审批中真实单。
  • PC/移动差旅单在首部概况与明细之间显示轻量差旅概要;草稿/驳回可编辑,审批中只读,历史单只用说明/明细日期降级且不猜地点。
  • 后端聚焦测试覆盖字节确定性、显式顺序、页数、准确 size、缓存缺失、加密/损坏回退、全部上限、差旅字段验证与非差旅不误拦截;前端 Playwright 覆盖按钮位置、加载文案、企微 previewFile、PC 打开和概要。
  • 运行 Prisma validate、新建空库 migration、server 聚焦/全量、client typecheck/build、无业务 25 页合并探针、Trellis/governance/process/docs/sensitive/diff 门禁。
  • 只读 review 迁移、提交门禁、短时合并件权限与审计。
  • 实现提交、推送和生产部署均已分别取得批准并完成。
  • 企微真机用当前真实报销验证合并 PDF 可打开、全部页可连续查看且返回详情正常;该人工结果不由自动化或发布 smoke 代替。

6.14 合并 PDF 与差旅概要生产发布

  • 实现提交 da35591 已推送到 origin/main;从该提交的干净临时 clone 执行标准 deploy/trialrun/deploy.sh,固定 SYNC_ENV=0、DEPLOY_DATA_MODE=existing,未触碰未跟踪的 portfolio review,也未同步生产 .env。
  • 如实记录第一次本地发布入口尝试:命令末尾包含临时 clone 清理动作,被本地安全护栏在进程启动前拒绝;未连接生产、未同步文件、生产没有变化。去掉清理动作后第二次发布全流程成功,完成验证后再校验临时目录前缀和提交身份并删除该临时 clone。
  • 发布来源校验确认 da35591 已进入远端;环境合同、Compose 预检、init 和 migration deploy 通过。63 个 migration 中新增 20260801120000_reimbursement_travel_summary 成功应用,schema 随后为 up to date;迁移只增加四个 nullable 列。
  • /ready、external deps smoke、runtime smoke 和公网前端资源扫描通过;公网 12 位构建标识与容器完整 SHA 分别匹配 da35591。构建仍报告既有 npm 风险基线:client 18 个风险(10 high),server 23 个风险(10 high、2 critical);本轮未执行自动升级。
  • 发布后只读验证目标 server 可加载 pdf-lib,且 pdftoppm 已从运行镜像移除;未认证材料合并签发和带无效 token 的取件请求均保持 401/403 边界。
  • 发布后首轮独立 /ready 复核误把公网 12 位前端标识按完整 40 位后端 SHA 断言,检查在只读响应处停止;未执行后续动作或改变生产。按既有“公网 12 位 + 容器完整 SHA”合同修正后复核通过。
  • 复用既有 unit 内的受控合同参数重装 automatic backup 三项与 WARCH3;4 个 service 构建身份均匹配 da35591,4 个 timer 均 enabled/active。手工触发 automatic backup daily 和源端 watchdog,结果均为 success/0。
  • 本次发布未修改真实报销状态、审批任务、权限、付款批次、银行回单或业务材料;企微真机合并 PDF 体验和真实报销后半链继续由对应真人验收。

6.15 首笔历史差旅概要受控补录

  • 写入前只读锁定唯一目标:当前真实报销仍为审批中、当前审批任务尚未处理、四个差旅概要字段均为空;5 条 travel 明细中只有 1 条出发火车票日期早于申请人确认的实际行程,且正确日期已由业务方明确确认。
  • 以单一 Serializable 数据库事务补录用户确认的事由、地点和起止日期,并只把上述唯一错误火车票明细日期改为确认后的实际乘车日期;未改金额、费用类型、说明、票据、附件、审批状态、工作流实例或待办。
  • 同事务新增 1 条管理员代录审计,只记录“字段于提交后上线、原提交未采集、业务方确认后代录”的原因、被修正字段名和受控 task 标识;未把真实事由、地点、日期、票据或原始请求写入 task 证据或审计 extra。
  • 写后只读断言通过:差旅概要四项完整、5 条 travel 明细日期全部位于确认区间、金额与 3 张发票和 3 个附件保持不变、工作流与当前待办仍为原 pending 状态、目标审计恰好新增 1 条;事务结果为 applied,未触发回滚。
  • 用户刷新当前真实报销后确认页面日期显示正确;该结果只证明日期展示,不代替差旅概要其他字段、材料列表或真实审批结果。
  • 补录不代表审批通过;马建勇仍须按业务事实完成主管审批,后续财务、付款批次、银行回单和最终复核继续遵守既有流程。

6.16 四块式详情与五阶段处理进度

  • PC 与移动端移除只读态材料列表的权限/失败条件,所有有权查看当前报销的人始终看到发票与补充附件列表;合并预览保留在列表上方。
  • 单份材料继续使用现有整行按钮和单份预览路径;只读审批人没有移除、删除或管理动作,编辑态既有动作保持不变。
  • PC/移动详情重排为“单头概况 → 费用明细 → 报销材料 → 处理进度”四块;差旅概要并入单头,关联/风险/付款/操作按数据与权限就近显示,不增加 Tab 或折叠。
  • 共享差旅概要组件在“草稿/驳回可编辑且字段不完整”时直接进入四字段填写态;完整概要保持单头内摘要 + 编辑,不新增报销类型或字段合同。
  • 后端详情新增五阶段 processingProgress,从 latest workflow snapshot/tasks/history、关联 PaymentBatchItem/batch、报销付款字段和回单计数生成;不改 schema、workflow 或 PaymentBatch 状态机。
  • 固化未来节点无姓名、共享批次措辞、maker-checker 各状态、回单次级状态、付款链接权限和三源独立缺失降级;返回中不包含批次其他单据、金额或材料。
  • PC/移动复用紧凑纵向时间轴:已完成无意见节点单行,当前/异常/有意见节点展开;不显示“第 N 步”、内部 step ID、角色码或权限码。
  • 更新后端聚焦测试与 PC/移动 Playwright,覆盖五阶段、退回/驳回、batch 状态、回单、来源缺失、未来无姓名、材料单份/合并、编辑权限、四块顺序、44px 触控和横屏无溢出。
  • 运行 Prisma validate、touched-file node --check、server 聚焦/必要全量、client typecheck/build、聚焦 Playwright、task/Trellis/process/docs/sensitive/diff 门禁;只读 review 跨 workflow/付款状态映射与权限,不让 reviewer 改代码。
  • 实现完成后分别取得提交、推送和生产部署批准;部署与公网检查已通过,未执行真实审批、付款或回单写入。

6.17 审批节点数据驱动修正

  • 移除 classifyApprovalTask + 阶段键 Map 覆盖路径;固定首尾业务阶段,中间按 workflow_tasks 的真实稳定顺序逐任务生成唯一节点,并按提交快照补齐尚未创建 task 的未来审批节点。
  • 节点标题按“可读 step name → assignee role 职责映射 → 审批”降级,过滤“步骤/节点/step + 序号”,不显示 step ID、角色码或序号。
  • workflow 整体不存在时保留主管/财务 pending 占位,实例 tasks 暂为空时按快照展示;前端 stage key 改为可扩展字符串并继续纯 map 渲染,不增加固定位置判断。
  • 新增第三个未知职责节点、两个同角色节点、未来快照尚无 task、空 task 实例单元测试,并复跑 reimbursement-workflow-progress.spec.ts 及既有四块/企微聚焦回归。
  • 重新运行后端聚焦与全量、Prisma、前端 typecheck/build、Trellis/process/docs/sensitive/diff 门禁;更新稳定审批投影规约后申请提交,随后按本轮授权推送、部署和公网检查。

验证记录:

  • 服务端聚焦 16 项通过;最终全量 171 个文件、1129 项通过,Prisma validate 与 touched route node --check 通过。
  • 前端 typecheck/生产 build 通过;Wave3 + R111 聚焦 2/2 通过,Wave3 同时覆盖 PC/移动 6 节点变长时间轴。
  • reimbursement-workflow-progress.spec.ts 首轮在临时库首次改密页停止;隔离处理种子账号后,依次暴露手工服务未启 jobs、共享 Page Object 仍等待已不展示的文件名、盲取差旅费用类型却未填概要、旧断言硬编码主管/财务五阶段四个既有测试漂移。逐项收紧测试编排与断言后,最终真实临时 PostgreSQL + server + Mock OCR 路径 1/1 通过;应用认证、OCR、差旅和 workflow 生产合同未为测试放宽。
  • workflow 实际只创建当前 task 的核查促使 DTO 继续用提交快照补齐未来 pending 审批节点;单元测试覆盖第三节点、同角色双节点、未来 snapshot-only 节点和空 tasks 实例。
  • 本轮唯一明确命名的临时测试库已关闭服务并删除;未读取或写入生产业务数据,未执行真实审批、付款或回单。

6.18 四块式详情与动态审批节点生产发布

  • 将 de2edd6 至 7bd80ef 共 6 个已验证提交推送到 origin/main,从远端 main 的干净 clone 发布 7bd80ef4f464;当前工作区未跟踪的 portfolio review task 未进入发布来源。
  • 以活动 systemd unit 和容器只读解析既有部署、Compose 与数据目录合同,固定 SYNC_ENV=0、DEPLOY_DATA_MODE=existing;未同步生产 .env,未变更数据挂载、Compose 项目、worker/minio profile 或生产业务数据。
  • 如实记录发布前尝试:第一次包装命令因含临时目录删除而被本地安全护栏在进程启动前拒绝;第二次从 Compose working-dir 标签推断 env 文件失败;第三次干净 clone 被切成 detached HEAD,来源门禁报 upstream_missing。三次均在 rsync 前停止,生产未变化;第四次保持 main upstream 后全流程成功,未使用未发布 override。
  • 环境合同、远端 Compose 预检、init、migration deploy 与 schema status 通过;现有 63 个 migration 无待执行项。/ready、external deps、runtime smoke 和公网 93 个前端资源扫描通过,公网 12 位标识与活动容器完整 SHA 均匹配目标提交。
  • 独立复核按层校正断言:第一次误从 /ready 顶层读取构建标识,第二次误在前端 bundle 查找由服务端 DTO 生成的批次文案,均为只读检查脚本漂移且未改变生产。修正后公网 bundle 命中“处理进度/报销材料”,活动 server 源码命中共享批次职责文案,未认证材料合并签发保持 401。
  • 运行镜像确认旧 PDF 栅格化依赖已移除:pdftoppm 不存在,未安装 pdfjs-dist;合并主路径所需 pdf-lib 与项目既有 sharp 均可加载。构建耗时主要来自 client/server 的 npm ci 依赖层重装,前端 Vite 构建本身约十余秒;依赖升级和缓存优化不在本次发布窗口顺手处理。
  • 复用既有 unit 的受控参数和运行时间刷新 automatic backup 三项与 WARCH3;4 个 service 构建身份均匹配 7bd80ef,4 个 timer 均 enabled/active。手工触发 automatic backup daily 和源端 watchdog,结果均为 success/0。
  • 用户确认马建勇在企微真机刷新后已能正常使用本轮页面;该结果只关闭四块式详情、材料查看与动态处理进度的真机可用性验收,不代表主管审批已经完成。真实主管审批、财务复核、付款批次、银行回单和最终复核仍未完成,task 保持 in_progress。

7. 完成条件

  • PRD 全部验收项有脱敏证据或明确由用户完成的真实业务验收结果。
  • 本任务未导入杨俊和两个既有测试成员之外的其他成员、未创建法体、未补银行资料;唯一测试业务数据已按受控生命周期清理/归档。
  • 若只完成系统就绪而真实报销尚未提交,任务保持未完成并明确剩余用户操作,不用合成测试替代。
  • 完成后归档本任务;后续按“财务与低频台账后台 + 核心流程真实采用”定位处理真实报销摩擦,不再返回已失效的 R63–R66 扩建排期,也不从本任务继续长出新的运维加固范围。

8. 已完成的脱敏证据

  • timer:4 个 service 构建合同一致,4 个 timer 均 enabled/active。
  • 备份:源端真实批次 success/0,ARM 独立 dead-man success/0。
  • 通讯录 dry-run:输入 1、active 1、缺手机号 1、incomplete 0、计划创建 1、冲突/跳过/失败 0。
  • 通讯录 apply:创建 1、成功 1、冲突/跳过/失败 0;角色严格为 employee,企微绑定唯一。
  • 主管接口:状态 200、更新 1、SYSTEM_USERS_BATCH_SET_MANAGER 审计新增 1;企微外部写入 0。
  • 主数据:active 费用类型 37,active 报销工作流定义 1。
  • 本地回归:5 个测试文件、61 项测试通过;Prisma schema 校验通过。
  • 公网检查:/ready 为 ok、构建标识匹配,首页 HTTP 200。
  • 只读 review:本轮只写 OA 员工、身份绑定和 OA 主管关系;未修改角色矩阵、workflow 代码、状态机、数据库 schema 或企微成员资料。
  • 测试账号受控闭环:dry-run/apply 2/2、最小角色和主管关系通过;普通浏览器双账号登录、首次改密、0.01 元测试报销、合成 PDF 上传、提交、主管退回、草稿删除、票据归档均通过;最终 OA 测试账号 archived 2、活动会话 0、企微同步 skipped 2、测试报销与 pending 待办均为 0。
  • finding:生产 OCR 为 mock 且真实腾讯 OCR 未配置,合成 PDF 自动生成 Mock 字段;草稿删除后页面导航前产生已删除详情/precheck 的 404 控制台噪声。前者阻断杨俊真实票据上传,后者不阻断业务。
  • OCR off 复验:配置切换后未改构建;三次有业务写入的复验/诊断均按“退回 → 删除 → 归档 → 停用”收口。累计 4 张合成测试票据(含第一轮)均已归档,未归档 0;测试报销与 pending 待办均为 0。
  • OCR off 结论:空发票业务字段可以绑定并提交,主管退回成功;真实使用暂由财务查看 PDF 原件并人工核对。文件 SHA-256 查重仍有效,发票号查重暂不可用。
  • 真实首跑复核:三名参与人 active 且企微绑定唯一,但企微首登均未发生;费用标准 0、适用预算池 0、active 法体 0,法体不阻断当前报销。历史 mock 票据仅 1 张且为测试账号上传,非测试员工为 0。
  • 审批规则 finding:[0,500) 可由马建勇和唯一 finance 王芝玲处理;[500,5000) 与 [5000,+∞) 均以 finance_mgr 收尾,但 active finance_mgr=0,达到 500 元会形成无人处理待办。未修正规则前不得笼统通知杨俊可提交。
  • 审批规则收口:写入前报销 reviewing/工作流 pending/待办 pending 均为 0;备份 watchdog 与 ARM dead-man 均为 success。正式接口更新 3 次、审计新增 3,生产仅剩 1 条 [0,+∞) active 规则。
  • 金额边界验证:实际工作流构造函数对 499.99、500、5000 均输出 department_manager → finance;直属主管解析到马建勇,active finance 唯一且由王芝玲承担。写后仍无报销、实例或待办新增,公网 ready 正常、构建标识未变化。
  • 真实报销生产只读核验:杨俊最新真实报销为 reviewing,工作流为 pending,当前唯一待办为主管审批且已指派主管;付款批次 0。未输出金额、单号、UUID、附件或原始 payload,未执行生产写入。
  • 真实验收 finding:主管能进入审批任务详情,但该页只有报销摘要,没有费用明细、发票、附件或完整报销单入口;因此尚未按业务事实审批。
  • 审批详情入口本地实现:移动任务详情新增“查看完整报销单”,复用移动报销详情和 state.from;PC 任务详情新增“查看报销单”。未修改后端、权限矩阵、审批状态机或列表卡片点击行为。
  • 首次聚焦 Playwright 运行因本地前端服务未启动,9 个用例均在 /login 前以 ERR_CONNECTION_REFUSED 失败,未执行到功能断言;启动 Vite 后改为只跑本次相关用例。
  • 移动聚焦用例首次进入/返回链路通过,随后因固定在 2026-05 的“已处理”测试数据超过页面最近 30 天窗口而失败;已把完成时间改为运行时近期时间,避免日历漂移。
  • 最终本地验证:npm run typecheck 通过,npm run build 通过;移动审批入口聚焦 Playwright 1/1 通过,PC 审批入口聚焦 Playwright 1/1 通过。
  • 交付门禁:当前 task validate、Trellis governance、process contract、敏感扫描和 git diff --check 均通过;文档注册审计为 0 error、1 条既有未注册文档汇总 warning。
  • 生产发布:d2841b166dc0 已部署,迁移无待执行项,发布脚本的 /ready、外部依赖、运行时和公网资源扫描通过;生产 .env 未同步。
  • 发布后运维身份:automatic backup 三项与 WARCH3 共 4 个 service 均匹配活动构建,4 个 timer 均 enabled/active;新 automatic backup daily 和源端 watchdog 均为 success/0。
  • ARM 证据边界:新批次已由 receiver 校验并 finalize;ARM dead-man timer enabled/active、最近自动结果 success/0,但本次没有扩大 sudo 权限来即时手工复跑独立 dead-man。
  • 公网入口:生产移动资源存在“查看完整报销单”,PC 资源存在“查看报销单”;只验证静态发布资源和构建身份,不读取真实报销数据。
  • 报销详情时区:共享日期时间格式化固定 Asia/Shanghai;聚焦 Playwright 将浏览器强制设为洛杉矶后,合成 UTC 附件与审批时间仍分别显示为上海 17:10、17:05,1/1 通过。
  • KISS 视觉复核:PC 与移动合成截图确认重复概况、状态、教学和空辅助区已收敛;未读取生产真实报销。Wave3 移动整段 1/1 通过;PC 大用例先通过本轮报销/审批断言,随后在未改动的合同页因找不到“筛选”按钮超时,因此不把该大用例记录为全绿。
  • 编辑态回归:R111 移动发票/附件能力 1/1 通过;PC 首轮因旧断言仍要求空“预算与审核提示”显示而失败,按新合同更新断言后,PC 发票与附件流程 1/1 通过。
  • 本地质量门禁:前端 typecheck/build 通过;task validate、Trellis governance、process contract、敏感扫描和 git diff --check 通过;文档审计 0 error、1 条既有未注册文档汇总 warning。
  • 企微旧包诊断:真机截图中的报销日期与已部署按钮属于同一个无额外条件的 JSX 块;公网 /ready 为部署构建且当前移动 chunk 包含入口文案,因此排除权限、报销关联缺失和未进入详情,结论为存活 WebView 旧包。
  • 旧包刷新护栏:页面回到前台时用 /ready 与前端构建标识做一次 no-store 比对;不一致只提示用户刷新,点击后清理 PWA 缓存并重载,同一生命周期不重复提示;一致、unknown/development、异常响应和网络失败静默。
  • 刷新护栏回归:mismatch/match/failure 聚焦 Playwright 3/3 通过,完整 login/portal UX 15/15 通过,typecheck/build 通过;375px 竖屏与 667×375 横屏无水平溢出,刷新按钮高度 44px。手机专项首次因测试在 React 壳监听器挂载前人工触发事件而失败,等待移动工作台渲染后复跑通过;未改生产或真实业务数据。
  • 原生预览调研:官方 previewFile JSAPI 与腾讯维护的 @wecom/jssdk 均确认支持企微 iOS/Android;普通 PDF 链接“只下载”不等于原生 JSAPI 不支持预览。原生调用必须提供可直接取件的短时 URL、带扩展名文件名和准确字节数。
  • 原生预览实现:服务端新增同源 JS-SDK 签名、发票元数据和附件 120 秒以内对象授权;客户端只在企微 WebView 动态加载 SDK。PC 发票使用短时 URL,PC 附件保留认证 Blob;移动发票/附件统一显示“查看原件”。未修改角色矩阵、workflow、数据库 schema 或真实业务数据。
  • 短时授权只读 review:grant 绑定用途、报销、附件、actor 与过期时间;签发前检查当前对象权限和下载理由,实际取件审计失败时不发送文件。review 发现附件 GET 初版会在普通未认证请求前查询对象,已改为无 grant 先认证、有 grant 先验签再查对象,并用回归固定 401/403 前置拒绝。
  • 原生预览回归:最终后端聚焦 3 个文件、46 项通过;服务端全量基线 169 个文件、1101 项通过;Prisma validate、touched server node --check、前端 typecheck/build 通过。聚焦 Playwright PC/企微 2/2 通过,mock bridge 收到准确 URL/name/size,企微路径未调用 window.open。
  • 原生预览治理:task validate、Trellis governance、process contract、敏感扫描与 git diff --check 通过;文档审计 0 error、1 个既有注册汇总 warning。稳定例外已写入 wecom-boundary、security-privacy 与 reimbursement-invoice-ocr spec。本步骤未部署生产,真机和真实材料验收仍待单独批准。
  • 原生预览生产发布:410d8cd71b1f 已部署,SYNC_ENV=0,62 个 migration 无待执行项;/ready、external deps、runtime smoke 与公网 bundle 扫描通过,未登录 JS-SDK 签名请求为 401。第一次尝试在同步前因示例目录权限失败且生产未变化,第二次通过活动 Compose 标签解析实际发布根目录并复用既有受控 root 运维入口成功。
  • 本次发布后运维身份:automatic backup 三项与 WARCH3 共 4 个 service 均匹配 410d8cd,4 个 timer 均 enabled/active;新 automatic backup daily 与源端 watchdog 均为 success/0。
  • 新增 finding:镜像构建审计为 client 18 个风险(10 high)、server 32 个风险(20 high、2 critical),未执行自动修复;既有部署 smoke 还会输出不必要的配置标识和测试管理员联系方式,后续需分别建立依赖升级回归和证据最小化收敛项。
  • 外部验收边界:生产已部署但企微真机中的无业务 PDF 原生预览、马建勇对真实发票与附件的可见性仍待人工验收;在材料真实可见前不得完成主管审批。
  • 移动范围对齐:管理员移动报销页新增“我的 / 全部”,默认 own,选择“全部”后请求现有 scope=all 并把 status/scope 带入详情回跳来源;普通员工即使 URL 带 scope=all 仍请求 own 且看不到切换。首轮 Playwright 因未显式指定本地 Vite 地址而在登录前连接失败;指定 E2E_BASE_URL 后功能执行,首次严格 44px 断言测得浏览器子像素值略低于 44,控件提升为 48px 后最终聚焦 2/2、同文件完整回归 5/5 通过。375px 竖屏和 667×375 横屏无横向溢出,typecheck/build 通过。
  • 移动范围生产发布:20b20b1 与 8b376f4 已推送,8b376f413585 以 SYNC_ENV=0 部署;无待执行 migration,公网 ready、external/runtime smoke、公网扫描和活动移动 chunk 标识通过。第一次本地命令在进程启动前被安全护栏拒绝,第二次因 portfolio review 令来源校验在同步前停止;临时 stash 后第三次成功,目录已原样恢复。4 个 service 构建身份匹配、4 个 timer enabled/active,新 daily 与 watchdog 均为 success/0。企微管理员真机的“全部”列表及发票/附件原生预览仍待用户验收。
  • 真实材料查看验收:用户随后确认已能从自己的企微管理员账号找到当前真实报销并查看材料;该确认只关闭查看阻断,不代表主管审批、财务审核、付款批次或最终复核已经完成。
  • 明细/材料 KISS 实现:PC 与移动端按 linkedItemId 在费用明细内显示可预览发票,未关联发票只留在统一“报销材料”区;材料区显示类型计数并以整行作为预览入口,后台类型、权限、审计、短时 URL 和企微 previewFile 均未改变。
  • 聚焦 Playwright 首轮因本地前端服务未启动,PC/移动 2 项均在 /login 前 ERR_CONNECTION_REFUSED,未进入功能断言。启动 Vite 并指定 E2E_BASE_URL 后,两端首次都因旧测试仍假设销售方文本唯一而触发 strict-mode failure;这是新界面同时在关联明细和材料区展示同一发票摘要后的断言漂移,改为按区域断言。
  • 下一轮 PC 通过,移动在“添加附件”后因测试仍从旧附件子区查找已移到统一材料区的隐藏 file input,等待至用例超时;页面快照确认实现已渲染且未发生业务错误。测试改为从材料区定位上传控件后,移动单项通过。
  • 最终本地验证:生产 build(含 typecheck)通过;R111 PC/企微双端与 Wave3 只读时区/KISS 聚焦回归 3/3 通过,企微 previewFile 参数、PC 打开 URL、关联/未关联发票、材料计数、无逐文件“查看原件”按钮、44px 触控目标和 667×375 横屏无溢出均有合成断言。
  • 最终治理:task validate、Trellis governance、process contract、敏感扫描与 git diff --check 通过;文档审计为 0 error、1 条既有汇总 warning(22 个历史未登记文件)。稳定展示合同已写入 reimbursement-invoice-ocr spec;未部署、未读取或写入真实业务数据。
  • 明细/材料生产发布:665dcab 与 0e44aa7 已推送,0e44aa72f3f5 以 SYNC_ENV=0 部署;无待执行 migration,schema、/ready、external/runtime smoke 与公网资源扫描通过,公网递归扫描 91 个 JS 资源并在 2 个活动资源中命中统一材料区标识。
  • 本次发布第一次本地命令因包含临时目录递归清理,被安全护栏在进程启动前拒绝,未生成快照、未连接或改变生产。第二次移除清理动作后,从干净 clone 发布成功;发布后按提交标识和受限临时目录模式删除本轮唯一快照,未保留构建日志。
  • 发布后运维对齐:只读检查先发现 automatic backup 三项与 WARCH3 均仍为旧构建身份;复用现有 unit 参数和运行时间刷新后,4 个 service 匹配 0e44aa7、4 个 timer enabled/active。新 automatic backup daily 与源端 watchdog 均为 success/0。
  • 本轮未同步生产 .env,未修改权限、审批状态机、企微认证或业务数据,未执行真实审批、财务审核、付款批次、银行回单或付款动作;真人企微 KISS 页面验收仍待用户刷新确认。
  • 整单材料实现:PC/移动费用明细不再渲染关联发票;只读态以一个“查看全部材料”入口生成有序图片包,企微调用一次 previewImage,PC 使用共享材料页连续显示;编辑态和失败降级仍保留逐份原件管理/查看能力。
  • 票种显示回归:合成数电发票与电子火车票分别显示正确票种;数电发票保留销售方,火车票使用购买方且不再出现“无代码 / 未识别销售方”;未重跑或改写生产 OCR 数据。
  • 后端验证:聚焦 5 个测试文件、23 项通过;服务端全量 171 个文件、1109 项通过,Prisma validate 与 touched-file node --check 通过。新增断言覆盖顺序、页/源/输出/缓存上限、token 篡改、缓存缺失、下载理由、访问审计失败和安全票种映射。
  • 前端验证:生产 build(含 typecheck)通过;R111 PC/企微 2/2 通过,覆盖费用明细无发票入口、票种文案、统一计数、材料页与一次有序 previewImage.urls 调用。
  • 目标镜像验证:server_build 成功安装 poppler-utils;Playwright 生成的无业务合成单页 PDF 经容器内生产 reimbursementMaterialPreview 转换为 1 页 PNG,探针结果为 raster-probe-pass。未合并、改写或使用真实票据。
  • 治理复核:task validate、Trellis governance、process contract、敏感扫描和 git diff --check 通过;文档审计 0 error、1 条既有汇总 warning(22 个历史未登记文件)。首次敏感扫描命令误指向不存在的旧路径并立即失败,改用当前 scripts/qa/check-sensitive-content.mjs 后 30 个变更文件、0 finding;该失败未执行生产或业务写入。
  • 本步骤只完成本地实现与验证;未推送、未部署、未修改生产配置或真实业务数据,不能据此通知真人线上测试。
  • 整单材料生产发布:8a9279efceee 已部署,SYNC_ENV=0,62 个 migration 无待执行项;/ready、external/runtime smoke、公网扫描与未登录 401 边界通过,目标容器内 pdftoppm 可用。
  • 本次长构建主要是 Poppler 首次进入生产基础层后引起系统包安装和 client/server/init 缓存失效;首轮路径权限、无进展 clone、启动前安全护栏拒绝和本地连接中断均已如实记录,未美化为一次成功。
  • 合并 PDF 本地实现:材料按发票/附件各自 created_at,id 显式排序,集合哈希纳入缓存键;pdf-lib 复制全部 PDF 页,Sharp 仅处理图片,固定 PDF 元数据与保存选项,相同输入两次生成字节完全一致。
  • Worker/边界验证:Node worker_threads 成功合并 25 页无业务 PDF 且页数完整;加密 PDF 和损坏 PDF 均整包失败,未使用 ignoreEncryption,未启用 Compose worker profile;同集合并发请求只生成一次。
  • 签发与审计验证:接口只返回一个短时 PDF URL、名称、精确字节数和页数;GET 复核 content-length 与响应字节一致,token 篡改、缓存缺失和访问审计失败均在发送字节前拒绝。
  • 前端回归:R111 PC/企微双端 2/2 通过;移动入口只在报销材料区,PC 只打开一个 PDF URL,企微只调用一次 previewFile 且 URL/name/size 精确;PC/移动均显示合成差旅概要。
  • 数据合同验证:Prisma schema 通过;63 个 migration 在临时空 PostgreSQL 16 数据库完整 apply;新迁移只增加四个 nullable 差旅概要列,未回填或改写真实审批中数据。
  • 最终质量:server 全量 171 个文件、1114 项通过;client typecheck/生产 build 通过;task、Trellis governance、process contract、敏感扫描和 git diff --check 通过。文档审计 0 error、1 条既有汇总 warning(22 个历史未登记文件)。
  • 发布后运维对齐:automatic backup 三项与 WARCH3 共 4 个 service 均匹配 8a9279e,4 个 timer 均 enabled/active;新 automatic backup daily 与源端 watchdog 均为 success/0。
  • 四块式详情实现:PC/移动均收敛为“单头概况 → 报销明细 → 报销材料 → 处理进度”;差旅概要、关联事项和真实风险并入单头,材料列表对只读审批人常显,单份与合并预览沿用既有权限和审计路径。
  • 五阶段只读投影:详情 API 固定返回申请提交、主管审批、财务复核、付款批次复核、付款与回单;付款批次未创建时可明确显示“待财务创建付款批次”,未来处理人不预填,普通申请人不获得批次跳转或批次其他业务信息。
  • 五阶段验证:后端最新聚焦 12 项覆盖草稿、审批中、退回/驳回、批次 draft/reviewed/executed/failed/cancelled、回单有无、无批次历史付款和批次链接权限;服务端全量基线 171 个文件、1123 项通过。Prisma validate 与 touched route node --check 通过。
  • 双端验证:client typecheck/生产 build 通过;R111 PC/企微 2/2、Wave3 只读详情 1/1 及移动视觉聚焦 2/2 通过,覆盖材料常显、只读无删除、四块顺序、五阶段无“第 N 步”、44px 触控和无横向溢出。视觉复核确认 PC 主内容不再因空侧栏过窄。
  • 只读 review:按 workflow task、PaymentBatchItem/batch、回单计数三源逐项复核映射与权限;修正“workflow 已通过但尚未建批次”原本无当前节点的问题,使其明确落在“待财务创建付款批次”。确认未来 checker 不预填、普通申请人无批次链接、共享批次不暴露其他单据/金额/材料;review 未修改状态机、权限矩阵或生产数据。
  • 最终治理:task validate、Trellis governance、process contract、敏感扫描和 git diff --check 通过;文档审计 0 error、1 条既有汇总 warning(22 个历史未登记文件)。本步骤未部署、未推送、未修改生产配置、真实报销状态、付款批次、回单或业务数据。
  • PC/移动 UX 最小收口:PC 从带 status/page/scope 的报销列表进入审批任务后可返回同一查询,从审批任务进入报销详情后显示“返回审批详情”,直接打开详情显示“返回报销列表”;业务动作区不再重复列表入口。共享 formatMoney 统一总额、明细、发票和标准提示为人民币两位小数;移动底栏只保留“提交审批”,材料区继续保留“添加发票”。
  • UX 聚焦验证:Wave3 返回/金额/视觉相关 5 项通过,R111 PC/企微材料相关 2 项通过;typecheck 与生产 build 通过,截图确认 PC 返回位于标题上方、移动底栏为单一主按钮。旧 R5 综合移动用例 2 项在进入报销详情前因采集器仍查 approvals/reimbursements/me 等旧 key 而只识别出 2 个入口;页面对该经理角色实际仍渲染“新建报销、上传票据、请假记录、采购”4 项,上一轮“实际为 2 个”的表述已在本轮勘误。
  • R5 门禁收口:测试从常用动作宫格动态采集入口,但固定断言经理角色的 4 项 key/标签集合,并保留双设备 44px、单行、SVG、边界和无重叠检查;详情返回按当前统一详情壳断言为按钮。R5 单跑 2/2 通过,并登记到 route-manifest.json 的 acceptanceSpecs。
  • 候选门禁修复:run-local-candidate.sh list 首轮暴露隔离夹具漏建普通 bash child-script,修正为按命令行同时发现 bash 与 bash -n 子脚本;focused 首轮随后揭示 Wave3 合同页在 Radix 菜单仍打开时等待背景“筛选”按钮至 300 秒超时,改为先完成页面操作、最后验证“更多/导出 CSV”。最终本地候选 50 项、10 个核心 witness 全通过,0 failed、0 skipped、0 unexpected,状态为 FOCUSED_BROWSER_PASS。
  • 门禁治理复验:QA Node 测试 52/52 通过;flow coverage 将 acceptance spec 从 7 项增至 8 项,8/8 有效且 0 blocking gap;前端最终 typecheck 与生产 build 明确 exit=0,PWA 产物生成完成。
  • UX 治理:task validate、Trellis governance、process contract、敏感扫描与 git diff --check 通过;文档审计 0 error、1 条既有未注册文档汇总 warning。稳定的 PC 单层来源返回、共享人民币展示及 acceptance spec 必须接入真实门禁的合同已写入 frontend-react-vite-design spec。本步骤未部署、未推送、未修改生产配置或真实业务数据。
  • 5dac336 生产发布事故与恢复:首次尝试把 Compose 配置目录误当仓库根目录,rsync 已把源码同步到错误嵌套位置,随后因重复拼接的 .env 路径不存在而停止;旧容器未重建且持续服务,但远端 .env 被错误同步删除。恢复只从仍运行的 server 容器按 .env.example 允许键提取,163/163 键可恢复、关键键缺失 0,原子写回后权限为 0600;未输出值或原始环境。第二次使用正确根目录发布成功并清理错误嵌套代码树,不能表述为一次成功。
  • 5dac336fbf851a4196ee6607e5705ee840dce92f 生产成功证据:63 个 migration 无待执行项;/ready、external deps、runtime smoke 和公网资源扫描通过;公网、活动容器与 4 个运维 service 构建标识匹配,4 个 timer enabled/active,automatic backup daily 与 watchdog 均为 success/0。本次未改真实报销、审批或付款数据。
  • 部署加固实现:新增既有部署包装入口,只从 automatic-backup systemd unit 读取 6 个 allowlist 参数且不回显值;远端仓库根、普通非 symlink .env、existing PGDATA 与 storage 在 mkdir/rsync 前检查。Dockerfile 把 apk add、client/server npm ci 移到 build SHA 之前;seed/smoke 不再打印完整登录标识、联系方式、企业微信标识、redirect URI 或生成凭据。
  • Docker 双 SHA 实测:第一次冷构建 server_build 通过,基础包约 124 秒、client npm ci 约 66 秒、server npm ci 约 85 秒;仅把前后端构建 SHA 改为另一组值后,三层均明确显示 CACHED,第二次约 78 秒,主要剩余前端 typecheck/Vite/PWA 构建与薄的镜像导出。第二个镜像内完整 BUILD_SHA 与前端 12 位标识均命中预期。
  • 加固验证:部署安全聚焦测试 7/7;server 全量 172 个文件、1136 项通过,退出码 0;Prisma validate、3 个 shell 语法、4 个 JS 语法、环境合同、task validate、Trellis governance、process contract、敏感扫描和 git diff --check 均通过。文档审计为 0 error、1 条既有汇总 warning(22 个历史未登记文件)。本步骤只完成本地流程加固,尚未提交、推送或部署。

9. 五人推广前的采用扩展阶段(本轮新增规划)

  1. 本地静态合同复核
    • 核对当前报销创建/提交硬门禁、resolveEntityPrecheck、权限解析、Prisma 状态枚举及历史闭环关联键。
    • 确认 people_lifecycle 不进入人员分母,法体不进入提交硬门禁;把各实体的计数口径和允许输出字段写成查询合同。
    • 为脱敏汇总增加 fail-closed 判据:预期模块/枚举缺失、字段名不匹配或异常空摘要立即失败。
  2. 申请并执行生产只读 PRE
    • 只读确认执行身份、运行 SHA、migration pending 状态、回滚窗口和数据库只读通道;保存脱敏基线。
    • 本步骤不登录真人账号、不调用业务 mutation、不修改生产配置或数据。PRE 结果交用户复核后,才申请正式 readiness 查询批准。
  3. 严格一次 readiness 与历史漏斗查询
    • 分别采集 active/可登录员工、主管覆盖及三项有效权限;active 费用类型、workflow、feature flag、票据上传/OCR 和提交阻断配置。
    • 分别按报销、票据池、workflow instance/task、付款批次、回单聚合状态,并按真实关联判断完整闭环和各停点。
    • 输出只含计数、布尔、枚举分布和脱敏结论;如需补读,明确登记为 supplemental,不改写首次执行次数。
  4. 形成 go/no-go 矩阵
    • 将缺口分为:可直接推广、推广前必须处理、只记录不阻断;法体默认属于观察项,除非现场代码合同出现新证据。
    • 任一需要账号、权限、主数据、OCR、历史状态或代码变化的处理项单独规划、单独批准。本阶段不修复。
  5. 决定真人试走是否启动
    • 仅在 readiness 结论允许且用户另行批准后,等待第二位真实员工的真实报销需求;不创建合成业务。
    • 由本人走上传票据、建单、明细、绑定、提交及后续真实审批/财务链;熟练管理员代走时标记为“真人摩擦下限”。
    • 全部摩擦记录,本轮最多处理三个;登录、认证、权限、数据安全或需生产写入的异常立即停止,不现场绕过。
  6. 本轮规划验证与停点
    • 运行 task validate、Trellis governance、process contract、docs registry audit、敏感内容扫描与 git diff --check。
    • 本轮停在规划只读复核;不得因 task 已为 in_progress 而自动执行生产 PRE、readiness 查询或真人试走。

9.1 首次生产 PRE 尝试(不完整,停止待补采批准)

  • 唯一一次生产执行已通过精确生产 origin/目录身份、运行构建与 origin/main 候选一致、migration pending=none,回滚窗口为 OPEN / terminatedRows=0 / basis=terminated_status_count。
  • readiness 聚合器在 BEGIN TRANSACTION READ ONLY 内成功退出,但本地输出校验器错误地要求运行 config.buildSha 等于 40 位候选 SHA;当前合同实际为候选的 12 位公开前缀。校验因此返回 QUERY_OUTPUT_INVALID,安全摘要没有输出或留存,员工/权限/生命周期分布均不得从本次执行推断。
  • 本次没有登录真人账号、调用业务 API mutation、修改配置或执行数据库写入;没有自动重试。校验器已按既有公开构建标识合同修正为比较 expected.slice(0, 12),后续只允许在用户明确批准后以 supplemental read 重新采集,并如实记为第二次只读查询。

9.2 Supplemental 生产只读核验与任务收口

  • 用户明确批准后于 2026-08-23 执行一次 supplemental read。生产身份、活动运行构建、migration pending=none、只读事务和回滚窗口均通过;查询执行 1 次、重试 0 次,未登录真人账号、调用业务 mutation、修改配置或写数据库。
  • 人员与权限:6 名 active 员工均具有登录标识、密码凭据和企微绑定;6 人具备 expense.submit 与 invoice.upload,4 人具备 expense.approve。3 人具有有效且不同人的 active 直属主管;杨俊与马建勇的唯一性、active、审批权限和直属关系合同全部成立。
  • 主数据与能力:38 个 active 费用类型、1 个 active 报销 workflow、1 个 active 法体观察项;票据上传已配置,生产 OCR provider 为 tencent,付款批次开关有效。发票验真开关关闭仅作为观察项,不冒充腾讯 OCR 未启用。
  • 生命周期:报销 paid=1、draft=1,其余状态为 0;报销 workflow approved=1、terminated=1,任务 completed=3 且无 pending;付款批次 executed=1、cancelled=1 且无 draft/reviewed;回单 1 份且治理状态为 approved;票据均已 archived。
  • 关联闭环查询确认 completeSubmitApprovePayReceiptLoops=1,因此杨俊差旅报销的“提交 → 审批 → 付款 → 回单”已走完,旧待办完成勘误。现存 1 条 draft 和 1 个 cancelled 批次作为历史停点保留,本轮不读取正文、不自动修复或删除。
  • 推广矩阵结论为 CONDITIONAL_GO:登录、企微绑定、提交/上传权限、主数据、OCR、workflow、付款和历史闭环均为 GO;直属主管仅覆盖适用人员中的一部分,新增真人首次提交前必须逐人核对主管关系。第二位真实员工试走仍需在真实需求出现时另行建任务,不制造测试业务。