回填公网验收与恢复诊断中发现的测试规则 [08-23-isolated-backup-restore-drill]

从孤儿 worktree(20260909-invoice-first、20260910-reimbursement-payment-integration)
合并回填两条实测中发现、从未提交的通用测试规则:

- reimbursement-invoice-ocr.md:公网合成验收流程(provider 检查→锁定 SHA256→
  上传);Fastify 对无 body 的 DELETE 请求发送 application/json 会报
  FST_ERR_CTP_EMPTY_JSON_BODY 的坑;批量分类后编辑需等视图更新,
  getByLabel 对已有内容的嵌套 textarea 可能定位失配。
- deployment-trialrun.md:buildSha 公网字段固定截断为 12 位、探针不得按
  完整 40 位比较;readiness fixture 必须覆盖错误/过短/空/超长四种值并在
  目标主机做无权限探测;附件引用校验失败前必须先保留已完成的 DB/解包
  结果,不能让后续失败掩盖已核实的部分。

均为测试脚本经验教训,无产品代码改动。

Co-Authored-By: Claude Sonnet 5 <[email protected]>
这个提交包含在:
2026-09-25 19:55:28 +08:00
共同撰写人 Claude Sonnet 5
父节点 dea0303485
当前提交 c81ed9ca69
共修改 2 个文件,包含 31 行新增和 0 行删除
@@ -727,6 +727,12 @@ const REQUIRED_ADMIN_NAV_KEYS = ["systemSettings"];
must explicitly provide both and must not publish `unknown`.
- Deployment compares public `/ready` and the public bundle marker with the
verified commit before reporting success.
- `/health.data.buildSha` and `/ready.data.buildSha` are normalized by
`server/src/config.js` to the first 12 characters. A probe with a pinned full
commit must compare the public value to exactly those 12 characters, not the
full commit or an arbitrary-length prefix. Runtime environment and backup
manifest identities remain full-SHA checks. A public identity mismatch is
not by itself proof that production changed.
### 4. Validation & Error Matrix
@@ -759,6 +765,11 @@ const REQUIRED_ADMIN_NAV_KEYS = ["systemSettings"];
- Synthetic 40-character build: bundle contains the matching 12-character SHA
and not the full value.
- Local-stub readiness test for expected/observed SHA propagation.
- Readiness fixtures must derive the public SHA from the actual `getConfig`
contract; cover wrong, short, empty and unexpectedly full public values.
Before a privileged restore handoff, exercise the same public probe from the
target host without privileges; a stub that echoes the input full SHA cannot
substitute for this read-only check.
- Public deployment still requires separate approval and post-deploy checks.
### 7. Wrong vs Correct
@@ -1627,6 +1638,12 @@ validate_copied_batch(private/batch, source_metadata)
- Emit the fixed diagnostic fields on the failure path before runtime teardown.
Teardown remains in a trap/finally-equivalent path and must still run after
diagnostic emission; callers retain stdout, not the private raw log.
- Before an attachment-reference failure, preserve completed DB checks,
extraction/file-count results and per-source reference/mismatch counts.
Classify missing files, size/hash mismatches, unsafe paths, malformed rows,
unreadable files and external storage without outputting identifiers or paths.
Check diagnostic totals against the unchanged validator; disagreement also
fails closed. Do not skip archived, test or duplicate references to gain PASS.
- An ARM restore runner fixes `restore_execution_path=DOCKER_STDIN`. A private
Docker proxy may observe the real `pg_restore --list` and apply calls and
persist only their stage name and numeric exit code; it must not record argv,
@@ -38,6 +38,20 @@ duplicate detection or attachment behavior.
## Rules
- 公网合成验收先用明确标注测试用途、无真实交易的样票单独跑 provider 必填检查,
通过后锁定 SHA256,再上传走队列/UI;provider 成功不替代上传整链。保留失败轮次,
最终区分草稿、审批、付款证据。清理使用本轮精确对象,回读草稿为零、票据归档且
未绑定、测试会话已撤销;归档不等于物理附件/OCR/审计数据删除。
- 测试 API 无 body 的 DELETE 不发送 application/json:Fastify 会报
FST_ERR_CTP_EMPTY_JSON_BODY(400);省略该头应正常进入处理器。
登录按实际合同携带设备指纹,logout 使用对应浏览器 Cookie;无 Cookie 的 200
不是会话撤销证据。报销 precheck 虽为 POST 但不等于提交审批,测试应按实际副作用
控制白名单,不能拦截该接口后宣称正常页面请求完整通过。
- 批量分类测试先等视图完成更新并核持久化类型,再开始另一项编辑,不能仅等待
classify HTTP 响应就假定查询缓存已更新。嵌套 label 内已有内容的 textarea 可能
使 getByLabel 的精确文本定位失配;使用稳定字段标识或 label 的独立 span + textarea,
同时覆盖空值与已有值,不靠延长超时反复消耗生产登录。
- 隔离串联的 `RUN_JOB_QUEUE=1` 必须运行真实 startPgBossJobs 与上传入口 enqueue,
等对应 invoiceId 的队列任务 completed,再校验发票状态和页面,不用直接调用
worker 冒充调度。只连接脚本新建数据库;非关注周期任务不得在测试期间改其他对象。