LICIBOT GovTech
Inteligencia de Contrataciones Públicas con Scraping Resiliente, Normalización de Pliegos y Alertas Predictivas.
LICIBOT: Sistema de Inteligencia y Rastreo Automatizado de Licitaciones Públicas
Plataforma SaaS GovTech de misión crítica diseñada para monitorear, rastrear, normalizar y alertar sobre compras públicas emitidas por múltiples organismos estatales (municipales, provinciales y universitarios). Resuelve la asimetría de información y la fragmentación burocrática mediante un motor headless de alta concurrencia que realiza ingeniería inversa sobre portales gubernamentales legados (Oracle APEX, ASP.NET WebForms y GeneXus), con deduplicación idempotente, filtrado semántico por palabras clave y seguridad perimetral anti-scraping.
Demostración en Tiempo Real: Dashboard, Crawling Reactivo & Auditoría
Contenedor Listo: [GIF / Video en Loop del Flujo Completo de LICIBOT]
Demostración operativa: visualización del Dashboard con métricas de salud de rastreo, disparo asíncrono manual con barra de progreso, filtrado instantáneo debounced por portal/palabra clave y auditoría de corridas con stack traces.
Bypass Portales Complejos
Elusión de barreras de renderizado en ASP.NET (ViewState/PostBack), Oracle APEX (reset de sesión) y GeneXus (inyección DOM).
Scraping Idempotente
Motor desacoplado con normalización a TenderData y clave compuesta (portal_id, reference) para cero duplicados.
Seguridad Defensiva
2FA con whitelist inteligente de IPs y middleware perimetral que bloquea con HTTP 403 a más de 30 scrapers agresivos de IA.
Bare-Metal Resiliente
Template SPA en Nginx puro, workers 24/7 daemonizados y eliminación de fallos de cgroups con Chrome Stable nativo.
Panel de Inteligencia, Observabilidad de Crawlers y Filtros Semánticos
Una interfaz de usuario de alta densidad construida con Vue 3 y TailwindCSS, enfocada en simplificar el seguimiento de licitaciones críticas, disparar ejecuciones manuales con feedback reactivo y auditar cada solicitud HTTP a portales del Estado.
Buscador reactivo con debounce, selector multi-portal, vista en acordeón de pliegos y disparador asíncrono manual.
Búsqueda Reactiva & Expedientes
Interfaz con filtrado instantáneo por texto, organismo o fecha límite, con tarjetas colapsables de resumen y enlace directo al pliego original.
Auditoría por corrida: métricas de duración, tasa de nuevos pliegos e inspección de stack traces aislados por portal.
Telemetría de Corridas & Auditoría
Trazabilidad profunda de cada job con aislamiento de errores: si un portal público cambia su DOM, el fallo se captura sin abortar el resto de organismos.
Panel reactivo para alta/baja de palabras clave con toggle activo/inactivo y configuración de destinatarios del digest diario.
Filtros Semánticos en Caliente
Activación y desactivación dinámica de criterios comerciales (e.g. seguros, ART, caución) sin tocar código ni reiniciar los workers de Laravel.
El Desafío Técnico Completo: Reverse Engineering, Patrón Strategy y DevOps Bare-Metal
Para evaluadores técnicos, arquitectos y CTOs: cómo construí un orquestador headless que elude sistemas obsoletos del Estado, gestiona concurrencia sin fugas de memoria y blindó sus datos contra bots externos.
1. El Problema de Negocio: La Fragmentación Burocrática de las Compras Estatales
Las compras y licitaciones del sector público en Argentina representan miles de millones de pesos anuales en pliegos de seguros, obras de infraestructura, suministros tecnológicos y servicios médicos. Sin embargo, no existe una API nacional unificada ni un catálogo estándar: cada municipio, provincia o universidad pública publica sus llamados en plataformas dispares y anticuadas (COMPR.AR Mendoza en ASP.NET, portales de San Luis en Oracle APEX, municipalidades en GeneXus, y sitios institucionales ad-hoc).
Esta asimetría de información provocaba que las empresas tuvieran que asignar analistas comerciales a revisar manualmente docenas de sitios lentos cada mañana. Con plazos de impugnación y compra de pliegos que a menudo duran menos de 72 horas, muchas oportunidades de negocio se perdían antes de ser detectadas.
El objetivo: Construir una plataforma centralizada que opere como un radar continuo, extrayendo las licitaciones de todas las fuentes oficiales, normalizando los campos heterogéneos en una estructura canónica, filtrando en caliente las relevantes para el negocio y despachando reportes ejecutivos antes del inicio de la jornada laboral.
2. La Arquitectura de Solución: Crawler Engine Desacoplado & Idempotencia
Para garantizar que el sistema fuera extensible y resistente a cambios en los sitios gubernamentales, implementé una arquitectura basada en el Patrón de Diseño Strategy:
Normalización Estricta mediante DTOs
Cada estrategia devuelve objetos tipados TenderData. Sin importar si el portal original expone fechas en formato dd/mm/aaaa, aaaa-mm-dd o con texto desordenado, la salida queda saneada con número de referencia, título limpio, descripción, organismo, fecha de apertura normalizada con Carbon y presupuesto parseado.
Garantía de Idempotencia Relacional
La tabla de licitaciones implementa un índice de unicidad compuesto ['portal_id', 'reference'] a nivel PostgreSQL. Si una licitación ya fue almacenada en una corrida previa, el motor actualiza los metadatos sin duplicar registros ni disparar alertas repetidas.
3. Ingeniería Inversa: Superando las Barreras de ASP.NET, Oracle APEX y GeneXus
Hacer web scraping sobre sitios corporativos modernos es predecible, pero el software gubernamental argentino fue construido hace 15 o 20 años sobre tecnologías pensadas para navegación interactiva de escritorio. Esto exigió ingeniería inversa profunda a nivel de protocolo y DOM:
El portal de compras de Mendoza requiere simular el ciclo de vida de un servidor ASP.NET: no admite URLs directas para paginar. El crawler orquesta Symfony Panther para extraer en caliente las variables criptográficas de estado de la página (__VIEWSTATE, __VIEWSTATEGENERATOR, __EVENTVALIDATION), simula la llamada a __doPostBack('...Page$N') mediante inyección de scripts, y sincroniza el CookieJar para ejecutar peticiones POST secundarias con withoutRedirecting() que interceptan códigos HTTP 302 y capturan las cabeceras Location que llevan al pliego definitivo.
Oracle APEX gestiona el estado en la propia URL (f?p=204:PAGE:SESSION...). Al acceder con navegadores automatizados, el sistema suele quedar atrapado en bucles de redirección ("Session Expired"). Diseñé un algoritmo con expresiones regulares que reescribe dinámicamente el identificador de sesión a 0 en tiempo de ejecución, forzando al motor APEX a aprovisionar una nueva sesión limpia en cada barrido y gestionando las cookies de estado mediante Guzzle.
GeneXus genera componentes con nombres dinámicos impredecibles (span_CTLOBJETO_...) y tablas recargadas por AJAX interno. El crawler ejecuta JavaScript directamente en el contexto del navegador headless para alterar el select de vigencia (vFILTROVIGENCIA = 'T'), dispara eventos sintéticos change del DOM, y evalúa el fin de la paginación inspeccionando el estado visual del botón de navegación (cuando la imagen de flecha "SIGUIENTE" pasa a estado deshabilitado en gris).
4. DevOps Resiliente & Blindaje Defensivo Anti-Indexing
El software en producción no vive en un entorno estéril: convive con la infraestructura del servidor, restricciones de memoria y amenazas externas de rastreadores agresivos:
Resolviendo el Conflicto de cgroups con Snap Chromium
En servidores Ubuntu modernos, Chromium viene empaquetado como Snap. Al ejecutarse desde cron o como daemon de sistema, Snap fallaba con el error fatal cron.service is not a snap cgroup debido a restricciones de aislamiento del kernel. Resolví este escollo purgando el paquete snap e integrando el binario oficial de Google Chrome Stable (google-chrome-stable deb oficial) con banderas de optimización (--disable-dev-shm-usage, --no-sandbox, --headless=new), logrando estabilidad absoluta y cero caídas.
Nginx SPA Puro & Supervisor 24/7
Desplegué el frontend de Vue 3 en una arquitectura Nginx pura sin Apache bajo HestiaCP, diseñando una plantilla de servidor específica que implementa try_files $uri $uri/ /index.html; para soportar el modo HTML5 History de Vue Router sin errores 404 al recargar. Los jobs de scraping se procesan a través de colas de Laravel gestionadas de forma persistente por Supervisor con reinicio automático.
La información recopilada representa una ventaja competitiva de alto valor. Para evitar que terceros o bots de IA consuman la base de datos de LICIBOT, implementé:
- Autenticación 2FA OTP + Whitelist de IPs: Códigos criptográficos de 6 dígitos con expiración estricta de 10 minutos y validación silenciosa en IPs previamente verificadas (
trusted_ips). - Middleware Anti-Bot Perimetral: Detección y bloqueo activo con código
HTTP 403 Forbiddencontra más de 30 User-Agents conocidos de rastreadores agresivos (GPTBot, ClaudeBot, PerplexityBot, ByteSpider, Googlebot, etc.). - Encabezados Anti-Indexación: Inyección automática de
X-Robots-Tag: noindex, nofollow, noarchive, nosnippet, noimageindexen todas las respuestas salientes.
Conclusión: Mi Rol como Full Stack Developer & Software Architect
LICIBOT demuestra mi capacidad de resolver problemas de software en todo el ciclo de vida: desde descifrar protocolos opacos de portales gubernamentales legados mediante ingeniería inversa y domar entornos Linux bare-metal bajo alta carga, hasta modelar una arquitectura orientada a patrones (Strategy, DTOs, Idempotencia relacional) y entregar una experiencia de usuario reactiva, moderna y protegida para tomadores de decisiones corporativas.