收敛真实OCR样票验收入口(07-28-travel-reimbursement-guide)
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s

这个提交包含在:
2026-07-29 08:28:42 +08:00
父节点 6a1fd4d789
当前提交 fa326f92fa
共修改 7 个文件,包含 464 行新增和 329 行删除
@@ -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