收敛真实OCR样票验收入口(07-28-travel-reimbursement-guide)
这个提交包含在:
@@ -251,6 +251,103 @@ const persisted = sanitizeOcrResultForPersistence("tencent", normalized);
|
||||
await prisma.ocrResult.create({ data: { result_json: persisted } });
|
||||
```
|
||||
|
||||
## Scenario: Live OCR Sample Stdin Probe
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
- Trigger: an authorized real PDF must prove Tencent credentials, network,
|
||||
subtype normalization and required-field behavior without creating an OA
|
||||
invoice or persisting the sample on the execution host.
|
||||
- This probe is intentionally one-file and PDF-only. It does not retain the
|
||||
historical manifest, directory scan, image evaluation or legacy VAT-only
|
||||
command modes.
|
||||
|
||||
### 2. Signatures
|
||||
|
||||
- Command:
|
||||
`node scripts/qa/check-ocr-provider-samples.mjs --alias=SAMPLE-PDF-<SAFE_ALIAS>`.
|
||||
- Input: exactly one PDF on stdin, at most `OCR_PDF_MAX_BYTES` (7 MiB).
|
||||
- Runtime env: `TENCENT_SECRET_ID`, `TENCENT_SECRET_KEY`, optional
|
||||
`TENCENT_OCR_REGION` and `OCR_TIMEOUT_MS`; provider is fixed to `tencent`.
|
||||
- Provider boundary: `runOcrForInvoice({ config, ocrType: "vat",
|
||||
imageBase64, sourceMimeType: "application/pdf" })`.
|
||||
- Output: one JSON object containing only `alias`, `provider`, `status`,
|
||||
`transportMode`, `elapsedMs`, safe document category/subtype/count,
|
||||
per-field hit booleans, missing field names and a bounded error code.
|
||||
|
||||
### 3. Contracts
|
||||
|
||||
- The caller selects one authorized PDF explicitly and streams it through
|
||||
stdin. The probe never accepts a file path, directory, manifest, image or
|
||||
batch list and never writes sample bytes to disk, OA storage or the database.
|
||||
- Alias must match `SAMPLE-PDF-[A-Z0-9_-]+`; it replaces the original file name
|
||||
in every output and evidence record.
|
||||
- Validate the 7 MiB limit, PDF version header and terminal `%%EOF` before
|
||||
constructing Base64 or invoking Tencent. One process performs at most one
|
||||
provider call.
|
||||
- Reuse `RecognizeGeneralInvoice`, `sanitizeOcrResultForPersistence` and the
|
||||
production category-specific required-field rules. The probe must not carry
|
||||
a parallel VAT-only field list.
|
||||
- Never output recognized identifiers, dates, amounts, buyer/seller/passenger
|
||||
names, provider messages, raw response or input bytes. Field presence is a
|
||||
boolean; errors are bounded stable codes.
|
||||
- A PASS proves the direct provider/normalization path only. It does not prove
|
||||
OA upload, queue, persistence, duplicate detection, binding or reimbursement
|
||||
submission.
|
||||
|
||||
### 4. Validation & Error Matrix
|
||||
|
||||
- Missing/invalid alias -> `sample_alias_invalid`; no provider call.
|
||||
- Empty stdin -> `sample_empty`; no provider call.
|
||||
- More than 7 MiB -> `sample_too_large`; stop reading and do not call provider.
|
||||
- Invalid header or missing terminal EOF -> `sample_pdf_invalid`; no provider
|
||||
call.
|
||||
- Missing credentials or provider mismatch -> `ocr_credentials_missing` /
|
||||
`ocr_provider_invalid`; no business values in output.
|
||||
- Supported subtype with missing category-required fields -> `status=HOLD`
|
||||
plus field names only.
|
||||
- Tencent failure -> `status=HOLD` plus a bounded SDK error code; omit the
|
||||
provider message and raw error object.
|
||||
|
||||
### 5. Good/Base/Bad Cases
|
||||
|
||||
- Good: stream one railway electronic ticket using an anonymous alias; receive
|
||||
`electronic_train_ticket`, boolean field hits and no recognized values or
|
||||
persisted sample.
|
||||
- Base: stream one supported accommodation invoice and receive a PASS summary
|
||||
for its VAT/full-VAT category.
|
||||
- Bad: point the probe at a directory, auto-run every PDF, write a manifest with
|
||||
real paths, accept images, print OCR values or retain the sample remotely.
|
||||
|
||||
### 6. Tests Required
|
||||
|
||||
- Unit tests inject synthetic provider results for VAT, full VAT and railway
|
||||
categories and assert category-aware required fields.
|
||||
- Negative tests assert non-PDF, truncated PDF and oversized input fail before
|
||||
the provider mock is called.
|
||||
- Privacy tests seed raw provider and recognizable normalized markers, then
|
||||
assert serialized output contains only booleans and safe metadata.
|
||||
- CLI test pipes one synthetic PDF over stdin with credentials absent and
|
||||
asserts one parseable redacted error object with empty stderr.
|
||||
- Before deployment run `node --check`, the focused tests, full backend tests,
|
||||
sensitive-content scan, task validation and Trellis governance.
|
||||
|
||||
### 7. Wrong vs Correct
|
||||
|
||||
#### Wrong
|
||||
|
||||
```bash
|
||||
PLAYWRIGHT_OCR_LIVE_DIR=<sample-dir> \
|
||||
node scripts/qa/check-ocr-provider-samples.mjs --provider=tencent --json
|
||||
```
|
||||
|
||||
#### Correct
|
||||
|
||||
```bash
|
||||
node scripts/qa/check-ocr-provider-samples.mjs \
|
||||
--alias=SAMPLE-PDF-TRAIN < <authorized-single-sample.pdf>
|
||||
```
|
||||
|
||||
## Scenario: Payment Batch Receipt Attention Count
|
||||
|
||||
### 1. Scope / Trigger
|
||||
|
||||
@@ -44,6 +44,14 @@
|
||||
7. 只记录 provider、状态、尝试/完成证据和脱敏字段命中摘要;不记录票面、完整字段或原始 payload。
|
||||
8. 正常清理或归档测试业务记录,再允许杨俊提交真实票据。
|
||||
|
||||
### 授权样票验证工具边界
|
||||
|
||||
- 既有 `check-ocr-provider-samples.mjs` 必须与生产 adapter 使用同一 `RecognizeGeneralInvoice` 入口和按票种必填字段规则,不得继续引用已删除的 VAT-only 导出或把铁路电子客票套入 VAT 五字段门禁。
|
||||
- 真实 PDF 从本地受控、Git 忽略的样票目录按匿名别名选择,经 SSH 标准输入直接流入生产 server 容器内存;不得把原件、临时副本或 manifest 写入远端磁盘、OA 附件存储、数据库、仓库或报告。
|
||||
- 每个进程只接收一份 PDF,验证文件签名和 7MiB 上限后最多调用一次 `RecognizeGeneralInvoice`。住宿与铁路样票分两次执行,任一失败立即停止,不自动遍历目录中的其他文件。
|
||||
- 输出只允许匿名别名、provider、票种、安全传输模式、耗时、字段命中布尔值、缺字段名和稳定错误码;不得输出文件名、原始响应、识别值、人员/企业名称、票号、金额或票面内容。
|
||||
- live runner 的代码、合成测试和生产部署先通过,再单独取得两次真实 API 调用批准;工具可用不等于真实样票已验证。
|
||||
|
||||
## 文档口径
|
||||
|
||||
- `docs/员工快速上手.md` 增加一页式差旅报销步骤:火车票和住宿费拆明细,官方 PDF 绑定对应明细,两类费用均附支付截图,金额差异必须说明,提交后进入主管和财务流程。
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
- [x] 检查公网 `/ready` 和预期构建标识。
|
||||
- [x] 在 server 内运行现有 external deps 和运行时 smoke,不输出 Secret 或原始响应。
|
||||
- [x] 确认实际 provider 为 `tencent`,且只有一个 OCR job executor。
|
||||
- [x] 修正 live 样票脚本:复用 `RecognizeGeneralInvoice`、按票种必填字段和安全持久化白名单,支持单 PDF 标准输入且仅输出脱敏摘要。
|
||||
- [ ] 使用合成 PDF/provider 响应覆盖住宿、铁路、非 PDF、超限、缺字段和原始响应不输出,并完成本地门禁、提交和生产部署。
|
||||
- [ ] 经单独样票批准后分别运行住宿电子普通发票和铁路电子客票 live OCR PDF 验收。
|
||||
- [ ] 只保存脱敏状态、耗时、provider 和字段命中摘要;确认不存在 mock 调用证据。
|
||||
- [ ] 按正常 API/业务生命周期清理或归档测试记录,并执行只读残留检查。
|
||||
|
||||
在新工单中引用
屏蔽一个用户