Policy OCR shipped 2026-08-01 (5e9cb12) and was documented nowhere. It is
not in INSURANCE_FEATURES_SPEC.md because it did not come from that
meeting — it came out of building the utility statement OCR pipeline in
RECEIPT_CAPTURE_SPEC.md §2 and noticing the same shape fits carrier
policy PDFs. A reader had no way to find that lineage.
New docs/POLICY_OCR.md covers it end to end, with weight on the three
things that are not obvious from the statement side:
- **One PDF = one policy.** Statements arrive bundled one customer per
page, so there a page is a document. A GMX certificate is one policy
across two pages, so the pages are concatenated and the parser runs
once per file — which is why `pageNumber` is a file ordinal and
`storageKey` is the source PDF, not a page image.
- **The GMX certificate carries no premium at all** — it lives on a
separate recibo PDF. Hence the null-preserving confirm and the
double-gated ledger write.
- **OcrModule was extracted out of StatementsModule to make this
possible**, and that was blocking rather than cosmetic.
Cross-referenced from RECEIPT_CAPTURE_SPEC.md §2 (where it came from),
INSURANCE_FEATURES_SPEC.md (which never proposed it, and whose §4 carrier
API it partly overlaps), PLAN.md step 11, README and RESUME.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The docs still described the state before the last five commits: the
insurance spec called for a `@Cron` literal and a manual mark-as-sent
mutation, PLAN.md had step 12 as "NOT STARTED", and README's module and
route lists predated seven modules.
- MASS_EMAIL_NOTIFICATIONS.md: new "Send flags", "API surface" and
"Scheduled runs" sections; "Cron (future)" removed — it exists. The
flags table says which flags apply where, and why a debug renewal send
must skip both the RenewalNotice row and `lastSuccessfulAt`.
- INSURANCE_FEATURES_SPEC.md: §1 BUILT note listing the three places the
build diverged from the spec; §1.1 and §1.4 marked superseded in place
rather than deleted, so the reasoning stays readable.
- PLAN.md: step 12 renewal emails DONE with the divergences; status
paragraph rewritten.
- README.md: current module/route lists, plus a "Scheduled jobs" section —
a reader cloning this repo had no way to know the API sends mail on a
timer.
- DEPLOY_AND_MIGRATIONS.md: the cadence lives in app_settings and survives
an image rollback, and the servicios sweep has no multi-replica lock.
- RESUME.md: session record for the whole notificaciones arc.
- RENEWAL_NOTICES.md: pointer that this is the legacy record, not what
shipped.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Companion to docs/RECEIPT_CAPTURE_SPEC.md — the insurance half of the
2026-07-25/26 meeting. Documentation only; no application code.
Verified against the code and a live query of the dev DB rather than
designed from the meeting notes alone, which changed several conclusions:
- Renewal emails and the liquidación batch are much smaller than they
look. RenewalNotice + its @@unique([policyId, generation]) idempotency
key and the aviso-renovacion letter body already exist; the per-policy
liquidation fields are wired end to end. What's missing is a scheduler,
a mail client, and the batch layer.
- Carrier research: ANA and GMX are one company (Grupo Valore). ANA
exposes a live SOAP service with a published operation list; GMX
publishes no machine interface at all. Every ANA operation serves
new-business quoting/issuance, not "list my book" — so the direction
question decides whether the feature is buildable.
- UTILSEG is unusable for Utilities↔Seguros reconciliation and the spec
closes that long-standing open question: DATGRAL.[NUM UTIL] is
authoritative (name match 298/563 vs 58/1024), and where the two
sources overlap they contradict on 170 of 218 shared ids.
Also records two live defects found while verifying: policy_types is
missing its INCENDIO and M_EMPR rows (the FK is ON DELETE SET NULL, so 5
m_empr policies silently lost their ramo), and the legacy settlement
slots don't match the target model (MULT/INCENDIO carry two, M EMPR
carries four, Policy collapses to one).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>