# OCR de Cédula de Identidad Venezolana — Diseño y Plan de Desarrollo

Objetivo: validar automáticamente el documento de identidad del productor (cédula venezolana)
para habilitar la impresión del carnet. Reemplaza la revisión 100% manual del administrador por
una extracción asistida (humano-en-el-círculo) y, a futuro, por cruce de huella/foto.

Estado actual: contrato + servicio + motor *pendiente* ya implementados
(`app/Services/Ocr/*`). Falta el motor real.

---

## 1. Campos a extraer de la cédula venezolana (frente)

| Campo | Ejemplo | Formato objetivo |
|---|---|---|
| Nº de identidad | V-12345678 / E-87654321 | `[V-E-J-G-P]-\d{5,8}` |
| Nombre(s) | JUAN CARLOS | título (`Juan Carlos`) |
| Apellido(s) | PÉREZ GONZÁLEZ | título |
| Fecha de nacimiento | 15/03/1990 | `YYYY-MM-DD` |
| Sexo | M / F | `M` o `F` |
| Texto crudo (debug) | — | hasta 5000 chars |

Normalización ya implementada en `CedulaOcrService`.

---

## 2. Arquitectura

```
Foto (multipart) → FotoService (disc public)
   → DocumentoController::uploadCedula
       → CedulaOcrService::extraer($ruta)        [núcleo normalizador]
           → CedulaOcrInterface (motor inyectado)
                ├─ PendienteCedulaOcr        (hoy: devuelve "pendiente")
                ├─ TesseractCedulaOcr        (MVP recomendado)
                └─ (futuro) CNN / API externa (reconocimiento asistido)
   → `documentos_verificacion.ocr` (jsonb) → el admin APRUBA/RECHAZA (humano en el medio)
```

- El motor se inyecta vía `AppServiceProvider`; cambiar de motor = 1 línea.
- El OCR **nunca** bloquea la subida: si falla o no está soportado, el documento queda
  `pendiente` y el admin lo revisa como hoy.
- El resultado se guarda en la columna `ocr` (jsonb) de `documentos_verificacion`.

---

## 3. Motor MVP recomendado: Tesseract (Node.js) en un servicio lateral

### Por qué Node y no PHP
- Tesseract.js maduro en Node; hay paquete para entrenar con *language data* propia.
- La cédula venezolana tiene tipografía específica (OCR-B / letra de máquina); conviene
  un motor dedicado, no la engine `spa` genérica.

### Componentes
1. **Servicio Node** (`services/ocr/`):
   - API HTTP `POST /ocr/cedula` con multipart → devuelve JSON normalizado.
   - Preprocesado con `sharp`: escala → 1800px, grises, contraste, binarización,
     corrección de perspectiva (detección de esquinas).
   - `tesseract.js` con engine **entrenada para cédulas VE** (`ve-cedula.traineddata`).
   - Post-procesado: regex de cédula, fechas, capitalización; reescritura de
     `l`→`1`, `O`→`0` en el Nº de identidad.
2. **Backend**: `TesseractCedulaOcr` que hace `Http::post($OCR_URL.'/ocr/cedula', [...])`.
   - Config en `.env`: `OCR_CEDULA_URL=http://ocr:3000/api/ocr/cedula`.
   - timeout corto (5s) + retry 0 (mejor pendiente que falso).
3. **docker-compose**: servicio `ocr` junto a `db`/`backend`/`nginx`.

### Datos de entrenamiento
- Recolectar ~500-2000 imágenes de cédulas VE (frente) variadas (fondo, flashes, ángulos),
  anotadas con los 5 campos.
- Entrenar Tesseract LSTM (o usar `tesstrain`) con el juego de muestras; medir CER por campo.
- Meta de calidad umbral: confianza ≥ 0.80 y cédula validada por dígito verificador.

---

## 4. Reglas de negocio y umbrales de confianza

| confianza | Acción |
|---|---|
| ≥ 0.85 y cédula == cédula del productor | **Pre-aprobar** (admin solo confirma) |
| ≥ 0.60 | **Sugerir** datos al admin (compara visualmente) |
| < 0.60 / no soportado | Revisión manual completa (comportamiento actual) |

- La **cédula extraída debe coincidir** con la cédula de la cuenta (`users.cedula`).
  Si no coincide → rechazo automático con motivo "El documento no corresponde a la cédula registrada".
- El admin SIEMPRE tiene la última palabra en `admin/documentos/{id}/verificar`.

---

## 5. Fases

| Fase | Alcance | Entregable |
|---|---|---|
| 0 (hecha) | Contrato + servicio + motor pendiente + cableado | Flujo invariable con OCR apagado |
| 1 | Servicio Node Tesseract + preprocesado sharp + endpoint | OCR básico del frente |
| 2 | Recopilación/anotación de cédulas VE + engine propia + umbrales | Calidad de campo |
| 3 | Sugerencia al admin (UI) + rechazo automático por cédula distinta | Producto usable |
| 4 | (Opcional) cruce de foto selfie vs foto cédula (verificación facial) | Anti-suplantación |

---

## 6. Riesgos / privacidad

- **Datos biométricos/PII**: las imágenes y lecturas son datos sensibles (LOPDP de Venezuela).
  Guardar en `storage` protegido, registro en `auditoria`, retención documentada.
- **Falsos positivos de OCR**: la validación humana (Fase 3) mitiga; nunca aprobar de forma
  100% autónoma sin umbral alto + dígito verificador de la cédula.
- **Latencia/offline**: el OCR corre en el servidor; la captura offline del censo no depende de él.
