Appearance
ADR: Mistral OCR document recognition
Status: Accepted — 2026-07-14
Decision
MyHoreca Pay uses a provider-specific MyHoreca.Pay.DocumentRecognition.Mistral project behind the existing provider-neutral recognition abstractions. The PostgreSQL-leased worker, local BankStatementFile storage, review UI, correction history, confirmation boundary and global learning lifecycle remain unchanged.
The provider opens the stored original once and streams it as multipart StreamContent to Mistral /v1/files with purpose ocr. It then sends one /v1/ocr request with strict document annotation, include_blocks=true by default and include_image_base64=false. A temporary remote file is deleted in finally; transient cleanup failures retain only its identifier for the existing cleanup retry.
The generated NuGet upload client is not used because its document parameter is byte[] and would buffer a complete multi-page PDF. The NuGet Mistral package remains pinned in the provider project, while a thin typed REST adapter covers the streaming Files and current OCR contracts. Application code serializes only typed DTOs through PayJsonSerializer/Newtonsoft.
Document annotation provides classification and banking fields in one pass. OCR blocks are used only for deterministic source matching. Coordinates are normalized and clamped to the page; when a match is absent or ambiguous the box remains null and evidence becomes uncertain. Coordinates are approximate, never invented.
Historical recognition data is retained with its original provider. A migration retires historical active/canary OpenAI model versions without deleting or rewriting them. Runtime model resolution filters by the configured provider and creates one global Mistral model per input kind. It remains tenant-independent and preserves evaluation, canary and rollback behavior.
Security and operations
MISTRAL_API_KEY is accepted only from process environment/deployment secrets and is never exposed to the browser, logs, audit data or database. Options are validated at startup. Provider failures are mapped to stable provider-neutral error codes without response bodies or document data. Original files remain on the existing local disk volume; no public URL or new storage/broker service is introduced.
Consequences
Mistral OCR can process a multi-page PDF without local page rendering or whole-file buffering. Token metrics remain null when OCR does not return them; real page count and provider request identifiers are retained. Handwritten recognition and block-to-business-field matching depend on provider output quality, and document annotations may have provider page limits; the manual review boundary remains mandatory.