Skip to content

Document

Contrato cross-surface para seleção, preview, e OCR de documentos em apps Koder (PDF, DOCX, MD, KMD, TXT, ODT). Toggles em Settings (`media.document.ocr`); defaults seguros; widgets `KoderDocumentPicker` + `KoderDocumentPreview` + `KoderOcrButton` em `engines/sdk/koder_kit`. OCR roda local-first via tesseract ou serviço Koder (`services/ai/ocr` quando disponível) — terceiros proibidos. Upload size cap 50 MB. `<APP>-DOC-*` error map. **Bridge com `image.kmd`:** captura via câmera retorna `KoderImageRef`; OCR vira o passo seguinte (image → text) e o resultado é tratado como document.

Source spec: specs/media/document.kmd

Full specification

Media — Document Spec — v0.1

Normative cross-surface spec para document I/O em apps Koder (incluindo OCR como bridge image→text). Implementação obrigatória via widgets KoderDocument* em engines/sdk/koder_kit — nunca rolar file_picker upstream ou <input type="file" accept=".pdf"> raw local.


Scope

Aplica-se a todo app Koder que aceite, exiba, ou faça OCR de documentos: anexar PDF/DOCX/MD/KMD/TXT/ODT em chat ou formulário, preview inline (sem download), upload de resume/contract, OCR de foto (recibo, RG, contrato) para extração de texto.

Surfaces cobertas: Flutter mobile (Android + iOS), Flutter desktop (Linux + macOS + Windows), Flutter web ou templ+HTMX. TV/CLI/TUI fora de scope (sem use case típico).


1 — MUST: expose "Documento" toggle group in Settings

Sub-seção "Documento" do agrupamento "Mídia"; deve conter, na ordem:

  1. OCR (media.document.ocr) — toggle: ON habilita extração de texto de imagens
  2. OCR backend (media.document.ocr_backend) — dropdown: local (tesseract embarcado), koder (services/ai/ocr), auto (local-first, fallback Koder)
  3. OCR idioma padrão (media.document.ocr_lang) — dropdown: auto (detect) / pt-BR / en-US / es-ES / etc.
  4. Preview de PDF inline (media.document.pdf_preview) — checkbox; default ON; OFF força download

2 — MUST: defaults seguros em fresh install

ChaveDefaultNotas
media.document.ocrOFFPrivacy-by-default; OCR consome bateria e (se backend=koder) envia imagem; opt-in
media.document.ocr_backendlocalLocal-first; user pode trocar pra koder ou auto
media.document.ocr_langautoTesseract detecta; user pode forçar idioma específico
media.document.pdf_previewONPreview inline reduz friction; documents podem ser previewed sem download

3 — MUST: privacidade

  • NUNCA auto-upload de documento (user confirma antes do POST)
  • OCR local-first quando viável: tesseract embarcado roda sem network call; services/ai/ocr é fallback (precisa OK explícito via toggle backend=koder ou auto)
  • NUNCA OCR via serviços terceiros (Google Cloud Vision, AWS Textract, Azure Form Recognizer) — apenas tesseract local OU services/ai/ocr self-hosted
  • NUNCA persistir texto extraído em telemetria, error report, breadcrumb — apenas counter media.document.ocr_done
  • Preview de PDF in-app deve sanitizar JS embarcado (PDF.js com disableExternalLinks: true)

4 — MUST: widget surface no koder_kit

WidgetFunção
KoderDocumentPickerFile picker filtered ao MIME suportado; retorna KoderDocumentRef
KoderDocumentPreviewPreview inline (PDF.js no web; pdf_render em Flutter; nativo em iOS/Android Quick Look)
KoderOcrButtonTrigger OCR sobre KoderImageRef ou KoderDocumentRef; retorna String ou OcrError
KoderDocumentThumbnailRender de primeira página como thumb 256px

KoderDocumentRef: {uri, mime, sizeBytes, pageCount?, title?, koderUserId?, workspaceId?}.


5 — MUST: format support

Suportados (pick + preview): PDF, DOCX, ODT, MD, KMD (Koder Markdown — superset de MD usado em specs/RFCs/policies; mesmo renderer de MD com extensões Koder), TXT, RTF, EPUB, HTML (sandboxed).

OCR-able: JPEG, PNG, WebP, AVIF, HEIC, PDF (com imagem embarcada — extract pages → run OCR per page).

Not supported (rejected ao pick): executáveis (.exe, .dmg, .app), arquivos compactados quando não whitelisted, MIME types desconhecidos.

Upload size cap: 50 MB. Exceder → <APP>-DOC-SIZE-001.


6 — MUST: error surface

CenárioIDTexto pt-BR
Formato não suportado<APP>-DOC-FMT-001"Este tipo de arquivo não é suportado."
Tamanho excede 50 MB<APP>-DOC-SIZE-001"Documento muito grande. Reduza páginas ou comprima."
Preview falhou (corrupto / encriptado)<APP>-DOC-PRV-001"Não foi possível visualizar este documento."
OCR falhou (idioma não disponível local)<APP>-DOC-OCR-001"OCR não disponível para este idioma. Tente backend Koder."
OCR backend Koder indisponível<APP>-DOC-OCR-NET-001"Serviço de OCR indisponível. Tente novamente."
Upload falhou<APP>-DOC-NET-001"Falha ao enviar o documento. Tente novamente."
Arquivo rejeitado (executável / suspeito)<APP>-DOC-SEC-001"Este tipo de arquivo não pode ser anexado por segurança."

7 — Observability

  • Counters: media.document.picked, media.document.uploaded, media.document.ocr_done, media.document.ocr_error, media.document.preview_failed
  • Latency histograms: media.document.upload_ms, media.document.ocr_ms, media.document.preview_render_ms
  • Não emitir métricas que vazem conteúdo (page text, file path, título do documento, hash) — apenas counters + latência + dimensões anônimas (mime, page_count, size_bucket)

8 — Adoption checklist (per app)

  • Importa KoderMediaSettingsTile (sub-seção Documento visível)
  • Usa KoderDocumentPicker (nunca file_picker upstream raw)
  • Defaults da §2 respeitados
  • OCR backend default local (privacy-by-default §3)
  • Formats da §5 respeitados (executáveis rejeitados)
  • Error map da §6 implementado
  • Upload path respeita multi-tenancy/contract.kmd
  • Se OCR ativo: services/ai/ocr é único cloud backend permitido

Bridge com image.kmd

Quando o user tira foto de documento (cartão, contrato) com a câmera, o flow é:

  1. KoderImagePicker.camera()KoderImageRef
  2. App chama KoderOcrButton(imageRef)String texto extraído
  3. App pode tratar texto como busca, autofill de form, ou salvar como KoderDocumentRef MD

Não é necessário converter KoderImageRef em KoderDocumentRef — o OCR widget aceita ambos diretamente. Para document scanning multi-page (várias fotos → 1 PDF), usar KoderDocumentScanner (helper de alto nível que combina image.camera() em loop + auto-crop + merge PDF).


Non-normative — referências

  • Sibling specs: specs/media/image.kmd (camera bridge), specs/media/video.kmd, specs/media/audio.kmd
  • OCR backend self-hosted: services/ai/ocr/ — futuro componente da Koder Stack; até existir, local (tesseract) é o único permitido
  • Implementation surface: engines/sdk/koder_kit/lib/src/media/
  • Voice precedent (privacy contract): specs/voice/wake-word.kmd

Other media capabilities

Image

Capture, picker, preview, crop, and upload. EXIF stripping ON by default; widgets KoderImagePicker / KoderImagePreview / KoderImageCropper.

Video

Recording, playback, and screen capture. Recording indicator mandatory; codecs via engines/kodec; widgets KoderVideoPlayer / KoderVideoRecorder / KoderScreenCapture.

Audio

Memos, podcasts, attachments, ringtones — generic audio, separate from voice/wake-word. Widgets KoderAudioPlayer / KoderAudioRecorder.