Novatecs
NOVATECS AGENTS · TECH DEEP DIVE
Arquitectura de los 35 agentes · 2026-04-17

Arquitectura técnica

Los 35 agentes IA que automatizan el ciclo procurement completo en Cemex y clientes LATAM. Supervisors + especialistas coordinados por LangGraph, modelos Claude elegidos por tarea, infraestructura multi-tenant. Esta es la explicación técnica que tú necesitas para vender, y el equipo técnico del cliente necesita para aprobar.

35 agentes 4 módulos activos Multi-tenant LangGraph Supervisor Claude Sonnet 4.6 + Haiku 4.5 Vision OCR SSE streaming Cron 3 timers
35
Agentes
4
Supervisors
13+
APIs externas
176
Tests verdes
85+
Endpoints REST
50+
Tools IA
Postgres
schema/tenant
§1 · Stack tecnológico

Con qué está hecho

Decisiones de stack razonadas para procurement enterprise: low-latency, multi-tenant, auditable, con proveedores maduros que no mueren mañana.

Claude Sonnet 4.6Razonamiento: supervisors, validación, clasificación compleja
Claude Haiku 4.5Velocidad: comunicación, notificaciones, OCR, tareas CRUD
LangGraph + langgraph-supervisorOrquestación multi-agente con handoffs
Flask + gunicornDashboard + webhook + blueprints (1 worker / 4 threads)
Supabase PostgresMulti-tenant schema-per-cliente + Storage PDFs
WhatsApp Meta Cloud APICanal bidireccional con proveedores
Microsoft GraphEmail outbound + polling inbound
MifielFirma electrónica con valor legal mexicano
DENUE / INEGIRegistro oficial de empresas MX
Google Maps PlacesDescubrimiento local de proveedores
Scrapling + httpxCascade de scraping con anti-bot fingerprint
WeasyPrintHTML → PDF para contratos y OCs
systemd timers3 crons: vigilantes M3, M4 + retention SAT
SSE (gevent port 8502)Streaming en vivo del pipeline M2
pytest + ruff176 tests + lint zero-errors
§2 · Vista aérea

Arquitectura consolidada

Cómo los 4 módulos se comunican entre sí y con el mundo externo. Un proveedor puede entrar por cualquier canal y llegar al mismo supervisor correcto.

WhatsApp Meta Cloud API Email MS Graph Outlook / Teams Mifiel Firma electrónica DENUE INEGI Registro empresas MX Google Maps Places API web_search Claude native tool OSM · Wikidata · SA · Empresite Directorios + scraping webhook.py (Flask port 5000) + cron_email_polling Debounce 8s · multi-tenant resolver · HMAC verify · rutea al supervisor correcto M1 · ALTA DE PROVEEDORES Supervisor M1 6 especialistas · onboarding WA+email → gestor → clasificador → validador (Vision) → comunicador → notificador 📌 RFC + CLABE 📌 6 docs 📌 FSM estados 📌 bandeja humana M2 · BÚSQUEDA INTELIGENTE Pipeline paralelo 15 sub-agentes · SSE streaming → analizador → memoria → 7 fuentes ‖ → scraper → evaluador 📌 score explicable 📌 dedup memoria 📌 anti-bot 📌 cost hardgate M3 · CONTRATOS Supervisor M3 7 especialistas · ciclo Mifiel → generador (PDF) → validador compl. → validador firma → vigilante (cron) → renovador · lector 📌 webhook Mifiel 📌 TTL 30d 📌 retention SAT 7a 📌 multi-firmante M4 · ÓRDENES DE COMPRA Supervisor M4 7 especialistas · FSM 9 estados → generador · validador → comunicador → seguimiento → escalador · lector → vigilante (cron) 📌 cascade M1+M3 📌 OCR evidencias 📌 auto-escalamiento 📌 sandbox Jinja aprobado firmado SUPABASE POSTGRES · MULTI-TENANT SCHEMA-PER-CLIENTE tenant_cemex · tenant_demo · tenant_<slug> Global: tenants, superadmins, sessions · Per-tenant: proveedores, contratos, ordenes_compra, eventos, historial Supabase Storage PDFs contratos + OCs + docs Dashboard Flask · /portal.<tenant>.novatecsagents.com · 4 portales · token auth
Sistemas externos M1 Alta M2 Búsqueda M3 Contratos M4 Órdenes Persistencia
§3 · Deep dive · M1

M1 — Alta de Proveedores

Onboarding automático de proveedores por WhatsApp + email. El supervisor orquesta 5 especialistas que reúnen los 6 documentos + 6 datos críticos antes de escalar a revisión humana.

6 agentes · productivo en Cemex

Cada mensaje del proveedor pasa por debounce 8s y llega al supervisor, que decide el handoff. La regla dura: todo flujo termina en comunicador.

Supervisor Sonnet5 especialistas FSM estadosLRU dedup 60s Vision OCRMulti-canal WA+email
🧠

Supervisor M1 (orquestador)

Decide quién atiende cada mensaje
Sonnet 4.6

Recibe cada mensaje inbound (WA o email), evalúa contexto (quién es el proveedor, estado actual, qué acaba de mandar) y delega al especialista apropiado. Valida que el mensaje final salga por comunicador — nunca habla directo al proveedor. Implementa debounce (8s) para consolidar mensajes ráfaga.

Coordinación
gestorclasificadorvalidador comunicadornotificador
📇

Gestor

CRUD + asignación automática
Haiku 4.5

Registra proveedor nuevo, actualiza datos, cambia estados, asigna asesor automático por menor carga (peso: revisión humana x3 + activos x1).

Tools
register_new_providerupdate_provider_data change_provider_statusasignar_asesor_automatico reassign_provider
Conectividad
Supabase (proveedores, asesor_id)
🏷️

Clasificador

Identifica tipos de documento
Haiku 4.5

Determina por pattern matching sobre filename si el archivo subido es constancia fiscal, opinión cumplimiento, comprobante domicilio, acta constitutiva, estado de cuenta o ID representante. Sin LLM — regex determinístico.

Tools
extraer_tipo_documento
Conectividad
Supabase Storage (filenames)
🔍

Validador

Vision + reglas fiscales MX
Sonnet 4.6

Valida documentos con Claude Vision (legibilidad, datos correctos, firmas/sellos). RFC formato SAT: persona moral 12 chars, física 13. CLABE 18 dígitos. Opinión cumplimiento con TTL de 30 días.

Tools
validate_rfc_formatvalidate_clabe_format validate_document_visioncheck_opinion_ttl
Conectividad
Anthropic Vision APISupabase Storage (GET signed URL)
💬

Comunicador

Canal único al proveedor
Haiku 4.5

Envía WhatsApp y email. Recibe respuestas. Respeta per-chat takeover (proveedores.agente_pausado) para cuando un humano retoma. Fallback: si WA falla, webhook extrae respuesta y la envía directo.

Tools
send_whatsapp_messagesend_email_microsoft_graph solicitar_documentos_faltantes
Conectividad
WhatsApp Meta Cloud APIMicrosoft Graph (send mail)
🔔

Notificador

Alertas internas al equipo
Haiku 4.5

Crea notificaciones en dashboard + email interno + Teams cuando un proveedor alcanza hitos (docs listos, revisión humana pendiente, aprobación). Dedup temporal 60s para evitar ruido si dos agentes notifican el mismo evento.

Tools
notificar_equipo_dashboardnotificar_equipo_email notificar_equipo_teams
Conectividad
Supabase (notificaciones)Microsoft Graph (email + Teams)
§4 · Deep dive · M2

M2 — Búsqueda Inteligente

Pipeline agéntico de 15 sub-agentes que encuentra proveedores nuevos cuando no están en catálogo. 7 fuentes externas corren en paralelo, el scraper enriquece top-5, el evaluador scorea con fórmula explicable.

1 supervisor Python + 15 sub-agentes · pipeline + SSE streaming

M2 sí tiene supervisor, pero custom en Python puro (vive en agents/modulo2_busqueda/orquestador/supervisor.py), no LangGraph. Orquesta el pipeline con ThreadPoolExecutor para ejecutar las 7 fuentes en paralelo, controla el hardgate de costo y streamea cada paso al frontend vía SSE. Razón del diseño: cero overhead de routing LLM + control determinista del costo por búsqueda.

7 fuentes paralelas ThreadPoolExecutor workers=7 Cost hardgate $1.50 Pydantic schemas Scrapling cascade
🎯

Analizador

NL → Criterios estructurados
Sonnet

Convierte query del comprador ("acero en Nuevo León con ISO 9001") a CriteriosBusqueda Pydantic validado (categoría, estado, num_resultados cap 10, certs requeridas).

Tools
analizar_consulta
Conectividad
Anthropic API (Sonnet)

Clarifier

Pregunta con slot-questions
Haiku

Si query ambiguo ("proveedores"), sugiere chat inline "¿qué categoría? ¿qué estado?" con opciones pre-armadas. Evita búsquedas desperdiciadas.

Tools
sugerir_slots
💾

Memoria (lector + escritor)

Catálogo acumulativo
SQL

Si ya buscamos esto antes con match alta confianza, retorna sin gastar APIs. Al final, upsert JSONB con dedup case-insensitive. Allow-list ISO regex para certs.

Tools
buscar_en_memoriaescribir_en_memoria
Conectividad
Supabase (catalogo_descubierto)
🏛️

DENUE

Registro oficial INEGI
Haiku

API gratuita del DENUE. Empresas con RFC válido y actividad económica oficial SCIAN. Coverage México total. Requiere DENUE_TOKEN.

Tools
buscar_denue
Conectividad
api.inegi.org.mx/DENUE
📍

Google Maps

Places API + reviews
Haiku

Empresas por categoría + ubicación. Extrae tel, sitio web, rating, horarios. Fallback a web_search si no hay API key.

Tools
buscar_google_maps
Conectividad
Google Places API
🌐

Buscador Web

web_search nativo Claude
Sonnet

Usa tool web_search_20250305 oficial de Anthropic. Encuentra empresas con presencia online pero no en directorios estructurados. Max 2 reformulaciones por cost cap.

Tools
buscar_web
Conectividad
Anthropic web_search tool
🗺️

OpenStreetMap

Overpass API gratis
REST

Coverage menor que Google Maps pero sin API key y complementa con datos geográficos precisos (coordenadas).

Tools
buscar_openstreetmap
Conectividad
overpass-api.de
📚

Wikidata

SPARQL corporativos
SPARQL

Empresas mexicanas grandes catalogadas en Wikidata (Q4830453 business, Q43229 organization). Útil para conocer corporativos y filiales.

Tools
buscar_wikidata
Conectividad
query.wikidata.org/sparql
📞

Páginas Amarillas MX

Directorio B2C con scraping
Scrapling

Scrapea seccionamarilla.com.mx. Scrapling usa curl_cffi + TLS Chrome fingerprint para bypass anti-bot. Heurísticas de extracción robustas a cambios de layout. follow_redirects=False (defensa SSRF).

Tools
buscar_paginas_amarillas
Conectividad
seccionamarilla.com.mx
🏢

Empresite MX

Directorio B2B
Scrapling

Scrapea empresite.mx enfocado a empresas B2B con razón social + domicilio fiscal. Complementario a Páginas Amarillas.

Tools
buscar_empresite
Conectividad
empresite.mx
🕷️

Scraper (cascade)

Enriquece top-5 URLs
Python

Visita top-5 sitios y extrae datos: tel, email, descripción, certs mencionadas. Cascade Scrapling → httpx si el primary falla. SSRF-safe (valida DNS, bloquea AWS IMDS), A6 sanitize (strip tags XML antes de LLM).

Tools
scrapear_urlsfetch_with_cascade
Conectividad
HTTP cualquier sitio (con SSRF guard)
💵

Enriquecedor de Precios

Benchmarks de mercado
Sonnet

Para top-5 usa web_search para estimar precios típicos de la categoría. Ayuda al comprador a contextualizar ofertas.

Tools
enriquecer_precios
⚖️

Evaluador

Score explicable 5 dim
Sonnet

Scorea candidatos en 5 sub-dimensiones (presencia web, certs, ubicación, precio, completitud) con pesos configurables. Output Pydantic con fórmula_explicada obligatoria. Fallback rule-based si Sonnet falla.

Tools
evaluar_candidatos
🔄

Refinador

Segunda pasada si hace falta
Sonnet

Evalúa calidad tras primera pasada. Si insuficiente, expande criterios y reintenta con fuentes que faltaron.

Tools
evaluar_calidadrefinar_busqueda
🎨

Presentador

Compone output para dashboard
Python

Composición pura Python (sin LLM): hero + tabla + mapa + card top-5. El frontend renderiza vía SSE en vivo conforme los demás agentes completan.

Tools
presentar_resultados
Conectividad
SSE → dashboard
§5 · Deep dive · M3

M3 — Contratos

Ciclo completo de vida de contratos: generación desde plantillas, firma electrónica con valor legal mexicano vía Mifiel, vigilancia de vencimientos con alertas 60/30/15/7 días, renovación asistida, retención SAT 7 años automática.

7 especialistas + supervisor · productivo

Mifiel provee firma con valor legal ante SAT. Simulation mode default en demo (no consume créditos). Multi-firmante lado proveedor + lado tenant, paralelo o secuencial configurable.

Mifiel APIFernet secrets + HKDF per-tenant Firma móvil QR públicaOCR Vision contratos legacy 2 crons (vigilante + retention)
🧠

Supervisor M3

5 triggers orquestados
Sonnet 4.6

Triggers: nuevo_contrato, firma_proveedor_recibida, firma_tenant_recibida, vencimiento_cercano, renovacion_iniciada. Todo handoff termina en comunicador_m3.

Coordinación
generadorvalidador_completitudvalidador_firmacomunicador_m3vigilanterenovadorlector
📝

Generador

Plantilla → PDF + registro Mifiel
Sonnet

Renderiza Jinja2 + WeasyPrint con variables del asesor y data proveedor. Hash SHA-256 para integridad. Registra documento en Mifiel para que arme widget de firma.

Tools
render_contract_pdfrender_templatecompute_pdf_hashmifiel_register_documentscan_unfilled_vars
Conectividad
Mifiel REST APISupabase StorageWeasyPrint (local)

Validador Completitud

Pre-envío a Mifiel
Sonnet

Verifica PDF draft antes de mandar al proveedor: variables sin llenar, cláusulas obligatorias presentes, bloque de firmas correcto.

Tools
scan_unfilled_varsvalidate_required_clausesvalidate_signature_blockvalidate_contract_completeness
✍️

Validador de Firma

Procesa webhooks Mifiel
Sonnet

Webhook handler idempotente (event_id unique). Procesa eventos signed / rejected / expired. Descarga PDF firmado cuando cierra. HMAC verify obligatorio fail-closed.

Tools
procesar_firma_evento
Conectividad
Mifiel webhooks (inbound)Mifiel API (download firmado)
📨

Comunicador M3

WA + email + notif tenant
Haiku

WA al proveedor con link widget Mifiel (deep link o QR), email con PDF adjunto, notif dashboard a firmantes tenant. Firma móvil pública accesible por QR sin login.

Tools
send_wa_contratosend_email_contratosend_notification_tenant
Conectividad
WhatsApp CloudMS GraphSupabase notificaciones
👁️

Vigilante

Cron diario 06:00 AM
Haiku

Barrido diario: alertas 60/30/15/7 días antes del vencimiento. Recordatorios WA si proveedor no ha firmado + expira TTL Mifiel (30 días).

Tools
escanear_vencimientosescanear_recordatorios_firmalistar_proximos_a_vencer
Ejecución
systemd timer · 06:00 AM diario
🔁

Renovador

Clona padre + deltas
Haiku

Comprador click "Renovar" → clona contrato padre, aplica deltas (fechas, montos), marca padre renovado, arranca generador sobre el nuevo.

Tools
clonar_contrato_para_renovacion
📖

Lector (OCR legacy)

Contratos firmados fuera del sistema
Haiku Vision

Vision sobre PDFs externos. Extrae partes, fechas, monto, tipo → inserta en contratos con estado=firmado_completo y fuente=externo. Trae contratos legacy al dashboard.

Tools
extraer_datos_contrato_externoregistrar_contrato_externo
Conectividad
Anthropic VisionSupabase Storage
§6 · Deep dive · M4

M4 — Órdenes de Compra

Ciclo completo de OCs: generación, validación integrada con M1+M3, envío al proveedor por WA+email, clasificación automática de respuestas, escalamiento a humanos cuando se requiere, OCR de evidencias de entrega, vigilante cron diario.

7 especialistas + supervisor · FSM 9 estados · MVP 2026-04-17

Cross-módulo fuerte: Validador M4 exige proveedor.estado=aprobado (M1) y contratos.estado=firmado_completo (M3). Si monto > oc_max_monto_sin_escalar, escala automático antes de enviar.

Jinja SandboxedEnvironment WeasyPrint timeout 10s CSV injection sanitize TenantScope context manager SSRF guard en lector
🧠

Supervisor M4

5 triggers, auto-escalamiento
Sonnet 4.6

Triggers: crear_oc, mensaje_proveedor, imagen_proveedor, vigilante_diario, crear_oc_sin_enviar. Invoca escalador automático si monto excede límite antes del envío.

Coordinación
generadorvalidadorcomunicadorseguimientoescaladorlectorvigilante
🧾

Generador OC

Plantilla sandboxed → PDF
Sonnet

Jinja2 SandboxedEnvironment (autoescape=true, bloquea {{ __class__ }} RCE) + cap 200KB plantilla + WeasyPrint timeout 10s via ThreadPoolExecutor. PDF a Supabase Storage.

Tools
generar_oc
Conectividad
Supabase StorageWeasyPrint
🛡️

Validador OC

Cross-módulo M1 + M3
Sonnet

Proveedor.estado=aprobado (M1), contratos.estado=firmado_completo + fecha vigente (M3), items cantidad+precio positivos, monto > 0, moneda MXN/USD/EUR, fecha entrega futura, RFC formato SAT.

Tools
validar_oc
Cross-módulo
proveedores (M1)contratos (M3)
📤

Comunicador OC

WA + email + nudges
Haiku

Envía OC con PDF signed URL, nudges de acuse, responde textos redactados por seguimiento. Respeta oc_simulation_mode para demos sin consumir APIs.

Tools
enviar_oc_a_proveedorenviar_nudge_acuseresponder_inbound_proveedor
Conectividad
WhatsApp MetaMS Graph email
🔍

Seguimiento

Clasifica respuestas inbound
Sonnet

Clasifica mensajes del proveedor en 5 buckets (acuse / confirmación / cambio / entrega / desconocido) con heurísticas. Cada bucket dispara su transición FSM y propone respuesta. Desconocido escala humano.

Tools
procesar_respuesta_proveedorevaluar_cronograma
⚠️

Escalador

Notif al comprador humano
Haiku

Crea notificación dashboard cuando: cambio fecha/cantidad, monto excede límite, disputa, pregunta fuera política, rechazo proveedor. Shape canónico {proveedor_id, tipo, mensaje, canal, leida} alineado con M1/M3.

Tools
escalar_a_comprador
Conectividad
Supabase notificacionesdashboard + Teams (futuro)
📷

Lector OC (OCR)

Vision sobre evidencias
Haiku Vision

OCR sobre fotos WA del proveedor: OC firmada → acuse, remisión → surtida_parcial, foto entrega → surtida_completa. SSRF-safe (DNS resolution + bloqueo IPs privadas) + cap 10MB.

Tools
leer_evidencia_proveedor
Conectividad
Anthropic VisionWA media URLs
📅

Vigilante OC

Cron diario 07:15 AM
Haiku

TenantScope context manager por tenant. Detecta: sin acuse > 2 días, retraso entrega > 3 días tolerancia, modificadas > 5 días. Cada alerta dispara comunicador o escalador.

Tools
escanear_ocs_atrasadas
Ejecución
systemd timer · 07:15 AM diario
§7 · Cross-module

Lifecycle completo de un proveedor

Cómo los 4 módulos encadenan desde que alguien contacta a Cemex hasta la OC cerrada. El dato fluye en una dirección; los estados cierran cada fase antes de habilitar la siguiente.

M1 · Alta

Proveedor mensaje por WA → supervisor gestor valida RFC+CLABE+6 docs → Vision → estado=aprobado

M2 · (opcional)

Comprador busca nuevos proveedores → 7 fuentes paralelas → score → invitación a alta M1

M3 · Contrato

Comprador arma contrato de plantilla → Mifiel firma proveedor + tenant → estado=firmado_completo

M4 · Órdenes

Comprador emite OC → validator exige aprobado+firmado → WA → OCR entrega → cerrada

§8 · Conectividad

Matriz de sistemas externos

Qué sistemas externos toca cada módulo. Todo outbound pasa por el módulo que tenga autoridad sobre ese sistema — no hay conexiones directas desde agentes cross-módulo.

Sistema externo M1 M2 M3 M4 Uso primario Tipo
WhatsApp Meta Cloud API · Inbound + outbound con proveedoresWebhook + REST
Microsoft Graph (Email + Teams) · Email outbound + polling + alertas TeamsOAuth + REST
Mifiel ··· Firma electrónica con valor legal SATREST + webhook
DENUE / INEGI ··· Registro oficial empresas MXREST público
Google Maps Places ··· Descubrimiento por ubicaciónREST + API key
Claude web_search tool ··· Búsqueda web nativa AnthropicTool use
OpenStreetMap / Overpass ··· Geo-data gratisREST público
Wikidata SPARQL ··· Corporativos grandesSPARQL
SecciónAmarilla MX ··· Directorio B2C scrapingHTML scraping
Empresite MX ··· Directorio B2B scrapingHTML scraping
Anthropic Claude API LLM Sonnet + Haiku + VisionREST
Supabase Postgres Multi-tenant schema-per-clientepostgrest
Supabase Storage · Documentos + PDFs firmadosS3-like API
§9 · Model selection

Sonnet vs Haiku — cuándo y por qué

No todos los agentes necesitan el modelo más caro. Sonnet solo donde el razonamiento justifica el costo y la latencia.

🎯 Sonnet 4.6 — SMART path

Usado en: todos los 4 supervisors, validador M1 (Vision + reglas), analizador M2, buscador_web M2, enriquecedor M2, evaluador M2, refinador M2, generador M3+M4, validador_completitud M3, validador_firma M3, validador M4, seguimiento M4.

Razón: decisiones multi-paso, clasificación con contexto histórico, compliance check, razonamiento sobre datos heterogéneos.

⚡ Haiku 4.5 — FAST path

Usado en: gestor M1, clasificador M1, comunicador M1, notificador M1, DENUE, Google Maps, memoria M2, clarifier M2, comunicador M3+M4, vigilante M3+M4, renovador M3, escalador M4.

Razón: CRUD, envío de mensajes, OCR structured output, pattern matching, tareas de baja incertidumbre donde la velocidad importa más.

👁️ Haiku Vision — OCR path

Usado en: lector M3 (contratos externos), lector M4 (evidencias entrega), validador M1 (docs proveedor).

Razón: extracción estructurada desde imagen con JSON schema. Haiku Vision basta; no necesitamos Sonnet.

🐍 Python puro — no LLM

Usado en: clasificador M1 (regex filename), memoria M2 (SQL directo), scraper M2, presentador M2.

Razón: operaciones determinísticas donde el LLM añadiría costo sin valor. Los agentes "sin LLM" son baratos y rápidos.

§10 · Seguridad

Defensas transversales

Todo módulo hereda estos patterns. La última auditoría CSO (2026-04-17) cerró 2 CRITICAL + 2 HIGH y dejó 0 abiertos.

🔐 Multi-tenant strict

Todos los queries per-tenant usan wrapper db() que resuelve schema por subdomain. Hook pre-commit bloquea supabase.table('proveedores') directo. TenantScope context manager en crons.

🛡️ Prompt injection (A6)

Datos del proveedor wrapped en XML tags (<provider_message>, etc). sanitize_mensaje_inbound strip tags + escape <> antes de LLM. Aplicado en M1, M3, M4.

🚫 SSRF defense

Scraper M2 + Lector M4 validan DNS resolution. Bloquean IPs privadas, loopback, link-local (169.254.169.254 = AWS IMDS). follow_redirects=False default.

📝 Jinja sandbox

Generador M3+M4 usa SandboxedEnvironment(autoescape=True). Bloquea RCE vía {{ __class__ }}. Cap 200KB plantilla.

⏱️ FSM guards

M3 (contratos) y M4 (OCs) tienen estados validados en DB CHECK constraints + agent validador + blueprint endpoints 409 invalid_state.

📊 Audit trail completo

Tabla historial_acciones + contratos_eventos + oc_eventos para trazabilidad. Cada mutation pasa por _log_accion.

🔑 Secrets Fernet + HKDF

Credenciales Mifiel por tenant cifradas con Fernet + HKDF derivation key-per-tenant. Master key en .env 0600.

🚪 Auth + rate limit

Tokens en-memoria 12h TTL + daemon cleanup 15min. Flask-Limiter en login 5/15min + 20/hora. Bcrypt 12 rounds.

🧾 CSV injection

Importador M4 prefija ' a celdas que empiezan con = + - @. Evita RCE Excel al abrir CSV exportado con data maliciosa.

§11 · Operaciones

Servicios + crons en el servidor

Todo corre en systemd con hardening (NoNewPrivileges, ProtectSystem strict, PrivateTmp). 7 unidades activas.

🌐 novatecs.service (puerto 5000)

Webhook WhatsApp + health. Flask single worker. HMAC verify fail-closed. Debounce 8s.

📊 novatecs-dashboard.service (puerto 8501)

Dashboard multi-tenant Flask. 1 worker / 4 threads. Tokens in-memory. 4 portales nginx per-tenant.

📡 novatecs-dashboard-sse.service (puerto 8502)

SSE streaming M2 búsqueda. gunicorn gevent 1 worker (SSE no-sync).

📧 novatecs-email.service

Cron email polling Microsoft Graph. Detecta intent + adjuntos.

⏰ novatecs-cron.timer

Seguimientos M1 proveedores (recordatorios docs).

👁️ novatecs-contratos-vigilante.timer

06:00 AM diario. Alertas 60/30/15/7 días + recordatorios firma.

📅 novatecs-oc-vigilante.timer

07:15 AM diario. Barrido OCs atrasadas M4. TenantScope por tenant.

🗓️ novatecs-contratos-retention.timer

Mensual. Retention SAT 7 años. Limpia contratos expirados + archiva.