文件
hyb-oa/docs/试运行与自动化验证手册.md
T
wangsli和Claude Opus 5.5 4a5cd8f2b3
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
借款出借人线上确认借款并以站内通知直达(09-17-company-loan-principal-repayment)
- 新增出借人确认声明:财务发起,出借人本人查看原件后确认或退回;快照与决定不可改删,金额、日期、原件或身份变化后整组失效
- 余额确认接受纸质协议或有效线上声明二选一,代账余额核对材料仍必需;声明与公司代表授权分离
- 普通员工无常驻入口,财务发起后仅通知对应出借人并直达确认页
- 新增迁移 20261010010000_loan_lender_acknowledgements(仅新增三表)
- 测试:单测、隔离 HTTP/浏览器、完整借款回归;独立只读复核无阻断;同步发布记录与操作手册

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-10 15:22:12 +08:00

424 行
34 KiB
Markdown
原始文件 Blame 文件历史

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
# 试运行与自动化验证 Runbook
**文档状态**:当前操作手册,用于本地、公网、企业微信和真实 OCR 试运行验证。
## 备份恢复验证边界
2026-09-17,`08-23-isolated-backup-restore-drill`完成一次已批准的ARM受限影子恢复:来源与生产构建同为`b1d25d3c`,数据库恢复和影子认证只读应用通过;62条附件引用中仅1条精确已接受历史缺件,未知不一致0。清理及源/生产/监控后验通过,未修改生产。
- 整体结论为`PARTIAL_KNOWN_MISSING_AND_SENSITIVE_DECRYPTION_NOT_TESTED`,不是完整灾备PASS。历史缺件未找回、不删除引用;其余引用按已有大小/摘要字段验证,不把无SHA字段的存在性检查说成全量内容校验。
- 应用证据是影子凭据经过真实认证/权限后的只读读取与恢复库比对,不是员工真实密码登录、浏览器全流程或敏感字段解密验收;生产密钥来源/保管与灾备可用性仍未证明,不索取聊天明文或擅自换密钥。
- 实测RPO为7小时2分52秒。分阶段耗时不包含完整清理/后验及切换过程,不将阶段小计称为完整RTO或SLA。
- 本次入口已消费,无需重跑。历史NO_GO与冻结包不改,当前状态按绑定review/execution/source三摘要的实际回执及task最新记录判断;后续扩大范围或再恢复需重新规划,不复用单次授权。
## 银行回单系统失败恢复
- `system_failed`、`key_failed`、`snapshot_failed`不是普通识别失败。管理员先依据安全原因码排查数据库可用性、密钥配置/版本或付款业务与银行快照;不输出账号、密钥或原始识别响应,不随意生成新密钥替换旧密钥。
- 当前没有管理员重排队接口。修复前提后,另获真实原件重传和云识别授权,由有上传权限的经办人从原批次重新上传原件;保留旧失败附件及审计,不直接SQL改状态、不删除失败证据、不批量重试。前提无法修复时停止,重上传不是修复快照或密钥的替代方案。
- 新附件重新经过安全检查、OCR、逐笔匹配、交易去重及必要的独立复核。旧失败件不单独阻止已有合格证据的登记;必须以实时readiness和登记事务结果为准,不以上传成功判断付款成功。批次已执行/取消不得借恢复入口重传重付。
- `failure_recording_failed`表示连独立失败回写也失败,不能声称失败态已落库。附件可能仍为processing,满15分钟后普通重试可能重新可用;管理员应先修复前提,不能将此例外描述为“所有系统故障绝不会重传”。重新核对按钮只刷新查询,不等于重新识别。
- 全人工录入是「原件留存 + 经办录入 + 独立人员复核」,不是机器核实内容一致,更不是银行验真或到账证明。找不到合格独立复核人时停止并由业务负责人安排,不能给通配权限或让本人自审绕过。
## 日常发布与初始化分离(本地候选,未声明已部署)
09-09-existing-deploy-seed-separation 将 init 统一为 `npm run deploy:init`:
existing 执行配置预检、迁移与只读基础配置检查,不运行 seed;initialize
额外按序执行两类 seed。模式缺失或非法就停止,不默认初始化。
批准后的正式发布仍走既有 deploy-existing.sh;受控直接 Compose init
必须显式传入模式并保留 `--no-deps`,不能以 init 名称推断允许建库。
费用类型、启用审批规则、活动报销流程任一完全缺失时,停止切换应用并报告
缺项。审批规则与流程定义由授权管理员在既有页面维护;费用类型缺失按
授权配置修复处理,不提供不存在的页面入口。不得在 existing 中自动重跑 seed。
管理员即使是有意停用全部费用类型、全部审批规则或全部报销流程,也会阻断
下次发布的配置检查;系统不会自动把它们补回来。请在另行批准的配置维护中
核实停用意图,不要为通过发布检查擅自启用配置或切到 initialize。
这三个非空检查不证明金额覆盖、审批人解析或付款资料齐全;工作区、编号、
开关和其他可选模块不强制等于初始化默认值。
迁移先于必需配置检查执行,因此检查失败时迁移可能已经落库,不能宣称
失败时零数据库写入;旧镜像回滚不能撤销数据变化。直接调用未提供模式的旧
命令将失败;提交、生产例外、部署及数据修复仍分别审批。
**当前状态(2026-07-18)**:最后有部署和公网复检证据的来源基线仍为 `df26922`;未做当前公网只读检查时,不据此断言服务器此刻仍运行该提交。`07-18-small-team-internal-readiness` 只收敛本地候选,完成上限为 `LOCAL_CANDIDATE_PASS`;它不代表已部署、可公网测试、企业微信真机通过或真实账号/数据验证。旧 7 天试运行只有 Day 1–Day 4 后中断,缺人工业务闭环和 Day 7 Go/No-Go;下一轮必须待当前可信基线部署并复核后,新建 Trellis task,从 Day 1 连续启动。正式能力继续保持 PDF-only OCR,不接真实支付、不接 ERP、不开放图片 OCR、不导入银行流水。
本文用于 hyb-oa 本地、企业微信和公网试运行。默认策略是:能自动化的先自动化,自动化无法覆盖的才请求人工配合。
测试分层、视觉验证、SKIP、状态回填和回归门禁的制度口径,以 [`docs/测试规约与回归门禁.md`](测试规约与回归门禁.md) 为准;本文只保留本地、公网、企业微信和真实 OCR 的操作步骤。
## 入口顺序
1. 读取 `.trellis/workflow.md` 和当前 Trellis task 的 PRD/设计。
2. 读取 `.trellis/spec/hyb-oa/` 与任务对应的业务事实源。
3. 读取 `AGENTS.md` 并检查 `git status --short`,保护已有改动。
4. 按任务读取事实源:
- 页面体验事实:`docs/产品设计规则.md`;视觉与交互裁决使用 `frontend-design`
- 报销发票:`docs/报销发票附件规则.md`
- Agent 交付:`docs/Agent开发交付实践.md`
5. 旧 `issues/*.csv` 只在需要历史追溯或外部导出时读取,不作为新任务执行合同。
## 本地验证
后端基础检查:
```bash
cd server && npm run prisma:validate
cd server && node --check src/routes/reimbursements.js
cd server && node --check src/routes/workflow.js
```
后端回归:
```bash
cd server && ./scripts/regression-workflow-actions.sh
cd server && ./scripts/regression-all.sh
```
若当前本地开发库存在 Prisma migration 漂移,禁止直接重置数据库。需要验证发票查重真实 HTTP 链路时,优先使用隔离临时库:
```bash
bash scripts/qa/check-local-migration-drift.sh
bash scripts/qa/run-isolated-regression-dedup.sh
```
`check-local-migration-drift.sh` 只读执行 `prisma migrate status` 并给出风险提示,不会执行 `migrate reset`。`run-isolated-regression-dedup.sh` 会创建临时 QA 数据库、执行迁移和种子、启动临时服务、运行 `server/scripts/regression-dedup.sh`,结束后默认删除临时库。若需要保留现场,可设置 `QA_KEEP_DB=1`。
前端检查:
```bash
cd client && npm run typecheck
cd client && npm run build
```
## Playwright 视觉验证
页面或交互改动优先用 Playwright 验证:
- PC viewport: 1440x960。
- mobile viewport: 基础 390x844;涉及移动布局、企业微信或 R6 移动反馈时必须扩展到 320x568、360x740、375x667、390x844、393x873、414x896、430x932。
- 企业微信 UA 使用 iPhone + `wxwork` 标识。
- 截图放在 `output/playwright/<trellis-task-id>/`。
移动端必须检查:
- 没有桌面表格。
- `scrollWidth <= viewportWidth + 2`。
- 底部导航高度合理,四个 Tab 中心点 `elementFromPoint` 命中自身或子元素。
- 当前选中项不是黑色空心样式。
- 弹窗不会默认聚焦搜索框导致键盘弹出。
- 无明显文字截断、遮挡、按钮样式不一致。
- 首页一级入口使用图标宫格时,图标、标题和容器不重叠,标题不逐字换行。
- 深层 Push 页隐藏底部 Tab,使用顶部返回;吸底主操作不遮挡内容。
- 移动验收采用“跨视口自动化 + 代表性真机确认”:自动化证明响应式基线,iPhone 12、iPhone 14、Redmi K60 或同类代表设备确认真实企业微信 WebView 行为。当前 `ME6-3` 已关闭;未来新增真机门禁若暂停,必须继续记录为 `PAUSED`,不能用自动化结果替代。
## 企业微信验证
自动化可模拟企业微信 UA,但真实登录态仍以手机企业微信为准。
需要人工配合的节点:
- 企业微信后台应用主页、可信域名、回调域名、可见范围配置。
- 手机企业微信实际点击应用入口。
- 企业微信授权或绑定确认。
真机公网测试按 [`docs/trialrun/真机公网测试清单.md`](trialrun/真机公网测试清单.md) 执行。可先生成报告模板:
```bash
node scripts/qa/create-real-device-report.mjs
```
真机验证状态允许使用:
- `PASS`:代表性真机和必要人工确认均通过。
- `FAIL`:真机复现阻断或严重问题,必须登记设备、账号、URL、步骤和证据位置。
- `BLOCKED`:缺少测试账号、企业微信后台配置、样票或网络等前置条件。
- `PAUSED`:用户或现场条件暂停验证;自动化通过也不能据此关闭真机门禁或把当前 task 验收标为完成。
### WF8 通知渠道验收矩阵
WF8 阶段采用“两渠道验收 + 邮件冻结说明”:站内通知和企业微信个人应用消息是当前正式验收通道,邮件通道按统一审批中心规约冻结,不作为当前硬门禁。任何缺少配置、账号、凭据或真机条件的渠道只能记录 `SKIP`、`BLOCKED` 或 `PAUSED`,不得写成 `PASS`。
| 渠道 | 前置条件 | 验收步骤 | 通过口径 | 不能替代的证据 |
| --- | --- | --- | --- | --- |
| 站内通知 | 测试用户、审批或业务事件、OA 登录态 | 触发待办或状态变化;目标用户进入 OA 通知或目标业务页;核对未读、标题、目标类型和目标 ID | 通知存在,deeplink 指向具体 OA 目标,权限拦截正确,非目标用户不可见 | 只跑后端单测不能替代 PC 或移动页面可达性 |
| 企业微信个人应用消息 | `IM_NOTIFIER_ENABLED=true`、个人应用消息渠道启用、员工已绑定企业微信 userId、应用可见范围正确、公网域名可访问 | 触发待办;管理员检查 delivery;审批人在手机企业微信收到消息并点击回 OA | delivery 成功且无 `invaliduser`、`unlicenseduser`、可见范围错误;手机端能进入 OA 移动审批或业务详情 | 企业微信 UA 自动化不能替代代表性真机消息接收和点击回流 |
| 邮件通道 | 用户确认邮件为正式通道、SMTP provider 和发件域确定、密钥存放和退信处理方案批准 | 当前 WF8 不执行;当前或独立 Trellis task 及对应规约记录冻结原因和解锁条件 | 当前结论为冻结或 SKIP,不参与 Go/No-Go PASS 统计 | 站内或企业微信成功不能证明邮件通道成功 |
| 失败追溯 | 通知 provider 可模拟失败或测试渠道返回失败 | 模拟发送失败;检查 `notificationDelivery` 摘要、错误类型、重试次数和管理员可见性;确认主业务不回滚 | 失败可追溯、敏感字段不外泄、业务状态保持正确 | 日志片段不能替代投递记录或管理员查询证据 |
验收结论必须区分四类环境:
- 本地自动化:用于证明通知创建、投递记录、失败重试、权限和脱敏基线。
- 公网匿名:只能证明入口、静态资源和未登录边界,不证明个人消息送达。
- 公网带凭据:用于证明真实账号、权限、deeplink 和业务目标页面可达。
- 企业微信真机:用于证明个人应用消息送达、点击回流、绑定状态和 WebView 行为。
公网 live smoke 和真实 OCR 准备按 [`docs/trialrun/公网LiveSmoke准备清单.md`](trialrun/公网LiveSmoke准备清单.md) 执行:
```bash
node scripts/qa/check-live-smoke-env.mjs
LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash scripts/qa/run-live-smoke-readiness.sh
```
### 当前可信度判定
- 聚合状态为 `PASS` 时仍必须检查必要子项和 `findingCount`;必要 live smoke、真实 OCR、权限、来源校验出现 `SKIP`、`PARTIAL`、`MISSING` 或 SHA 不匹配时,不得给出最终 clean PASS。
- 本地 runner 通过只证明当前代码;必须核对部署来源 commit、`/ready` observed build SHA 和公网 bundle marker,才能证明公网使用了同一基线。
- 新连续试运行前必须确认部署 runner 已包含 7 月 P0 修复;旧 Day 1–Day 4 报告不得补证新的正式启用结论。
### 2026-05 SYSTEM-COMPLETE-GATE 历史完成门禁
系统开发完成收口采用以下最小门禁:
```bash
set -a && source ~/.hyb-oa/live-smoke.env && set +a
LIVE_SMOKE_BASE_URL=https://oa.hyinda.com node scripts/qa/check-live-smoke-env.mjs --strict
QA_ISSUE_ID=SCG LIVE_SMOKE_BASE_URL=https://oa.hyinda.com bash scripts/qa/run-live-smoke-readiness.sh
cd client && E2E_BASE_URL=https://oa.hyinda.com npx playwright test tests/e2e/dg7-mobile-information-dedupe.spec.ts tests/e2e/r124-mobile-entry-matrix.spec.ts tests/e2e/r6-wecom-mobile-rendering-hardening.spec.ts --workers=1 --reporter=list
```
完成门禁只核验系统可正式使用,不扩展功能边界。`payment_batch_v1` 应保持 `force_on`,`erp_sync` 应保持 `force_off`。图片发票 OCR、真实支付接口、ERP 实时凭证、银行流水导入、复杂 BPM、审批设计器和重预算控制继续冻结。
### 2026-05 LAUNCH-OPS-V1 历史首周运营检查
正式使用首周每日检查:
- 公网 `/ready`、PC 登录、移动/企业微信入口。
- 报销/PDF OCR、审批、请假、采购、通知、付款批次、AP 导出和审计日志。
- `payment_batch_v1` 未意外关闭,`erp_sync` 未意外开启。
- 出纳在银行侧完成真实付款后,可将经授权的付款回单作为 OA 留存证据,再执行 OA 已付款标记;误传回单必须填写理由并留痕作废,不物理删除。银行流水不导入 OA,银行侧原始材料仍按受控财务流程交接。
- 当天问题按时间、角色、页面、步骤、影响等级和处理结论登记。
无法登录、无法审批、无法提交核心单据、付款状态错误、权限越权、`/ready` 异常或冻结项被误开启时,结论应为 Pause,并另建或更新最小修复 Trellis task;不得用重置数据库或生产恢复临时绕过。
### ARM 异机应用健康监控
`07-27-app-health-monitoring` 为公网 `/ready` 增加轻量异机探测:ARM 每 5 分钟经标准 HTTPS 校验访问一次;连续两次失败才发送一条脱敏企微群机器人告警,相同类别持续失败不重复发送。它覆盖 OA 应用、数据库就绪、OA 主机不可达、DNS/Caddy/TLS 已失效等基础故障,不替代登录、审批或报销等业务 smoke,也不执行自动重启或恢复。
2026-07-27 已完成 ARM 安装、启用和真实故障/恢复演练:timer 为 enabled/active,首次失败 pending、第二次发送、重复失败降噪、正式恢复发送、重复健康降噪,用户确认群内实际收到一条故障与一条恢复通知;备份 dead-man 未受影响,临时上传和临时 sudoers 已删除。
`08-23-wecom-public-health-alert-diagnostics-and-debounce` 已完成诊断与防抖增强:DNS 与 TCP 分类分离;应用消息标题明确为“OA 公网健康”;恢复改为连续 2 次健康确认;正常恢复后 60 分钟内同类故障再次达到 2 次失败时只发送一次链路反复抖动提醒,后续切换只保留脱敏计数,连续健康 30 分钟后静默退出。先运行本地无真实消息合同:
```bash
bash scripts/qa/run-app-health-monitor-contract.sh
```
ARM 安装时必须复用现有 root-owned `0600` 机器人文件,并把本次已通过备份回归的共用告警 helper 修订安装到受控目标;应用健康使用独立 state/alert state,不得覆盖备份 dead-man 状态。`install` 默认停用 timer,只写入受控探测器、helper 修订和 units;人工核对 unit、权限与一次健康手动执行后,才可另行批准 `enable`。只读检查使用:
```bash
systemctl is-enabled hyb-oa-public-app-health.timer
systemctl is-active hyb-oa-public-app-health.timer
systemctl list-timers hyb-oa-public-app-health.timer --no-pager
systemctl status hyb-oa-public-app-health.service --no-pager
```
2026-08-23,`08-23-arm-public-health-monitor-controlled-rollout` 已把提交 `a0f0483` 的增强版受控升级到 ARM 外部健康监控节点;腾讯云服务器仍是 OA 真实生产主机,ARM 不运行 OA 服务。部署依次通过本地 36 项应用健康合同、74 项备份共享合同、ARM 只读预检、disabled 安装和正式 `/ready` oneshot;probe state 从 v1 保守迁移为 v2/healthy,未产生恢复噪声。timer 启用后连续两个自然调度窗口成功且无非预期企微消息,备份 dead-man 基线不变。临时上传和 sudoers 已清理,回滚副本按批准边界保留;本轮未修改腾讯云 OA、DNS、业务数据或企微配置,也未执行故障注入或测试消息。
增强版受控演练必须证明:第一次失败仅进入 pending;第二次持续失败只发一条;重复失败降噪;第一次健康不恢复、第二次连续健康只恢复一条;60 分钟内同类复发只产生一条抖动提醒;连续健康 30 分钟后静默退出。群消息只允许状态和稳定类别,不粘贴地址、路径、响应、凭证或 journal 原文。ARM 自身宕机仍会令该 timer 失声,首版保留为人工 timer 巡检风险,不据此宣称具备第三方 dead-man。
发布候选进入公网或小范围试运行前,先按 [`docs/trialrun/发布试运行准备清单.md`](trialrun/发布试运行准备清单.md) 完成证据整理、权限直连审计、部署预检、live smoke 和试运行分级。
系统应避免让已绑定用户反复登录。若手机企业微信能进入但仍要求登录,优先检查:
- 回调 code 是否传到后端。
- 后端是否拿到 `UserId`。
- 本地账号是否绑定了企业微信 userId。
- cookie domain、SameSite、Caddy 反代头是否正确。
## OCR 验证
先确认当前 OCR provider:
- `mock` 只用于自动化和本地回归。
- 腾讯 OCR 需要真实环境变量和网络。
发票上传问题排查顺序:
1. 上传接口是否成功返回 invoice id。
2. 发票是否进入 `pending_ocr`。
3. 单票识别任务是否立即入队,周期任务是否只作为兜底。
4. OCR job 是否运行。
5. OCR provider 是否为腾讯而不是 mock。
6. OCR 是否返回结构化字段。
7. 查重是否把发票转为不可添加。
8. 前端事件流或轮询兜底是否触发刷新。
9. 报销详情是否自动添加到明细。
发布前可执行 pending OCR 扫描,定位卡住的票据:
```bash
node scripts/qa/check-pending-ocr.mjs --thresholds=2,5,10
```
脚本只输出票据 ID、上传时间、尝试次数和最后错误摘要,不读取票据文件内容。缺少 `DATABASE_URL` 时应输出 `SKIP`,不视为真实数据库健康检查通过。
### BIZ8 批量样票 OCR 回归设计
批量样票回归用于判断真实 OCR provider、异步终态和失败复核路径是否稳定,不替代 PDF-only 当前验收,也不代表图片 OCR 已开放。
推荐分层:
| 层级 | 用途 | 通过口径 |
| --- | --- | --- |
| mock OCR | 验证上传、pending、状态刷新、失败提示和报销绑定流程 | 本地自动化通过;不得宣称真实 provider 通过 |
| pending OCR 扫描 | 识别卡住的 `pending_ocr` 票据 | `check-pending-ocr.mjs` 输出计数和摘要;缺 `DATABASE_URL` 记录 `SKIP` |
| 单张真实 OCR | 验证 live provider、凭据、网络和字段归一化 | 授权样票上传后进入可解释终态;重复票据可算可解释终态 |
| 批量真实 OCR | 验证多样票稳定性、失败率和错误分类 | 仅使用授权或脱敏样票;失败逐张记录并人工复核 |
批量真实 OCR 只能在满足以下条件后执行:
1. 样票已按 [报销发票附件规则](./报销发票附件规则.md) 完成授权、脱敏和别名登记。
2. 文件名使用样票别名,不使用真实供应商、客户、员工姓名或业务说明。
3. `PLAYWRIGHT_OCR_LIVE_FILE`、`PLAYWRIGHT_OCR_LIVE_FILES` 或 `PLAYWRIGHT_OCR_LIVE_DIR` 指向仓库外安全目录。
4. 批量报告只作为本地辅助复核;未经脱敏的 `artifacts/r70/live-ocr-batch-report.md` 不得提交。
5. 如缺少样票、凭据、授权或网络,只能记录 `SKIP` 和补测条件,不得标记 PASS。
示例命令:
```bash
cd client
PLAYWRIGHT_MANUAL=1 PLAYWRIGHT_OCR_LIVE=1 PLAYWRIGHT_OCR_LIVE_BATCH=1 PLAYWRIGHT_OCR_LIVE_DIR=<safe-sample-dir> npx playwright test tests/e2e/manual/live-invoice-ocr-batch.spec.ts --workers=1 --reporter=list
```
结果判读:
- `available` 或可解释的重复票据终态表示 OCR 链路可继续人工复核。
- `pending_ocr` 超过阈值必须结合 pending 扫描和 worker 日志排查,不能直接算失败或通过。
- `ocr_failed` 必须记录错误摘要、provider、样票别名和是否可重试,不记录完整票面字段。
- 批量样票结论必须区分 PDF、图片、mock 和真实 provider;图片 OCR 仍是后续候选,不进入当前 R7E 验收。
## 发布候选本地门禁
### 五人团队内部候选(2026-07-18)
内部部署规划前,先在当前 checkout 上执行两层本地门禁:
```bash
bash scripts/qa/run-web-gates.sh payment-concurrency-local
bash scripts/qa/run-local-candidate.sh full
```
- `payment-concurrency-local` 使用回环 PostgreSQL 和 `hyb_oa_payment_` 前缀的一次性合成数据库,执行当前全部 migration,并验证付款竞态与审计/通知唯一性;数据库清理失败即门禁失败。
- `run-local-candidate.sh full` 执行无历史 Issue CSV 依赖的基础门禁、路由/流程反例和本地 Vite 合成浏览器行为。只有该模式成功时才输出 `LOCAL_CANDIDATE_PASS`。
- `focused` 只重跑路由反例和浏览器行为,成功标记为 `FOCUSED_BROWSER_PASS`,不能替代 `full`;`list` 只证明 Playwright 资产可解析,标记为 `LIST_ONLY`。
- 浏览器入口只允许无凭据、无路径参数的 loopback HTTP origin;候选 spec 排除 `manual/live`,测试数据、角色、账号和材料必须为合成内容。
- 路由门禁要求所有注册路由完成分类,核心流程 witness 与 manifest 一一绑定,且全部候选用例不得 failed、skipped、unexpected 或来源漂移。
收口证据至少记录:本文件所在提交、命令与退出码、环境边界、migration/临时库清理、路由与流程统计、Playwright passed/skipped/failed 数、十个 witness 的最终 URL/H1/角色/允许与禁止动作、页面错误计数、代表 viewport/溢出指标、脱敏截图引用,以及 finding 的修复/部署/外部验证三层状态。所有路径使用仓库相对引用,不保留原始 payload、真实账号、银行资料或完整本地路径。
本地候选通过后仍只能表述为“本地候选通过,尚未部署”。真实账号分配、超级管理员托管、迁移执行、备份恢复、内部地址验收、公网检查和企业微信真机必须由后续获批 Trellis task 完成。
### 历史 A8 本地回归参数
首轮主线 A8 复跑本地门禁时,需要先用本地回归参数启动服务,再执行回归脚本。推荐参数:
```bash
SERVE_CLIENT_DIST=true
OCR_PROVIDER=mock
IM_NOTIFIER_ENABLED=true
FIELD_ENCRYPTION_KEY=<local-test-key>
PROJECT_DOMAIN_ENABLED=true
PROJECT_LINKING_ENABLED=true
PROJECT_COMMUNICATION_LOG_ENABLED=true
PROJECT_CLOSURE_CHECKLIST_ENABLED=true
```
注意:
- `FIELD_ENCRYPTION_KEY` 只允许使用本地测试值;生产密钥不得提交或写入文档。
- `OCR_PROVIDER=mock` 只证明本地 OCR 流程,不代表真实 OCR provider 通过。
- `IM_NOTIFIER_ENABLED=true` 用于覆盖通知链路;缺真实企业微信配置时,企业微信真机仍必须标 `SKIP`。
- 项目相关开关用于本地项目轻管理回归,不得被解释为扩展 P2 范围。
## 公网与部署
当前公网服务器信息以受控运维配置为准。历史基础设施信息已脱敏:
- 服务器:由 `DEPLOY_SERVER` 在执行时显式提供,不写入仓库。
- 反代:Caddy
- 域名示例:`oa.hyinda.com`
远端操作原则:
- 先备份配置和数据。
- 先确认远端目录是否为 git 工作树。
- 若远端不是 git 工作树,继续使用既有 rsync/部署脚本。
- 修改 Caddy、数据库、系统服务前必须先说明风险并等待确认。
## 数据库迁移漂移
如果 `npx prisma migrate status` 显示本地迁移历史和数据库迁移表分叉,不要自动修复。
必须暂停并让用户确认处理策略:
- 备份当前数据库。
- 对齐缺失 migration 文件。
- 或重建本地开发库并重新 seed。
- 或对生产/试运行库执行受控迁移。
禁止在未确认时执行:
- `prisma migrate reset`
- 删除迁移记录。
- 手工改生产表结构。
- 破坏性数据库命令。
## 收口标准
每轮交付收口至少包含:
- 当前 Trellis task 的 PRD、验收、状态和提交引用真实。
- 明确区分本地 commit、部署来源 commit 和公网复检结果。
- 自动化命令、结果和必要视觉证据路径记录完整。
- 已知阻塞明确归类为代码、测试、环境、数据或人工配置。
- task validate、Trellis governance 和任务要求的必要门禁通过。
- 历史 Issue CSV 保持审计可追溯,但不要求作为当前状态合同。
- 中文分批 commit。
## 出借人在线确认(2026-10-10 本地候选,尚未发布)
此入口需本轮发布后才能在线上使用,生产状态以借款任务 implement 顶部回执为准。财务在“公司借款 → 出借人确认 → 发起出借人确认”选择同一出借人的一笔或多笔待核实借款,填写说明。原借入凭据须先上传,系统固定借入日期、原始本金、余额核对截止日、截至日未还本金及原件摘要。
财务发起后,系统只给该出借人创建一条 OA 站内“借款声明待本人确认”通知,不发送企业微信或其他外部消息。出借人使用本人 OA 账号,在电脑或手机的通知中心找到通知(可筛选“借款确认”),点击后直接打开本次声明。普通员工没有常驻“公司借款”入口;财务和公司代表保留原入口。出借人查看明细和原件,勾选本人声明并填写说明后确认;有误则填写原因退回财务。财务不能代确认,普通员工出借人也无需经理权限。历史通知仍可查看,但失效声明须由财务重新发起,不能通过旧通知恢复确认。线上记录作为系统接受的借款确认材料,不因留痕即宣称当然等同纸质签字的法律效力。
财务仍须上传代账余额核对材料;截至日未还本金少于原本金时,还须系统外已还本金依据。有效在线确认可替代协议或借款确认书附件,之后由财务填写代账引用并确认期初余额,再单独登记公司代表授权、由有权公司代表确认。出借人声明不自动完成余额确认、授权或付款审批。关键金额、日期、原件或出借人关联变化会使整组旧声明失效,恢复旧值也须重新发起;旧记录保留。已经确认余额的借款,如曾有在线声明且现已失效,仍可重新发起出借人确认,原余额确认记录不被改写。身份资料刷新导致公司代表授权失效时,授权还须另行重新办理。
开发验证沿隔离借款 runner,`RUN_ISOLATED_LOAN_ACK_ONLY=1` 选择声明专项,`RUN_ISOLATED_LOAN_BROWSER=1` 加电脑/手机操作;先构建前端,并设置已有 BIFF8 Python 环境。真实人员确认和生产迁移另行批准,不用合成回执替代真实业务验收。
## 2026-09-17 本地借款与付款责任候选
本地源码新增公司向个人借入的人民币本金台账及还本;登记出借人/核实OA身份、上传原借入和核对材料、确认期初余额后,可将同一出借人的多笔借入分配到一笔还款。付款批次独立复核、线下网银制单/回单、登记成功后核销本金,会计交接单独确认。未知或在途银行结果保持占用;不得仅用取消理由解锁重付。此段描述待发布候选,不表示公网已具备该入口。
付款进度候选显示当前可处理人员、原站内提醒对象及脱敏发送记录。企微个人消息仅按`wecom_app_sent`成功认定已发送,不等于已读;无成功记录也不能单凭页面断言消息一定没有发出。多接收人anchor记录不能证明人人送达。真实批次接收人/送达仍须在另行授权的范围核实际记录。
ERP专属实现与后台同步已从本地候选移除,历史ERP数据保留只读且不能重试;共享企微、通知和outbox保留。历史`erp_sync=force_off`证据不改写;当前候选的运行时不再提供该开关对应的ERP执行能力。工资、绩效、预算和企微考勤摘要不在本次删除范围。
验证入口为`09-17-company-loan-principal-repayment`与`09-17-erp-exclusive-retirement`的implement回执;合成专库使用`RUN_ISOLATED_LOAN_DB_TEST=1 node scripts/qa/test-company-loan-db.cjs`,浏览器另设`RUN_ISOLATED_LOAN_BROWSER=1`且先构建client。BIFF8使用已有专用Python并传`PAYMENT_ORDER_PYTHON_BIN`,不自动安装或联网;所有身份、密钥和材料运行内生成,不读生产配置。独立只读复核、真实银行样本/恢复保管事实、迁移发布及真实录入付款仍是独立门禁。
## 业务编号增量切换(准备,未启用生产)
执行合同为 `09-18-reimbursement-periodic-numbering`。先部署加法迁移和兼容新旧规则的所有写入实例,策略表无记录时仍发旧号,不重跑seed切换。旧单和未编号旧草稿不回填;不得清理编号计数表。切换前经另行批准取得格式分布/缺号及同格式占号摘要,完成独立复核,确认银行材料和来源快照兼容,再确定未来生效时刻;优先准备就绪后的月初,不预定某个日期上线。
管理入口 `node server/src/scripts/manage-business-numbering.js --help`;status只输出版本、启用状态、生效时刻及需要专门兼容复核的旧周期类型,activate需要含时区的未来ISO时间、操作人UUID、变更引用与 `--writers-compatible`。该标记只是操作人对全部写入实例兼容的明确确认,不能代替发布核验。首次激活在等待策略锁及检查后重新取时,已过期的生效点拒绝。若旧报销/采购/盘点取号配置本身已使用新月/年日期段,启用/恢复会保守拒绝并要求专门兼容处理,不能擅自清零或改写旧规则;这与源表里已有若干同格式号码的正常接续不同。入口不读取.env;正式数据库连接只能通过届时批准的注入方式提供,本轮不提供或执行生产连接命令。
pause/resume保留首次生效时刻、全部已发号码和高水位;暂停仅影响以后创建对象,已归属v2的采购草稿仍按v2首次提交取号。策略变更与既有审计同事务,启停等待已持策略锁的业务事务结束。回退代码必须仍兼容两类号,不删除新增表/版本字段、不减计数,也不重新导出旧批次为新编号。
本地验证命令:`cd server && npm run prisma:validate && npm test`;隔离PG为 `RUN_ISOLATED_NUMBERING_DB_TEST=1 node scripts/qa/test-business-numbering-db.cjs`,使用本机已备好的PostgreSQL镜像和合成运行环境,禁外联/宿主端口,包含合成借款HTTP整链及银行文件测试。需沿用已有受控Python运行环境;不得因缺依赖下载或读取真实配置。本次新证据在 `artifacts/qa-layout/business-numbering-20260918`,旧失败与冻结材料保留;仍须另行完成原G20完整门禁、独立复核及授权发布后的公网验收。
### 借款银行结果对账与恢复(09-17,本地待验收)
本节描述待验收的本地流程,不是生产已启用的操作指引。启用前须完成 S0 存量核实、合格复核人数及银行官方材料确认、真实回单验证和独立复核;不得直接发布当前 main。
- 导出与银行提交分别登记。提交清单须确认完整并经独立复核;新增、撤回登记或重新导出都会使旧确认失效。
- 银行终态逐提交举证;不能用一条失败推定其他提交结束。成功事实不能靠作废附件消除,处理中回单仅可被同指令终态了结。最终取消时再次检查依据与等待期。
- 仅导出未提交的人工例外须查询无结果官方 PDF、同期账户对账单、相关导出人的文件去向说明齐全,完整清单已复核且等待期满;另由两名独立合格人员复核。材料或人员不足继续占用,不能用线下结论直接解除。
- 已确认失败/银行未付款,但依据失效且占用未释放:另发起补证恢复,补齐逐次终态、送审、独立复核,再取消。撤回或驳回不恢复旧释放依据;材料变化必须新轮次复核。原终态始终保留。
- 晚到成功:另上传原件、人工录入并说明归属,一经登记即冻结后续付款;独立复核后补记,原批次不能再次导出。占用冲突须先处理;只有实际重复付出的差额列待追回。
- 超额追回:实际退款到账回单、独立复核、登记入账;部分到账只减待追回额,全额到账后关闭相应原因。其他未关闭原因仍阻止付款。误报须独立复核更正证据后关闭,不删除原事件;已用于解冻的更正依据不能再作废。
- 终态复核可一次核对多份同指令处理中回单。已作废的回单只通过对账卡片的历史证据入口查看,必须填写用途并记审计,不恢复付款效力。登记晚到成功后,原失败取消入口暂停释放;更换未入账记录会接续已有冲突冻结,不能用换记录解除冻结。
- 不得再将原下载制单导入网银;OA 不能令已下载文件失效。发现新的银行事实,应登记对账事件,不改原终态或直接改数据库。
合成验证使用 `RUN_ISOLATED_LOAN_DB_TEST=1 RUN_ISOLATED_LOAN_BROWSER=1 node scripts/qa/test-company-loan-db.cjs`;BIFF8 依赖按锁定 requirements 安装并由 `PAYMENT_ORDER_PYTHON_BIN` 指定。容器无网络、无持久卷,只清理本次拥有的资源。完整结果及尚未覆盖项以该任务 implement.md 为准。