Skip to content
Docs

Command palette

Jump to a page or search the docs.

Changelog

Document scanner

How a car document photographed on the phone becomes a draft of its type, grounded in the text read, and is saved only when the person confirms.

Markdown

What it does

The scanner (AI features spec §1) reads any car document and returns a draft of its type with a confidence and the line it was read from per field; nothing is saved before Confirm (RN10).

DocumentBecomes
Fuel receipta fuel expense and its odometer reading, the photo as its receipt
Workshop invoice (up to 5 photo pages)a service with its items and reading; printed taxes go in its note
Insurance policythe policy as a document (its end is a reminder) and the premium as a recurring expense
Vehicle tax (IPVA, licensing, Kfz-Steuer)the notice as a document; paid, an expense of the tax category; still due, a yearly recurring expense from its due date
Purchase invoiceM-Compra's price, costs, down payment and amount financed (a recorded value changed needs a reason)
Loan contractthe Loan (or the terms of the one the purchase opened) and its monthly payment from the next month

The flag ai.capture shows the scanner and lets the model help. Reading is on the phone (expo-text-extractor) and never metered; with the flag on and a structuring model configured, the text (never the photo) goes to scan.structure, which counts against the structuring quota (AI foundation).

Reading and grounding

@autofolio/domain/scan is the scanner's pure core:

  • detectKind names the document type from its words; the type the person picked always wins.
  • readDocument is the phone's own draft: a receipt's fields (readReceipt) plus, per type, the lines with a tax's name and due date, a policy's term and instalments, a contract's rate (yearly or monthly), term and payment, a workshop's item lines and taxes.
  • groundScan keeps only values printed in the text, each with its line, at medium confidence when the model filled it: a model can never invent an amount, a date or a name. An item whose amount is not printed keeps its name only.
  • mergeScans takes the surer value per field; the same value from the phone and the model is sure (0.9). scanReady says when every value a type needs is read surely.

scan.structure sends the scrubbed text (no plate, VIN or email) to the model with a fixed schema, grounds the answer against the same scrubbed text and drops a document date after today. Off, rate-limited, slow or failing: { draft: null } and the phone's draft stands; past the quota, QUOTA.

ProcedureWhoFailures
scan.structure { kind?, text, locale, today, platform }every MemberINPUT_VALIDATION (empty or over 12,000 characters), QUOTA

Confirm

Confirm writes through the features' own procedures. Fuel and a workshop invoice go through their offline queues (useExpenseQueue, useServiceQueue), so RF10's duplicate warning and RN07's lower reading answer as when typed (an old invoice is checked against the readings around its date on the server); the confirmed rows carry ocr_draft_confirmed. The rest need a connection: the original is filed first as the car's document, then the recurring expense, the Loan or the purchase. Every write has an id made with the draft, and an uploaded page is reused, so a retry never writes twice. Pages after the first are filed as the same document, "· 2/3".

App

  • Scan-Main (screen-Scan-Main, /scan?vehicleId=…): One document or Shoebox (modo-um, modo-caixa), the document type (Detect automatically by default), the pages with Add page and remove, Take photo (tirar-foto) then Read document (ler-documento). Shoebox's Choose photos (escolher-fotos) reads each photo as one document and opens the queue.
  • Scan-Draft (screen-Scan-Draft, /scan/draft?id=…): the pages, the type (tipo-doc), each field (campo-<field>) with "confidence high" or a check pill and the line it was read from highlighted under it, what Confirm will create, Confirm (confirmar), Save anyway after a duplicate warning, a reason when RN07 or a purchase correction asks, and Discard draft.
  • Scan-Batch (screen-Scan-Batch, /scan/batch?vehicleId=…): the drafts oldest first (readings then rise as they are saved), the ones read the same grouped under the first, a state per row (ready, check, same as above, needs you, saved, on this phone) and "Confirm the N ready ones" (confirmar-prontos). Ready means a fuel receipt, workshop invoice or tax notice whose needed values were read surely; the rest open one by one.

M-Veiculo's More and M-Documentos' more open the scanner. autofolio://dev/Scan-Main opens it with the sample receipt as a page; Scan-Draft opens a workshop invoice's draft, Scan-Batch a shoebox of four (one fuel receipt twice), all read on the phone from fixed text.

shortcut: PDFs and the share sheet are not imported yet: the phone reads text from photos only (Hermes has no WebAssembly for the PDF converter, and server conversion failed its memory gate, ADR-0008); a native PDF text module and a share extension come with the next dev-client build. The drafts live in memory for the session; persist them if owners scan long shoeboxes.

Key files

Edit on GitHubDocumentation is in English.

We use essential cookies to make our app work. With your consent, we also use optional cookies to improve your experience. Read our Cookie Policy and Privacy Policy.