# EpicrisisIA

EpicrisisIA es una aplicación web construida con FastAPI para procesar documentos clínicos, extraer texto desde PDFs, estructurar información médica con modelos de lenguaje, asignar códigos CIE-10 y CUPS, y ofrecer soporte de consulta y validación SOAT para el contexto colombiano.

El proyecto está orientado a flujos de trabajo de análisis de historias clínicas, documentos quirúrgicos, facturación y generación de epicrisis, con almacenamiento en MongoDB y componentes de búsqueda semántica basados en FAISS.

## Extracción de identidad documental

La extracción de `patient_name`, `patient_id` y `case_number` sigue una política conservadora:

- `app/services/patient_name_extraction.py` mantiene el extractor general compartido y debe permanecer estable.
- Si un flujo necesita leer identidad con heurísticas distintas, debe crear un extractor especializado o una estrategia nueva, sin endurecer el extractor general.
- Los consumidores sensibles, como historia clínica individual o prefactura, deben seleccionar explícitamente la estrategia de identidad adecuada.
- Cuando no exista contexto suficiente, el default es el extractor general.

## Funcionalidades principales

- Autenticación web con JWT almacenado en cookie HTTP-only.
- Gestión básica de usuarios y panel administrativo.
- Carga de PDFs clínicos y extracción de texto.
- Análisis de historia clínica y de texto médico estructurado con LLM.
- Procesamiento de documentos adicionales: laboratorio, radiología, prescripción, documento quirúrgico y factura.
- Carga masiva asíncrona por ZIP con seguimiento por lote.
- Codificación automática de diagnósticos con CIE-10.
- Codificación automática de procedimientos con CUPS.
- Indexación, consulta y apoyo documental sobre el manual SOAT.
- Generación y visualización de epicrisis y vistas por paciente.

## Arquitectura general

La estructura principal del repositorio es:

- `app/`: aplicación FastAPI, configuración, autenticación, startup, rutas y servicios.
  - Incluye `app/batch_processing/` para el pipeline desacoplado de carga masiva.
- `modules/`: procesamiento, RAG, embeddings, acceso a MongoDB, indexadores y lógica de soporte.
- `web/`: plantillas HTML renderizadas con Jinja2.
- `static/`: recursos estáticos.
- `logs/`: logs locales.
- Archivos de datos y referencia:
  - `cie10_estructura_completa.json`
  - `TablaReferencia_CUPS__1.xlsx`
  - `Manual-SOAT-2025.pdf`

### Punto de entrada vigente

El entrypoint actual del proyecto es:

```bash
uvicorn app.main:app --host 0.0.0.0 --port 7000 --reload
```

El archivo principal de arranque es:

- `app/main.py`

Si encuentras referencias antiguas a `app/main_CIE10.py`, deben considerarse desactualizadas para el estado actual de este repositorio.

## Requisitos previos

Para ejecutar el proyecto correctamente se recomienda contar con:

- Python 3.12.
- `pip` y `venv`.
- `uv` opcional para desarrollo local.
- MongoDB accesible, local o remoto.
- Redis accesible para procesamiento batch con Celery (recomendado para entornos no locales).
- `GROQ_API_KEY` válida para el flujo principal de análisis.
- `GEMINI_API_KEY` opcional si deseas usar Gemini en flujos habilitados.
- Recursos de CPU y memoria suficientes para generar y cargar índices FAISS y embeddings.
- Para producción, un servidor Linux compatible, idealmente Ubuntu o Debian.

### Consideraciones importantes

- Si MongoDB tiene autenticación habilitada, el usuario configurado en `MONGO_URI` debe tener permisos sobre la base definida en `DB_NAME`.
- Para que la codificación CIE-10 y CUPS funcione correctamente, los índices FAISS deben existir o generarse previamente.
- El soporte SOAT avanzado requiere un índice `soat_faiss`; si no existe, esa funcionalidad queda limitada o deshabilitada.

## Variables de entorno

La configuración se carga desde el archivo `.env`. Estas son las variables más relevantes:

### Obligatorias para uso normal

- `MONGO_URI`: cadena de conexión a MongoDB.
- `DB_NAME`: nombre de la base de datos.
- `GROQ_API_KEY`: clave para el proveedor principal de LLM.
- `SECRET_KEY`: clave para firmar los tokens JWT.
- `ADMIN_USERNAME`: usuario administrador inicial.
- `ADMIN_PASSWORD`: contraseña del usuario administrador inicial.

### Recomendadas

- `COLLECTION_NAME`: colección principal para almacenamiento de PDFs.
- `LLM_PROVIDER`: proveedor principal (`groq` o `gemini`).
- `ADMIN_FORCE_RESET`: si vale `1`, `true` o `yes`, fuerza el reseteo de la contraseña del admin al ejecutar el bootstrap explícito.
- `BATCH_DISPATCHER`: modo de ejecución batch (`inprocess` o `celery`).

### Opcionales

- `GEMINI_API_KEY`
- `GOOGLE_API_KEY`
- `REDIS_URL` (broker/backend para Celery)
- Variables de auditoría:
  - `AUDIT_LOG_ENABLED`
  - `AUDIT_LOG_FILE`
  - `AUDIT_LOG_LEVEL`
  - `AUDIT_MONGO_ENABLED`
  - `AUDIT_RETENTION_DAYS`
- Variables avanzadas de modelos:
  - `GROQ_MODEL_DEFAULT`
  - `GROQ_MODEL_CLINICAL`
  - `GROQ_MODEL_SOAT`
  - `GROQ_MODEL_CIE10`
  - `GROQ_MODEL_CUPS`
  - `GROQ_MODEL_RESUMEN`
  - `GROQ_MODEL_HISTORIA`
  - `GROQ_MODEL_HISTORIA_LIGHT`
  - `GROQ_MODEL_LLM1`
  - `GEMINI_MODEL_DEFAULT`
  - `GEMINI_MODEL_HISTORIA`

### Ejemplo de `.env`

```env
MONGO_URI=mongodb://epicrisis_app:TU_PASSWORD@localhost:27017/Epicrisis?authSource=Epicrisis
DB_NAME=Epicrisis
COLLECTION_NAME=HistoriaClinica
SECRET_KEY=cambia-esta-clave
GROQ_API_KEY=tu_clave_groq
GEMINI_API_KEY=
LLM_PROVIDER=groq
ADMIN_USERNAME=admin
ADMIN_PASSWORD=cambia-esta-clave
ADMIN_FORCE_RESET=0
REDIS_URL=redis://localhost:6379
BATCH_DISPATCHER=inprocess
AUDIT_LOG_ENABLED=true
AUDIT_LOG_FILE=logs/audit.jsonl
AUDIT_LOG_LEVEL=INFO
AUDIT_MONGO_ENABLED=true
AUDIT_RETENTION_DAYS=180
```

## Auditoría y logs

El runtime web/worker ahora emite:

- logs técnicos a consola con `trace_id` y `request_id`,
- eventos de auditoría estructurados a `logs/audit.jsonl`,
- y persistencia best-effort en MongoDB en la colección `audit_events`.

La auditoría está diseñada con política `metadata only`: no debe almacenar texto clínico crudo, prompts completos, respuestas completas del modelo, cookies, JWT ni llaves de API.

## Ejecución en local

Esta es la secuencia recomendada para dejar el proyecto funcionando en desarrollo local.

El flujo local con `uv` usa `pyproject.toml` y `uv.lock` como fuente de verdad.
Los archivos `requirements.txt` y `requirements-dev.txt` se mantienen como exports
compatibles para entornos que siguen instalando con `pip`.
El `Makefile` está preparado para Linux/macOS y Windows nativo con PowerShell.

### 1. Ubicarse en el repositorio

```bash
cd /ruta/al/proyecto/epicrisis27022026
```

### 2. Crear el entorno virtual

Opción recomendada para desarrollo local con `uv`:

```bash
uv venv --python 3.12 .venv
```

Opción compatible con producción usando `pip`:

```bash
python3 -m venv .venv
```

### 3. Activar el entorno virtual

En Linux/macOS:

```bash
source .venv/bin/activate
```

En Windows PowerShell:

```powershell
.venv\Scripts\Activate.ps1
```

Si usas los targets del `Makefile`, no necesitas activar el entorno manualmente.

### 4. Instalar dependencias

Con `uv`:

```bash
uv sync --dev
```

Con `make` en Linux/macOS o Windows PowerShell:

```bash
make uv-sync
```

Con `pip`:

```bash
python -m pip install --upgrade pip
pip install -r requirements.txt -r requirements-dev.txt
```

### 5. Configurar el archivo `.env`

- Crea o ajusta el archivo `.env`.
- Verifica que `MONGO_URI` sea válido.
- Verifica que el usuario de Mongo tenga permisos sobre `DB_NAME`.
- Asegura que `GROQ_API_KEY` esté configurada.

### 6. Verificar MongoDB

Antes de arrancar la aplicación:

- Asegúrate de que `mongod` esté levantado.
- Si usas autenticación, confirma que el usuario del `MONGO_URI` tenga al menos permisos `readWrite` y `dbAdmin` sobre `Epicrisis`.
- Si la base no existe, MongoDB la creará en el primer `insert`, pero solo si el usuario tiene permisos para ello.

En Linux, una validación típica sería:

```bash
systemctl status mongod
```

Si el servicio no está activo:

```bash
sudo systemctl start mongod
```

### 7. Generar índices FAISS requeridos

#### Índice CIE-10

```bash
python -m modules.processing.cie10.Carga_estructura
```

Con `uv`:

```bash
uv run python -m modules.processing.cie10.Carga_estructura
```

Esto genera el índice principal de CIE-10 en `faiss_principal_jerarquico/`.

#### Índice CUPS

```bash
python -m modules.processing.cie10.carga_cups
```

Con `uv`:

```bash
uv run python -m modules.processing.cie10.carga_cups
```

Esto genera el índice de procedimientos en `cups_faiss/`.

#### Índice SOAT (opcional)

```bash
python -m modules.processing.soat.soat_indexer --pdf Manual-SOAT-2025.pdf --out soat_faiss
```

Con `uv`:

```bash
uv run python -m modules.processing.soat.soat_indexer --pdf Manual-SOAT-2025.pdf --out soat_faiss
```

Este paso es recomendado si vas a usar el módulo SOAT completo.

### 8. Aplicar migraciones MongoDB

```bash
python -m app.migrations.run
```

Con `uv`:

```bash
uv run python -m app.migrations.run
```

### 9. Bootstrap explícito del usuario admin

```bash
python -m app.scripts.bootstrap_admin
```

Con `uv`:

```bash
uv run python -m app.scripts.bootstrap_admin
```

### 10. Warmup opcional de recursos pesados

```bash
python -m app.scripts.warmup_resources --resource cie10 --resource cups
```

Con `uv`:

```bash
uv run python -m app.scripts.warmup_resources --resource cie10 --resource cups
```

Si también vas a usar SOAT, puedes precargarlo con:

```bash
python -m app.scripts.warmup_resources --resource soat
```

Con `uv`:

```bash
uv run python -m app.scripts.warmup_resources --resource soat
```

### 11. Arrancar la aplicación

```bash
uvicorn app.main:app --host 0.0.0.0 --port 7000 --reload
```

Con `uv`:

```bash
uv run uvicorn app.main:app --host 0.0.0.0 --port 7000 --reload
```

Si quieres un flujo más corto para desarrollo local, el repositorio ahora incluye atajos:

```bash
make uv-sync
make deps-export
make run
make test
make lint
```

En Windows PowerShell los mismos targets funcionan igual:

```powershell
make uv-sync
make run
make worker
```

### 12. Abrir la aplicación

Abre en tu navegador:

```text
http://localhost:7000/login
```

### 13. Primer acceso

El usuario administrador ya no se crea durante el startup web. El bootstrap explícito usa:

- `ADMIN_USERNAME`
- `ADMIN_PASSWORD`

Si el usuario ya existe:

- lo deja intacto por defecto,
- o actualiza la contraseña si `ADMIN_FORCE_RESET=1`.

### 14. Rutas recomendadas para validar el arranque

Después del login, puedes validar el entorno con:

- `GET /login`
- `GET /dashboard`
- `GET /subir_documento`
- `GET /subir_lote`
- `GET /health`
- `GET /ready`

## Batch Processing

El flujo del procesamiento por lotes quedó implementado como un módulo desacoplado en:

- `app/batch_processing/domain/`
- `app/batch_processing/application/`
- `app/batch_processing/infrastructure/`
- `app/routes/batches.py`

### Qué hace el pipeline batch

1. Recibe un ZIP en `POST /api/lotes`.
2. Guarda el ZIP y crea el lote con estado inicial.
3. Descomprime de forma segura (rechaza path traversal y archivos no soportados).
4. Procesa PDFs válidos (extracción de texto, clasificación heurística y asociación de caso).
5. Persiste trazabilidad por archivo y estado agregado del lote.

### Colecciones MongoDB usadas por batch

- `processing_batches`: estado global del lote.
- `processing_batch_files`: estado y resultado por archivo.
- `processing_batch_cases`: casos consolidados para extensiones futuras.

### Endpoints batch disponibles

- `GET /subir_lote`
- `POST /api/lotes`
- `GET /api/lotes/{batch_id}`
- `GET /api/lotes/{batch_id}/documentos`
- `GET /api/lotes/{batch_id}/pendientes`
- `GET /api/lotes/{batch_id}/casos`
- `PATCH /api/lotes/{batch_id}/documentos/{file_id}/asociacion`

### Trazabilidad HU-26 en detalle por archivo

`GET /api/lotes/{batch_id}/documentos` incluye ahora:

- `associated_user` (mapeado a identidad de paciente)
- `association_source` (`auto` / `manual`)
- `score_breakdown` (aporte por señal al score)
- `top_candidates` (casos mejor rankeados)
- `manual_resolution` (usuario, fecha y motivo cuando aplica)

## Redis y Celery para batch processing

`BATCH_DISPATCHER` define cómo se ejecuta el procesamiento batch:

- `inprocess`: ejecuta el lote en un thread local del proceso web (útil en desarrollo).
- `celery`: orquesta fan-out real por archivo (`prepare_batch_job` -> `process_batch_file_job` -> `finalize_batch_job`) usando Redis y worker externo (recomendado en staging/prod).

### Instalación de Redis

#### Ubuntu / Debian

```bash
sudo apt-get install lsb-release curl gpg
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis
sudo apt-get install redis-server redis-sentinel redis-tools
sudo systemctl enable redis-server
sudo systemctl start redis-server
```

#### macOS (Homebrew)

```bash
brew install redis
brew services start redis
redis-cli ping
```

#### Alternativa rápida con Docker

```bash
docker run -d --name epicrisis-redis -p 6379:6379 redis:7
```

### Configuración mínima en `.env`

```env
REDIS_URL=redis://localhost:6379
BATCH_DISPATCHER=celery
```

### Arranque de FastAPI + Celery

En una terminal:

```bash
uvicorn app.main:app --host 0.0.0.0 --port 7000 --reload
```

En otra terminal (mismo entorno virtual activo):

```bash
celery -A app.batch_processing.celery_app.celery_app worker --loglevel=INFO
```

Si Redis y el worker están correctos, los lotes creados en `/subir_lote` se procesan por cola.

### Verificación rápida de Redis y Celery

```bash
redis-cli ping
```

Debe responder `PONG`.

Luego crea un lote en la UI o invoca `POST /api/lotes` y valida logs del worker Celery.

## Troubleshooting en local

### `ModuleNotFoundError: No module named 'fastapi'`

- Síntoma: la app no arranca o falla al importar módulos.
- Causa probable: no instalaste las dependencias en el entorno virtual activo.
- Acción correctiva:

```bash
source .venv/bin/activate
make uv-sync
```

Ruta compatible con `pip`:

```bash
pip install -r requirements.txt -r requirements-dev.txt
```

### `RuntimeError: Falta la variable de entorno requerida: GROQ_API_KEY`

- Síntoma: el arranque falla al construir servicios.
- Causa probable: `GROQ_API_KEY` no está en `.env`.
- Acción correctiva: agregar la variable y reiniciar el proceso.

### `pymongo.errors.OperationFailure: not authorized on Epicrisis...`

- Síntoma: Mongo rechaza consultas o escrituras.
- Causa probable: el usuario del `MONGO_URI` no tiene permisos sobre la base `Epicrisis`.
- Acción correctiva:
  - revisar permisos del usuario,
  - crear un usuario con acceso a `Epicrisis`,
  - o ajustar `MONGO_URI` para usar un usuario autorizado.

### `Error 111 connecting to localhost:6379` (Redis no disponible)

- Síntoma: Celery no inicia o los lotes quedan encolados sin ejecutar.
- Causa probable: Redis no está instalado, no está activo o `REDIS_URL` es incorrecta.
- Acción correctiva:

```bash
sudo systemctl status redis-server
redis-cli -u "$REDIS_URL" ping
```

Si no responde `PONG`, corrige el servicio/URL y reinicia worker.

### El lote queda en `recibido` o `preparando` y no avanza con `BATCH_DISPATCHER=celery`

- Síntoma: FastAPI responde `202` pero no hay progreso en `/api/lotes/{batch_id}`.
- Causa probable: worker Celery no está corriendo o usa otro entorno/URL.
- Acción correctiva:

```bash
celery -A app.batch_processing.celery_app.celery_app worker --loglevel=INFO
```

Verifica también:

- que el comando se ejecute con el mismo `.venv`,
- que `BATCH_DISPATCHER=celery`,
- que `REDIS_URL` sea la misma en app y worker.

### `Indice FAISS CIE-10 no disponible`

- Síntoma: la codificación CIE-10 falla o queda en estado pendiente.
- Causa probable: no existe `faiss_principal_jerarquico/`.
- Acción correctiva:

```bash
python -m modules.processing.cie10.Carga_estructura
```

### `Indice FAISS CUPS no disponible`

- Síntoma: la codificación CUPS falla o no devuelve resultados.
- Causa probable: no existe `cups_faiss/`.
- Acción correctiva:

```bash
python -m modules.processing.cie10.carga_cups
```

### El índice `soat_faiss` no existe

- Síntoma: endpoints SOAT muestran errores de índice no inicializado o capacidades parciales.
- Causa probable: no se generó el índice SOAT.
- Acción correctiva:

```bash
python -m modules.processing.soat.soat_indexer --pdf Manual-SOAT-2025.pdf --out soat_faiss
```

### Problemas de login con `admin`

- Síntoma: no puedes entrar con el usuario esperado.
- Causa probable:
  - el usuario no fue creado por falta de permisos en Mongo,
  - la contraseña cambió por `ADMIN_FORCE_RESET`,
  - o el `.env` no coincide con lo esperado.
- Acción correctiva:
  - revisar logs de arranque,
  - confirmar permisos en Mongo,
  - validar `ADMIN_USERNAME`, `ADMIN_PASSWORD` y `ADMIN_FORCE_RESET`.

## Despliegue en servidor Linux

La siguiente guía describe un despliegue recomendado para un servidor Linux tradicional, sin asumir Docker como camino principal.

## 1. Preparación del servidor

Se recomienda:

- Crear un usuario de sistema dedicado, por ejemplo `epicrisis`.
- Instalar paquetes base:
  - `python3`
  - `python3-venv`
  - `python3-pip`
  - `redis-server`
  - `mongodb` o acceso a un Mongo externo
  - `nginx` opcional como reverse proxy
- Copiar el proyecto al servidor en un directorio controlado, por ejemplo `/opt/epicrisis`.

Ejemplo en Ubuntu/Debian:

```bash
sudo apt update
sudo apt install -y python3 python3-venv python3-pip redis-server nginx
sudo systemctl enable redis-server
sudo systemctl start redis-server
```

Si MongoDB corre en el mismo servidor, asegúrate de instalarlo y configurarlo por separado, con autenticación y roles mínimos.

## 2. Configuración de la aplicación

Dentro del servidor:

```bash
cd /opt/epicrisis
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txt
```

Luego:

- Crea el archivo `.env` de producción.
- Usa claves y contraseñas distintas a las de desarrollo.
- Configura `MONGO_URI` contra un usuario con permisos mínimos necesarios.
- Si usarás procesamiento batch asíncrono (recomendado), configura:
  - `BATCH_DISPATCHER=celery`
  - `REDIS_URL=redis://localhost:6379`

Genera también los índices requeridos:

```bash
python -m modules.processing.cie10.Carga_estructura
python -m modules.processing.cie10.carga_cups
python -m modules.processing.soat.soat_indexer --pdf Manual-SOAT-2025.pdf --out soat_faiss
```

Antes de crear servicios del sistema, valida que la app arranque manualmente:

```bash
uvicorn app.main:app --host 127.0.0.1 --port 7000
```

## 3. Ejecución como servicios con `systemd` (API + colas)

En producción se recomienda ejecutar API y worker de colas como servicios separados.

### 3.1 Servicio de API FastAPI

Archivo sugerido: `/etc/systemd/system/epicrisis-api.service`

```ini
[Unit]
Description=EpicrisisIA FastAPI Service
After=network.target

[Service]
User=epicrisis
Group=epicrisis
WorkingDirectory=/opt/epicrisis
EnvironmentFile=/opt/epicrisis/.env
ExecStart=/opt/epicrisis/.venv/bin/uvicorn app.main:app --host 127.0.0.1 --port 7000
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

### 3.2 Servicio de worker Celery (gestión de colas)

Archivo sugerido: `/etc/systemd/system/epicrisis-worker.service`

```ini
[Unit]
Description=EpicrisisIA Celery Worker
After=network.target redis-server.service
Wants=redis-server.service

[Service]
User=epicrisis
Group=epicrisis
WorkingDirectory=/opt/epicrisis
EnvironmentFile=/opt/epicrisis/.env
ExecStart=/opt/epicrisis/.venv/bin/celery -A app.batch_processing.celery_app.celery_app worker --loglevel=INFO --hostname=epicrisis@%h --concurrency=2
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
```

Notas:

- Esto es un ejemplo de referencia para el README, no una configuración ya aplicada.
- No uses `--reload` en producción.
- Si cambias `REDIS_URL` o `BATCH_DISPATCHER`, reinicia API y worker.
- Ajusta `--concurrency` según CPU/memoria disponibles.

Después de crear ambos servicios:

```bash
sudo systemctl daemon-reload
sudo systemctl enable epicrisis-api epicrisis-worker
sudo systemctl start epicrisis-api epicrisis-worker
sudo systemctl status redis-server epicrisis-api epicrisis-worker
```

### 3.3 Operación y monitoreo de colas en Linux

Ver logs en tiempo real del worker:

```bash
sudo journalctl -u epicrisis-worker -f
```

Reiniciar solo el worker (sin tumbar la API):

```bash
sudo systemctl restart epicrisis-worker
```

Validar que Celery responde (desde `/opt/epicrisis`):

```bash
source .venv/bin/activate
celery -A app.batch_processing.celery_app.celery_app inspect ping
celery -A app.batch_processing.celery_app.celery_app inspect active
```

Inspeccionar backlog aproximado de la cola por defecto:

```bash
redis-cli -u "$REDIS_URL" LLEN celery
```

Si el backlog crece y no baja:

- confirma `BATCH_DISPATCHER=celery` en `.env`,
- verifica que `REDIS_URL` sea la misma en API y worker,
- aumenta `--concurrency` o ejecuta un segundo worker.

## 3.4 Contenedor all-in-one para consola Linux

Este repositorio ahora incluye un empaquetado Docker de una sola imagen que levanta:

- `mongod`
- `redis-server`
- worker `Celery`
- `uvicorn`

Advertencia operativa:

- Esta topologÃ­a simplifica despliegue en un servidor con acceso solo por consola.
- No es la arquitectura recomendada para alta disponibilidad ni escalado independiente de MongoDB, Redis, API y worker.
- Para producciÃ³n mÃ¡s exigente, separa los servicios.

### Archivos incluidos

- `Dockerfile`
- `docker/entrypoint.sh`
- `docker/healthcheck.sh`
- `docker/supervisord.conf`
- `docker/env.example`
- `docker-compose.yml`

### Variables de entorno adicionales

- `MONGO_APP_DATABASE`: base interna donde se crea el usuario de aplicaciÃ³n.
- `MONGO_APP_USERNAME`: usuario interno de MongoDB.
- `MONGO_APP_PASSWORD`: contraseÃ±a del usuario interno de MongoDB. Si no se define, el contenedor genera una clave interna aleatoria y la persiste en `/data/runtime/.mongo_app_password`.
- `MONGO_APP_FORCE_RESET`: si vale `1`, actualiza la clave del usuario Mongo existente.
- `EPICRISIS_AUTO_MIGRATE`: ejecuta migraciones al iniciar.
- `EPICRISIS_AUTO_BOOTSTRAP_ADMIN`: ejecuta bootstrap explÃ­cito del admin al iniciar.
- `EPICRISIS_AUTO_WARMUP`: precarga opcional de recursos pesados.
- `EPICRISIS_WARMUP_RESOURCES`: lista separada por comas, por ejemplo `cie10,cups`.

### ConstrucciÃ³n

```bash
docker build -t epicrisisia-all-in-one .
```

### EjecuciÃ³n con `docker run`

1. Copia `docker/env.example` a un archivo local de despliegue, por ejemplo `deploy.env`.
2. Ajusta al menos:
   - `SECRET_KEY`
   - `ADMIN_PASSWORD`
   - `GROQ_API_KEY` o `GEMINI_API_KEY`

Ejemplo:

```bash
docker run -d \
  --name epicrisisia \
  -p 7000:7000 \
  --env-file deploy.env \
  -v epicrisis-data:/data \
  epicrisisia-all-in-one
```

### EjecuciÃ³n con Docker Compose

```bash
cp docker/env.example .env.docker
docker compose --env-file .env.docker up -d --build
```

Si omites `MONGO_APP_PASSWORD`, el primer arranque generarÃ¡ una clave interna persistente para MongoDB.

### Persistencia

El volumen `/data` almacena:

- datos de MongoDB,
- datos append-only de Redis,
- `logs/`,
- `_batch_uploads/`,
- `_batch_extracted/`,
- `_batch_reports/`,
- `_individual_uploads/`,
- `faiss_principal_jerarquico/`,
- `cups_faiss/`,
- `soat_faiss/`.

### OperaciÃ³n desde consola

Ver estado:

```bash
docker ps
docker inspect --format='{{.State.Health.Status}}' epicrisisia
```

Ver logs:

```bash
docker logs -f epicrisisia
```

Entrar al contenedor:

```bash
docker exec -it epicrisisia bash
```

Detener e iniciar:

```bash
docker stop epicrisisia
docker start epicrisisia
```

### Notas de inicializaciÃ³n

- El entrypoint crea un usuario de aplicaciÃ³n en MongoDB dentro de `MONGO_APP_DATABASE`.
- Luego ejecuta `python -m app.migrations.run`.
- DespuÃ©s ejecuta `python -m app.scripts.bootstrap_admin`.
- Finalmente arranca `mongod`, `redis-server`, Celery y FastAPI bajo `supervisord`.

### Restricciones de esta modalidad

- El contenedor corre varios procesos; si necesitas escalar worker y API por separado, esta imagen deja de ser suficiente.
- MongoDB y Redis quedan encapsulados en la misma unidad de despliegue, por lo que el backup y la observabilidad deben planearse a nivel de volumen.
- El primer arranque puede tardar mÃ¡s si activas `EPICRISIS_AUTO_WARMUP=1`.

## 4. Reverse proxy con Nginx

Se recomienda publicar la aplicación detrás de Nginx.

Ejemplo de configuración mínima:

```nginx
server {
    listen 80;
    server_name tu-dominio-o-ip;

    location / {
        proxy_pass http://127.0.0.1:7000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

Después:

```bash
sudo nginx -t
sudo systemctl reload nginx
```

## 5. HTTPS y seguridad

Para producción:

- Usa TLS con Let's Encrypt o un certificado equivalente.
- No expongas `uvicorn` directamente a Internet.
- Restringe CORS; el código actual permite `allow_origins=["*"]`, lo cual no es recomendable para producción.
- Usa un `SECRET_KEY` fuerte y único.
- No uses credenciales por defecto.
- Rota contraseñas de administración y de MongoDB.
- Usa usuarios de MongoDB con permisos mínimos.
- Restringe acceso al puerto `27017` para que no quede expuesto públicamente.

## Recomendaciones operativas para Linux

- Ejecuta la aplicación con un usuario no root.
- Mantén separados los logs de aplicación, MongoDB y Nginx.
- Implementa backups periódicos de MongoDB.
- Monitorea consumo de memoria y CPU, especialmente al generar o cargar embeddings e índices.
- Verifica que el usuario configurado en `MONGO_URI` tenga permisos correctos sobre `Epicrisis`.
- Mantén `.env` fuera de repositorios públicos y con permisos restringidos.
- Verifica que los directorios `faiss_principal_jerarquico/`, `cups_faiss/` y `soat_faiss/` existan después de cada despliegue.
- Usa `--reload` solo en desarrollo.
- Si el tráfico crece, considera migrar de `uvicorn` simple a `gunicorn` con workers Uvicorn.

## Endpoints y rutas útiles

Estas rutas sirven como referencia rápida para validar el sistema:

- `GET /login`
- `GET /dashboard`
- `POST /upload_pdf`
- `POST /upload_documento_adicional`
- `GET /subir_lote`
- `POST /api/lotes`
- `GET /api/lotes/{batch_id}`
- `GET /api/lotes/{batch_id}/documentos`
- `GET /procesar_ultimo_pdf`
- `POST /soat/indexar_pdf`
- `POST /soat/chat`

## Estado actual y notas de mantenimiento

- El proyecto está en estado MVP.
- Puede existir documentación interna heredada que no refleje exactamente el estado actual del código.
- Debes revisar compatibilidad entre la versión de Python y ciertas dependencias del stack LangChain / Transformers.
- Antes de un uso productivo, conviene validar seguridad, observabilidad, rendimiento y tolerancia a fallos.
- Si la aplicación evoluciona, actualiza este README junto con el entrypoint real, variables de entorno y procesos de despliegue.
