Investigación y pruebas: 25 de septiembre de 2026. Alcance: una sola empresa, uso propio.
Sí hay una ruta viable. La búsqueda no necesita depender del navegador de SECOP y ya conseguimos descargar y leer una invitación pública real sin resolver CAPTCHA. Recomiendo continuar con un servicio propio que ingiera datos abiertos, conserve los documentos, analice evidencia y mantenga una cola de excepciones. Una restricción de una fuente debe detener esa operación concreta, no toda la aplicación.
La entrega anterior fue demasiado fácil de interpretar como «todo está resuelto salvo el CAPTCHA». La investigación práctica de esta segunda etapa permite precisar tres cosas:
No hace falta construir facturación SaaS, planes ni aislamiento multiempresa. Sí hacen falta acceso privado, copias de seguridad, control del gasto de IA y una persona responsable de revisar las excepciones jurídicas.
La implementación existe en SalvedadBackend/src/services/datosGov/. sodaClient.js consulta SODA mediante X-App-Token, aplica reintentos y ofrece paginación. trmService.js y ciiuService.js guardan resultados en PostgreSQL mediante Prisma. datosGovSyncWorker.js utiliza BullMQ/Redis para trabajos y programación. El documento técnico de AXSoftware describe la misma integración.
Es una base reutilizable, pero actualmente integra TRM y CIIU; no encontré allí un conector SECOP ni un descargador de pliegos. Podemos reutilizar el patrón de sincronización y la separación entre consulta externa y datos propios. CIIU y UNSPSC son clasificaciones distintas: un código de actividad empresarial no sustituye el código del bien o servicio a contratar.
Encontré y reproduje dos defectos del adaptador existente en una ejecución aislada, sin modificar Salvedad ni consultar su producción:
| Caso simulado | Resultado del código actual | Riesgo al reutilizarlo en SECOP | Corrección necesaria |
|---|---|---|---|
| Tres respuestas HTTP 429 consecutivas | Termina lanzando undefined porque esa rama no asigna lastError |
Se pierde la causa real del límite de consultas | Error tipado, conservar HTTP y respetar Retry-After |
| HTTP 200 con HTML en vez de JSON | query produce un objeto y fetchAllPages termina con [] |
Una falla de formato aparenta que no existen registros | Validar esquema; abortar sincronización; conservar el último lote válido |
Evidencia reproducible: evidencia-salvedad.json y test_salvedad_adapter.cjs. Referencias de código: sodaClient.js, líneas 49–53, 98 y 110–111. No extrapolo estos casos simulados como incidentes que ya hayan ocurrido en producción.
Antes de copiar el worker también conviene revisar zona horaria explícita, configuración TLS de Redis, consumo de memoria de la paginación y el alcance real del timeout sobre el cuerpo de la respuesta. Son puntos de revisión de código, no fallas de producción demostradas.
| Canal | Qué resuelve | Resultado de esta investigación | Decisión |
|---|---|---|---|
| SODA 2.1 de datos.gov.co | Búsqueda y sincronización de registros | HTTP 200 sin token; respuesta de muestra en 0,94 s | Canal inicial operativo |
Campos :id y :updated_at |
Identificar filas y cambios de publicación | HTTP 200; dos filas con marca de actualización | Usarlos con reconciliación, no como garantía absoluta de cambio de negocio |
| CSV acotado del catálogo | Importación y reconstrucción tabular | HTTP 200; 2 registros solicitados; 1,07 s | Canal de reconstrucción, no réplica independiente |
| OData v4 | Otra interfaz oficial de lectura | HTTP 200; 1 registro solicitado; 4,08 s | Alternativa de compatibilidad, no remedio para una caída total de datos.gov.co |
Catálogo documental dmgg-8hin |
Identificar archivos y enlaces oficiales | HTTP 200; 11 referencias del portafolio examinado | Descubrimiento documental operativo |
| URL exacta publicada de invitación | Obtener el PDF original | HTTP 200 y PDF completo de 708.933 bytes | Descargador corregido e integrado |
| SODA 3 | Interfaz actual con identificación del cliente | Documentación oficial verificada; prueba autenticada pendiente de autorización del token de Salvedad | Preparar adaptador; SODA 2.1 sigue soportado |
API OCDS histórica api.colombiacompra.gov.co/releases/ |
Posible canal adicional | Timeout de conexión en la prueba | No usar como dependencia crítica hasta verificar servicio, cobertura y actualización |
| Registro OCP de Colombia | Histórico para investigación | El registro declara datos hasta abril de 2022 y última obtención en marzo de 2023 | No sirve para descubrir convocatorias nuevas de 2026 |
Las latencias anteriores corresponden a una petición por caso, no son percentiles ni acuerdos de servicio. Evidencia: evidencia-fuentes-publicas.json.
Socrata documenta que SODA 3 requiere identificación/autenticación para consultas y que SODA 2.1 continúa disponible. El token de aplicación mejora la atribución y manejo de cuotas; no es una clave de acceso a PDFs de SECOP y no elimina sus verificaciones. No debemos cambiar de interfaz para esquivar un 429: se respeta la pausa del proveedor. SODA 3, tokens.
:updated_at permite trabajar incrementalmente, pero Socrata advierte que una sustitución completa del conjunto puede cambiar la marca de todas las filas. Por eso hacen falta hashes de contenido, conciliación periódica y cuidado con borrados y páginas movidas durante la descarga. Campos de sistema.
El catálogo oficial describe dmgg-8hin como referencias para descarga desde 2025, con actualización diaria. Los archivos se alojan en otro servicio; disponer de su fila no prueba que la descarga esté disponible. Descripción oficial de CCE.
En esta investigación:
User-Agent que identifica verazmente el aplicativo, se obtuvo la invitación completa. El nuevo conector volvió a descargarla y la sirvió desde el almacenamiento local.Documento comprobado: Invitación Pública.pdf, ID 861728476, proceso CO1.REQ.11087573, referencia MB-MC-027-2026, Municipio de Belén, Boyacá.
| Medida | Resultado |
|---|---|
| Tamaño del archivo descargado | 708.933 bytes |
| Tamaño declarado en el catálogo | 708.933 bytes |
| Páginas extraídas | 30 |
| Páginas sin texto suficiente según el control aplicado | 0 |
| Caracteres extraídos | 117.524 |
| Resultado del lector PDF | Código de salida 0 |
SHA-256: 8564dc33330d9dd39db2c2b72c214a85925fc6cb81c2a6a9eaba9b182e9e34b0.
Esto demuestra un documento completo descargable, no una tasa nacional de éxito de 100%. Tampoco demuestra que imágenes, firmas o gráficos hayan sido interpretados por la extracción de texto. Se conserva el original para verificarlos. URL oficial del documento.
El PETI 2026 de CCE, página 21, incluye en su inventario una aplicación denominada «Api descarga archivos SECOP» para SECOP I y II. La existencia inventariada está comprobada; no encontré en las fuentes revisadas un contrato público de acceso con URL, autenticación, cuotas y SLA que permita integrarla ya. No se debe presentar una herramienta interna como API pública disponible sin comprobarlo. PETI 2026.
Dejé redactada una solicitud concreta para CCE en SOLICITUD-CCE.md: documentación, acceso para uso empresarial propio, cuota, versión documental, cronogramas y canal de incidentes. No fue enviada. Esta gestión puede convertir la descarga pública observada en una integración con condiciones explícitas, pero su aprobación no está garantizada.
El proveedor de la cuenta mencionada inicialmente, Licitacionescolombia.co, sí anuncia integraciones mediante API. Por tanto, existe una vía comercial concreta para evaluar, distinta de automatizar su interfaz de usuario. Su anuncio público no acredita que nuestra suscripción incluya API, PDFs completos, adendas o derecho de almacenamiento y análisis con IA. API anunciada por el proveedor, reportes e integración.
La API secop-co documentada por Apitude consulta empresas; esa documentación no demuestra una descarga integral de expedientes. No la contrataría como solución al problema de PDFs sin una demostración específica. Documentación del proveedor.
Antes de pagar a cualquier proveedor exigiría una prueba sobre 20 procesos nuestros, con pliego vigente, anexos, adendas, ID oficial, actualización, errores informados y permisos de conservación. Pediría precio por documentos y límites, no solo por búsqueda. Dejé ese cuestionario en EVALUACION-PROVEEDOR.md.
| Problema | Evidencia o alcance | Cómo se resuelve | Qué no debemos prometer aún |
|---|---|---|---|
| Archivo accesible en una petición y rechazado en otra | 200 y 403 observados | URL publicada, cliente identificado, controles de formato/tamaño, registro de contexto; gestión con CCE | Descarga universal o SLA de origen |
| Datos con retraso | Frecuencia diaria del catálogo | Registrar fecha de origen y de consulta; verificar procesos prioritarios por canal autorizado | Actualización al segundo desde un lote diario |
| Mismos nombres de documentos en fechas distintas | Referencias del 09/09 y 22/09 en el portafolio de Belén | Historial por ID y hash; reconocer versiones; comparar adendas | Que el archivo de nombre más reciente sea automáticamente el jurídicamente vigente |
| Campo de fecha insuficiente | El catálogo mostraba el día; el PDF contiene una hora de cierre | Leer cronograma, zona horaria y cambios; mostrar procedencia | «Todavía puede aplicar» usando solo el día del catálogo |
| Experiencia mal simplificada | La invitación exige forma, objeto, soporte y participación | Motor de reglas por contratos individuales y unidades, unido a evidencia | Habilitación por sumar todos los ingresos de la empresa |
| Lectura parcial de imágenes/tablas | pdftotext no hace OCR ni autentica firmas |
OCR por página, tablas, inventario y revisión de páginas problemáticas | «Comprensión total» porque todas las páginas tienen algún texto |
| Contradicciones de documentos | Riesgo en pliego, anexos, adendas y respuestas | Detección de conflictos y consolidación posterior a la extracción | Resolver contradicciones jurídicas con una simple preferencia por fecha |
| Fallas de datos.gov.co | Timeouts observados y casos 429 reproducidos por simulación | Almacén propio, cola persistente, pausas, reintentos acotados | Descubrir información nueva durante una caída total de la fuente |
| Modelo IA incorrecto o incompleto | Pruebas previas pequeñas; citas no validan interpretación | Evaluación contra revisión humana y verificación numérica fuera del modelo | Probabilidad de éxito o exhaustividad jurídica sin validación |
| Equipo local apagado | El prototipo corre en este equipo | Servidor persistente y supervisión del proceso | Servicio 24/7 mientras dependa de una terminal personal |
La página 9 contiene exigencias sobre actividad CIIU 4761, objeto social, facultades de representación y documentos empresariales. La página 10 pide experiencia sobre un contrato liquidado, con cuantía comparada en SMMLV y ponderación según participación cuando procede. Son criterios observados de ese documento, no reglas universales para toda contratación ni una validación de su legalidad.
La página 15 fija la entrega de propuestas para 25/09/2026 a las 16:00. Esa hora fue extraída del PDF; no se confirmó contra adendas posteriores ni contra el cronograma transaccional, por lo que no debe emplearse como certificación de plazo vigente.
Para este caso, una ficha que solo diga «experiencia: 100 millones» resulta insuficiente. Debe poder probar número de contratos admitidos, objeto, liquidación, fechas, participación, soporte y conversión aplicable. Tampoco se deben inventar índices financieros solo porque existan campos financieros en nuestra aplicación.
La disponibilidad debe medirse en tres planos separados:
| Plano | Qué medimos | Qué ocurre si falla |
|---|---|---|
| Aplicación propia | Puede abrir, buscar su índice y consultar documentos guardados | Reinicio automático, réplica/recuperación y alertas |
| Actualización externa | Tiempo desde última sincronización válida de cada fuente | Seguir con copia local, indicar antigüedad y mantener pendientes |
| Expediente y evaluación | Documentos esperados, obtenidos, leídos y revisados | Marcar la parte pendiente; impedir una conclusión definitiva |
El sistema debe responder, por ejemplo: «Puede consultar los 42 procesos ya guardados. La última sincronización válida fue ayer a las 10:31. No he podido comprobar nuevas adendas. La búsqueda local funciona; la vigencia del expediente está pendiente». Los números de ese ejemplo son ilustrativos.
SODA / catálogo documental / API contratada autorizada
↓
Sincronizador con trabajos persistentes y controles por fuente
↓
PostgreSQL: procesos, versiones, requisitos, eventos y evidencia
+
Almacén de archivos: originales, hashes, OCR y extracciones
↓
Extracción por páginas → reglas numéricas → consolidación y conflictos
↓
Ficha empresarial verificable + análisis Vertex + revisión humana
↓
Aplicación web privada, buscador, chat, bandeja de pendientes y alertas
Propuesta: un backend y un worker permanente, PostgreSQL y almacenamiento de archivos; Redis/BullMQ si se reutiliza el ecosistema Salvedad. Una sola organización y pocos usuarios internos. Railway puede alojarlo aprovechando la experiencia existente, pero requiere definir proyecto, persistencia, acceso y presupuesto antes de desplegar. No se modifica ni carga de trabajo adicional a la producción de Salvedad como parte de esta investigación.
No necesitamos un motor vectorial aparte al inicio: filtros SQL y búsqueda de texto son suficientes para descubrimiento y trazabilidad; la búsqueda semántica puede añadirse cuando mejore resultados medidos.
:updated_at, orden total y ventana de solapamiento. Guardar punto de avance solo tras persistir el lote completo. Si hay reemplazo masivo, ejecutar reconciliación por contenido.SODA, CSV y OData comparten plataforma. Diversificar formatos puede resolver una incompatibilidad de interfaz, pero no protege contra una caída del dominio o contra datos que aún no se publicaron. La independencia real proviene de nuestra copia, otra fuente con permiso y respaldo operativo.
La clasificación debe derivarse de señales técnicas y evidencia guardada, no de una explicación inventada por IA:
| Señal | Clasificación | Acción |
|---|---|---|
| HTTP 429 | Cuota de la fuente | Respetar Retry-After; usar copia; no alternar interfaces para evadirlo |
| Timeout o 5xx | Fallo temporal observado | Reintento limitado; circuito de pausa; conservar cola y copia |
| DNS/TLS/conexión | Fallo de comunicación, causa aún indeterminada | Separar red local, certificado y origen; no atribuirlo automáticamente a CCE |
| HTTP 401/403 | Acceso rechazado | Revisar contexto/documentación; no declarar CAPTCHA solo por el código |
| Página o redirección explícita de CAPTCHA | Verificación humana | Pendiente de acceso; flujo asistido o API autorizada |
| HTTP 400 / columnas cambiadas | Consulta o esquema incompatible | Detener ese conector y corregirlo; no culpar al usuario ni fingir cero registros |
| HTTP 200 con HTML o JSON inesperado | Contenido inválido | No sobrescribir copia válida |
| Respuesta correcta con cero filas | Sin coincidencias en ese catálogo y filtro | Expresar ese alcance; no concluir ausencia universal del proceso |
| PDF sin texto / cifrado / dañado | Limitación de procesamiento documental | OCR, solicitud de otra copia o revisión humana |
| Falta de pliego, adenda o certificado | Evidencia insuficiente | Estado «no verificable» y lista específica de piezas faltantes |
| Fuente consultable pero atrasada | Vigencia pendiente | Mostrar fechas y bloquear recomendaciones dependientes de actualización |
Cada incidente debe registrar canal, consulta o documento, fecha, HTTP, formato, último éxito, próxima acción y grado de certeza de la causa. El usuario debe ver si falla nuestra implementación, la comunicación, el acceso de origen o la evidencia, sin ocultarlo bajo «error de IA».
Versión local 0.2 preparada y probada:
Retry-After, reintento acotado de timeout/5xx y pausa tras fallos temporales repetidos. Los diagnósticos no ocultan una caída mostrando caché como conexión exitosa.39 pruebas automáticas aprobadas. La importación real devolvió 30 páginas, preservó el hash y permitió recuperar el original local con HTTP 200. Evidencia: evidencia-importacion-v2.json.
Esta caché es de consultas previamente ejecutadas; no es todavía el índice completo ni la sincronización continua propuesta. No se ha desplegado un servicio de producción 24/7. La versión sigue siendo local, con Flask de desarrollo y tareas de IA dentro del proceso del servidor; la cola persistente y el despliegue supervisado forman parte de la siguiente fase.
La extracción de la invitación real terminó seis lotes y produjo 97 condiciones con cita encontrada en el texto. Se descartaron otras 16 propuestas por citas que no superaron el control literal. No se midió todavía qué proporción de esas 97 interpretaciones era correcta ni la exhaustividad frente a revisión jurídica.
Se observaron errores reales del modelo: calificó fechas de 2026 como futuras y algunos lotes indicaron que faltaban requisitos o presupuesto que estaban en otras páginas. La extracción había recorrido el texto, pero sus observaciones no estaban consolidadas. Esto demuestra por qué procesar todas las páginas no equivale a comprender correctamente todo el documento.
La implementación se corrigió para aportar la fecha actual, identificar cada observación como parcial y ejecutar una revisión conjunta con todo el texto local antes de cerrar un análisis nuevo. También se comprueban las citas de esa revisión y se invalida la caché de análisis de la versión anterior. El flujo completo se verificó con prueba automatizada; la revisión conjunta se probó adicionalmente sobre el documento real. La evidencia inicial se conserva en evidencia-analisis-real.json para no ocultar esos fallos. La prueba real de revisión conjunta produjo 15 propuestas: 9 conservaron todas sus citas válidas y 6 se descartaron por referencias no verificadas. Este resultado confirma que sigue siendo necesaria la revisión humana y que no puede certificarse exhaustividad. Evidencia: evidencia-revision-conjunta.json.
Las jornadas siguientes son estimaciones técnicas para un ingeniero con revisión jurídica disponible, no cotización ni plazo garantizado. Las fases de acceso institucional/comercial pueden transcurrir en paralelo y dependen de terceros.
| Fase | Resultado | Criterio de aceptación | Estimación |
|---|---|---|---|
| 1. Integración fiable | SODA con token propio/autorizado, inventario y descargador | Muestra de 30 procesos y hasta 100 documentos: cada intento termina con éxito verificado o causa explícita; medir cobertura real | 3–5 jornadas |
| 2. Servicio continuo | Índice propio, worker, cola, copias y monitoreo | 7 días de piloto; reinicio y caída de origen simulados sin pérdida de trabajos ni falsa actualización | 5–8 jornadas |
| 3. Expediente completo | Versionado, OCR, tablas, anexos y adendas | Inventario reconciliado por proceso; diferencias y piezas no procesadas visibles | 5–10 jornadas |
| 4. Evaluación empresarial | Contratos, personas, certificados, cifras y reglas con evidencia | 20 expedientes revisados por especialista; medir omisiones y falsos cumplimientos antes de permitir conclusiones | 7–12 jornadas |
| 5. Operación privada | Acceso interno, alertas, exportación, presupuesto y recuperación | Restauración de respaldo probada; gastos limitados; responsable de excepciones y decisión final | 3–5 jornadas |
Total orientativo de ingeniería: 23–40 jornadas, más la disponibilidad del especialista y los tiempos externos. No hace falta esperar una API especial para avanzar con búsqueda, conservación, análisis y descargas públicas que ya funcionen.
No fijo una promesa como «99,9% actualizado»: sería mezclar disponibilidad propia con publicación externa. Podemos adoptar objetivos medibles propios después del piloto. Por ejemplo, 99,5% de disponibilidad de aplicación equivale a un máximo de 216 minutos en un mes de 30 días; es un objetivo propuesto, no un resultado medido ni una garantía de datos frescos.
Costo mensual = infraestructura persistente + almacenamiento/respaldo + OCR por páginas que lo necesiten + tokens de IA realmente procesados + API comercial si se contrata + revisión de excepciones. Se instrumentará consumo por expediente y caché de análisis por hash, para no pagar de nuevo por documentos idénticos. No se verificó aquí una cotización comercial ni se contrató un plan.
Ejemplo de dimensionamiento, no medición de mercado: 100 procesos por mes × 8 archivos × 1 MB supone aproximadamente 0,8 GB nuevos mensuales; si cada proceso aporta 80 páginas analizables, serían 8.000 páginas al mes. Debe sustituirse por la muestra real antes de dimensionar almacenamiento y presupuesto IA.
El producto final sí puede dar una conclusión útil: «con la evidencia disponible cumple estos requisitos, falla estos otros, faltan estos soportes y hay estas alertas». Puede construir escenarios de precio o puntaje cuando existan reglas publicadas.
No convertiría esa conclusión en una probabilidad estadística de adjudicación sin datos históricos, ofertas comparables, definición de resultado, evaluación temporal y calibración. Cumplimiento habilitante, puntaje competitivo y resultado de adjudicación son magnitudes diferentes. Para uso propio de la consultora, empezaría por una decisión postular / subsanar evidencia / consultar a la entidad / descartar, con razones y citas.
Superar mínimos no necesariamente produce puntos. Una tasa de coincidencia entre requisitos registrados no debe disfrazarse como porcentaje de ganar. Esta restricción no impide construir el producto; evita una métrica que perjudicaría decisiones reales.
La ruta recomendada es avanzar con API pública + repositorio propio + descarga oficial cuando esté disponible + gestión explícita de excepciones. Una respuesta 403 no debe detener el producto; tampoco debe ocultarse. El resultado útil se logra haciendo que la aplicación distinga lo que sabe, lo que conserva y lo que todavía necesita comprobar.