NOVATECS AGENTS · M3
Presentación técnica · Contratos
← Volver a Agentes

Módulo 3 — Contratos

Siete agentes IA cubren el ciclo de vida del contrato: generación con plantillas Jinja2 + WeasyPrint, firma electrónica vía Mifiel con multi-firmante y QR móvil, vigilancia diaria de vencimientos, renovación automática, y OCR Vision para contratos legacy. Retention SAT 7 años cumplida automáticamente.

1 supervisor + 7 agentes LangGraph Mifiel firma electrónica QR móvil Cron diario 06:00 Retention 7 años

Arquitectura — 1 supervisor + 7 agentes IA

Supervisor Sonnet con LangGraph. Generador + validadores para el frontend, comunicador para outbound, vigilante + renovador como cron, lector como OCR legacy.

SUPERVISOR M3
Orquestador principal
Recibe triggers: crear contrato, webhook Mifiel, cron vigilante, upload legacy PDF. Decide qué sub-agente invocar con recursion_limit=25. Regla: toda comunicación outbound pasa por Comunicador M3.
Sonnet 4.6LangGraph create_supervisor
1 · GENERADOR
Plantilla Jinja2 → PDF
Renderiza plantilla con SandboxedEnvironment (no escape posible) + variables proveedor + items. Genera PDF con WeasyPrint. Sube a Supabase Storage y crea row contratos en estado borrador.
SonnetJinja2 sandboxWeasyPrint
2 · VALIDADOR_COMPLETITUD
Pre-envío a firma
Chequea que todos los campos obligatorios de la plantilla estén llenos (fechas, partes, monto, cláusulas). Si falla, bloquea envío a Mifiel y lista faltantes al usuario.
Sonnetschema validation
3 · VALIDADOR_FIRMA
Webhook Mifiel idempotente
Recibe webhooks de Mifiel en cada firma del proveedor. Idempotente: reenvíos no duplican transiciones. Actualiza estado enviado_firma → firmado_parcial → firmado_completo.
HaikuMifiel webhookidempotent
4 · COMUNICADOR_M3
Notifica al proveedor
Envía WA/email en cada transición: "contrato enviado a firma", "esperamos tu firma", "contrato completado". Respeta simulation_mode para testing sin consumir Mifiel credits.
HaikuWhatsApp + Email
5 · VIGILANTE
Cron diario 06:00
Barrido diario (systemd timer) que detecta: contratos que vencen en 30/15/7 días, atrasos en firma, vencimientos hoy. Dispara Comunicador para nudge o Renovador para pre-crear renovación.
Haikusystemd timer06:00 AM
6 · RENOVADOR
Clone + deltas automáticos
Cuando un contrato está próximo a vencer, clona todas las cláusulas y aplica deltas (nuevas fechas, monto actualizado, etc). Deja renovación en borrador para revisión humana antes de mandar firma.
Sonnetjinja2 deep clone
7 · LECTOR OCR
Vision para legacy PDFs
Para contratos ya firmados fuera del sistema (escaneos, PDFs viejos), Claude Vision extrae partes, fechas, monto, cláusulas clave. Guarda con origen='legacy_importado' + confianza por campo.
Sonnet VisionJSON extract

Flujo happy path — contrato firmado digital

De creación a firma completa, con Mifiel + QR móvil multi-firmante.

1
Usuario crea contrato desde dashboard
Selecciona proveedor (debe estar aprobado en M1), elige plantilla, llena variables. Click Generar.
API: POST /api/contratos
2
Generador renderiza Jinja2 + PDF
SandboxedEnvironment protege contra injection en variables. WeasyPrint con timeout 10s (ThreadPoolExecutor, thread-safe en gunicorn). PDF a Supabase Storage.
generador
3
Validador_completitud pre-envío
Checkea campos obligatorios. Si OK, estado pasa a validado. Si falla, lista faltantes y bloquea.
validador_completitud
4
Comunicador envía a Mifiel
API Mifiel con simulation_mode=true por default para testing. Crea documento en Mifiel, obtiene URL firma + token QR para cada firmante proveedor.
comunicador · Mifiel API
5
Proveedor recibe WA con link + QR
Multi-firmante: cada persona del proveedor recibe su propio link. QR móvil abre /firma/<token> pública, optimizada para celular.
comunicador_m3
6
Primera firma → webhook Mifiel
Validador_firma recibe webhook (HMAC verify), procesa idempotente. Estado: firmado_parcial. Comunicador notifica "firma parcial recibida".
validador_firma
7
Segunda firma → completo
Todas las firmas proveedor recibidas. Estado: firmado_completo. Mifiel genera PDF final firmado. Se guarda URL definitiva en contratos.pdf_firmado_url.
validador_firma
8
Comunicador celebra con proveedor
WA "Tu contrato está firmado y archivado. Copia: {URL}". Email con PDF adjunto. Evento en tab Historial.
comunicador_m3
9
Vigilante agenda recordatorios
Cron diario 06:00 monitorea fecha_vencimiento. A los 30d, 15d, 7d antes → nudge. Al vencimiento → disparo Renovador.
vigilante (cron)
10
Renovador pre-crea renovación
Clona cláusulas, aplica deltas (fechas nuevas, monto ajustado por inflación si aplica), deja en borrador. Usuario revisa y dispara nuevo ciclo de firma.
renovador

Máquina de estados del contrato

8 estados. legacy_importado es terminal para contratos ya firmados fuera.

borrador
enviado_firma
firmado_parcial
firmado_completo
vencido
renovado
legacy_importado
cancelado
borrador ─→ enviado_firma ─→ firmado_parcial ─→ firmado_completo ─→ vencido ─→ renovado
    │              │                    │                   │
    └──→ cancelado                       └──→ cancelado    (legacy importado desde PDF — entra directo a firmado_completo)

Modelo de datos

4 tablas per-tenant específicas de M3. Cross-ref con proveedores de M1.

TablaPropósitoCampos clave
contratosContrato raízproveedor_id, plantilla_id, estado, pdf_borrador_url, pdf_firmado_url, fecha_inicio, fecha_vencimiento, monto, origen (manual/legacy)
contratos_firmantesMulti-firmantecontrato_id, tipo (proveedor/cliente), nombre, email, mifiel_doc_id, firmado_en
contratos_eventosTimeline + auditoríatipo (creado/enviado/firmado/vencido/renovado), meta JSONB, usuario
plantillas_contratoJinja2 templatesnombre, contenido, variables_requeridas, activa

Integraciones externas

← M1 Alta (proveedor aprobado)

Requisito: el proveedor debe estar aprobado. Validación al crear contrato.

→ Mifiel (firma electrónica)

API oficial Mifiel. Crea documento, obtiene URLs de firma + QR tokens. Webhook inbound en firma. Simulation mode default.

→ Jinja2 SandboxedEnvironment

Todas las plantillas renderizan en sandbox: no __class__, no accesos a globals. Seguro contra injection en variables del usuario.

→ WeasyPrint (HTML → PDF)

Render con timeout 10s vía ThreadPoolExecutor (thread-safe bajo gunicorn). Branding per-tenant aplicado.

→ Supabase Storage

Bucket contratos con subpaths por tenant. Signed URLs con TTL configurable. Backup automático.

→ QR móvil público

Endpoint /firma/<token> pública (sin auth), token 1-use, TTL 7 días. Página optimizada móvil.

→ M4 Órdenes (pre-requisito)

M4 bloquea crear OC si no hay contrato firmado_completo. Cross-check automático del validador M4.

→ Retention SAT 7 años

Cron mensual marca contratos elegibles para archivado. Cumple obligación fiscal automáticamente.

API — Blueprint /api/contratos/*

POST   /api/contratos                   # crear (Generador + Validador_completitud)
GET    /api/contratos                   # listado + filtros (estado, proveedor)
GET    /api/contratos/<id>               # detalle + firmantes + eventos
PATCH  /api/contratos/<id>               # update borrador
POST   /api/contratos/<id>/enviar        # dispara Comunicador + Mifiel
POST   /api/contratos/<id>/cancelar      # solo si no firmado
POST   /api/contratos/<id>/renovar       # fuerza Renovador
GET    /api/contratos/<id>/pdf           # signed URL del PDF actual
POST   /api/contratos/legacy/importar    # upload PDF legacy → Lector OCR

POST   /webhook/mifiel                   # Mifiel firma callback (HMAC verify)
GET    /firma/<token>                    # página pública firma móvil (sin auth)
POST   /firma/<token>/confirmar          # confirma firma vía QR móvil

GET    /api/plantillas                   # CRUD plantillas
POST   /api/plantillas
PATCH  /api/plantillas/<id>
DELETE /api/plantillas/<id>

GET    /api/contratos/vencimientos       # upcoming renewals (vigilante UI)
GET    /api/contratos/retention          # contratos archivados SAT 7a

Seguridad y cumplimiento

Jinja2 SandboxedEnvironment

Bloqueo de escape: {{ config.__class__ }} no funciona. Variables de usuario no pueden acceder internals de Python.

Webhook Mifiel idempotente

Reenvíos del mismo event_id no duplican firmas ni transiciones. HMAC verify. Replay attacks bloqueados.

Token QR 1-use + TTL

Firma móvil pública pero el token se invalida tras firmar. TTL 7 días desde envío. Sin acumulación de tokens zombies.

WeasyPrint thread-safe

ThreadPoolExecutor (no signal.alarm) — seguro bajo gunicorn multi-worker. Timeout 10s evita cuelgues.

Retention SAT 7 años

Cron mensual archiva contratos cumpliendo obligación fiscal MX. No se borran: se marcan archivados + bucket separado.

Audit trail completo

Cada transición en contratos_eventos. Cada acción de usuario en historial_acciones. Quién, cuándo, qué.

Números del build

1+7
Supervisor + agentes
38
Endpoints HTTP
16+
Tabs en UI
8
Estados FSM
4
Tablas M3
7 años
Retention SAT