Files
Autoparts-DB/docs/plans/2026-10-11-auditoria-completa-mejoras-ia.md
consultoria-as a386ca5b4a
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled
Mejoras de sesion: estabilizacion, IA, Nexus Yonke y marketplace B2B
- F0 blindaje: Redis/Celery, pg_hba sin trust LAN, secretos a env 600, backups, webhook auth, jobs muertos
- F1 caja: bugs POS, reembolsos al corte, apartados, CFDI, topes de descuento en cotizacion/apartado
- F2/F7 IA de catalogo: autocategorizacion, dedup de SKUs con embeddings, OCR de facturas, descripciones, claves SAT, limpieza de fitment
- F3 IA en el flujo: vision Yonke, preguntas MeLi, venta cruzada, anomalias, sinonimos, busqueda semantica (rerank/embeddings)
- F4/F8 escala y cartera: /metrics+Prometheus+Grafana, pool, score de credito, churn, metricas multi-tenant
- Nexus Yonke (M1-M6): modelo de datos 1-de-1, alta por donador, vitrina publica, MeLi usado, consignacion, garantia por dias, reportes, etiquetas
- Marketplace B2B entre yonkes (catalogo + pedidos cross-tenant)
- Seguridad: auth en /api/admin/* (35 endpoints), alertas por tenant
- Migraciones v4.27/v4.28; timers expire-demos y rollup-metrics
2026-10-12 00:57:31 +00:00

15 KiB
Raw Permalink Blame History

Auditoría completa de la plataforma + IA no conversacional — Nexus Autoparts

Fecha: 11-oct-2026 · Base: 6 investigaciones con evidencia en archivo:línea, SQL real y estado del host. Énfasis solicitado: áreas de mejora + IA no conversacional (predicción, clasificación, visión, OCR, anomalías, matching).


0. Resumen ejecutivo

La plataforma es hoy, en los datos, un catálogo de autopartes con fitment masivo (≈21 M relaciones pieza-vehículo y ≈406 K equivalencias) más un POS funcional pero con poco volumen transaccional (máximo 24 ventas en un tenant; la única serie temporal real son 4,582 ventas históricas de Atlas en 19 meses). El código de IA existente es LLM + visión (QWEN/Hermes/Gemma) y Meilisearch; no hay ML clásico instalado.

Hay tres frentes con problemas:

  1. Operación/seguridad (grave y barato de arreglar): firewall abierto, Postgres con trust en toda la LAN, secretos en texto claro, Redis caído 6 días → todo Celery muerto, alertas silenciosas (sin ALERT_PHONES), backups que fallaron 5 días sin avisar.
  2. Bugs de producto en caja (visibles al usuario hoy) y funciones construidas pero sin cablear (garantías, notificaciones de taller, lealtad, venta cruzada, flotillas).
  3. Calidad de datos que bloquea el catálogo, la publicación en MercadoLibre y el SEO: 0 imágenes, 0 descripciones, reorder_point 100% NULL, 0 precios de proveedor, 52 listings sin inventory_id.

IA no conversacional: qué sí tiene sentido hoy (no depende de volumen de ventas): auto-categorización de productos (ML y taxonomía), deduplicación/matching de SKUs, OCR/VLM de facturas de proveedor, visión para graduar piezas usadas (Yonke), semantic search por embeddings, y detección de anomalías de negocio (descuentos/stock). Qué NO vale la pena todavía: forecast de demanda (cold start), triage de logs con LLM, agrupación de alertas con ML (overkill).


1. Operación y seguridad — P0 (hacer ya)

# Hallazgo Evidencia Acción
1 Postgres con trust para toda la LAN + puerto 5432 abierto en 0.0.0.0 pg_hba.conf: host all all 192.168.10.0/24 trust; iptables -S → INPUT ACCEPT sin reglas; ufw no instalado Quitar trust (usar scram-sha-256), listen_addresses a localhost/LAN acotada, firewall
2 Secretos en claro en unit files world-readable nexus-pos.service (QWEN/FACTURAPI/JWT/INTERNAL/MEILI keys), nexus-manager.service, nexus.service, meilisearch.service EnvironmentFile modo 600 o systemd-creds; rotar llaves
3 Redis caído 6 días → Celery en bucle de muerte systemctl status redis-server = failed; celery.log: Cannot connect to redis://localhost:6379/1 (55/100) desde hace 6 días Levantar Redis (o quitarlo del diseño); hoy toda tarea Celery está caída
4 Alertas silenciosas /etc/nexus/alert.env sin ALERT_PHONES → alerts.log: ALERT no ALERT_PHONES configured; RedisDown activo 6 días sin consecuencia Poblar alert.env, segundo canal (email/Slack), alertas de backup/Celery/app-down
5 Backups: fallaron 5 días en silencio (7–11 oct); solo locales; 3.5 GB zombi journalctl -u nexus-backup; BACKUP_S3_BUCKET sin definir; cleanup no borra .dump/.sql viejos Ya corregí el ((deleted++)); falta validar el timer 02:00, offsite S3 y limpieza
6 Sin TLS en este host solo listen 80; no hay 443 Confirmar proxy/Cloudflare delante, o terminar TLS
7 Endpoints expuestos Grafana admin/nexus2026; Prometheus/Alertmanager sin auth; webhook /pos/api/notifications/webhook POST sin auth Auth + bind a localhost
8 Servicios como root y timers muertos (nexus-quart, cache-warm, mv-refresh, cron.d inexistente) systemctl status Erradicar jobs muertos / matrices obsoletas

Observabilidad: Prometheus/Grafana/Alertmanager corren y scrapean infra, pero la app no expone /metrics (:5001/metrics → 404; grep prometheus_client = 0) → el dashboard "Nexus — Application" está vacío. Falta pg_stat_statements cargado (shared_preload_libraries vacío) y log_min_duration_statement activo.

Escalabilidad: el pool es por proceso (tenant_db.py:24-32, minconn=2, maxconn=20 × 8 workers gunicorn) → ~160 conexiones/tenant en el peor caso; sin PgBouncer. 8 tenants van sobrados; a ~15-20 tenants calientes revienta max_connections=200. A 100 es insostenible.


2. Bugs de producto en caja — P0/P1

Sev Bug Evidencia
P0 Venta offline rota: totals['total'] no existe → ReferenceError, el ticket offline nunca se muestra pos/static/js/pos.js:1587
P0 Devolución muestra reembolso $0: lee res.refund_total, el API devuelve total_refund pos.js:978 vs pos_bp.py:2628
P0 Apartado liquidado no muestra la venta: lee res.sale_id, el API devuelve {id,...} pos.js:1054 vs pos_bp.py:2377
P0 "Facturar CFDI" no hace nada: se manda generate_cfdi pero ningún backend lo lee pos.js:1519; grep generate_cfdi en pos/**/*.py = 0
P0 Reembolsos no entran al corte de caja → efectivo esperado sobreestimado pos_bp.py:2454 no inserta cash_movements; cashregister_bp.py:195-314 no resta devoluciones
P1 Apartado cancelado no revierte contabilidad (pasivo fantasma 240) pos_bp.py:2389-2449
P1 Apartado se liquida siempre como efectivo (aunque sea tarjeta) pos_bp.py:2291,2332
P1 Descuento/tope de precio solo se valida en venta directa (cotización/apartado la evaden) pos_engine.py:290-295; pos_bp.py:822,1212,1704,1864
P1 Devoluciones sin control de rol (solo pos.sell) pos_bp.py:2455
P1 500 por query param sin validar (?per_page=abc) error.log; /pos/api/marketplace-ext/*

Construido pero sin cablear: garantías/RMA nunca se registran al vender (warranty_bp.py:41); notify_order_ready/notify_maintenance_due existen y no se llaman; lealtad acumula pero no se puede canjear en el POS; venta cruzada muerta (part_kits.py no se importa); flotillas fuera del menú (sidebar.js no incluye fleet); analytics de cliente (LTV/churn) calculado y no mostrado (crm_bp.py:227, crm_engine.py:289).


  • Imágenes: 0 en todos los tenants (image_url vacío; inventory_images 0 filas). Bloquea publicar en ML, el catálogo público y el SEO.
  • supplier_catalog: 17,246 items, 0 con imagen, 0 con descripción.
  • reorder_point/reorder_qty 100% NULL; min_stock=0 en ~95% → las alertas de stock bajo nunca disparan; reorder_alerts = 0 filas.
  • Filtro de sucursal roto en reorden: filtra por inventory.branch_id, que es NULL al 100%.
  • Motor de Proveedores/Órdenes de Compra completo y sin uso (purchase_orders = 0 filas en todos los tenants); supplier_catalog_prices = 0; catalog_part_id 0/14,568 → sin precios/margen de proveedor.
  • Fitment: inventory_vehicle_compat de Estrada = 20.7 M filas / 129,101 items ≈ 160 por pieza (99.5% salida QWEN, conf 0.843) — ruidoso; Capa/Rached usan supplier_catalog (0.95, limpio).
  • Búsqueda: Meili cubre inventario y proveedor, pero el índice nexus_parts (1.55 M docs TecDoc) sigue re-indexándose y está muerto; los aliases/cross-refs no entran a smart_search; sin sinónimos.
  • Estrada y Originales Autopartes son clones exactos (mismos 157,243 SKUs y 20,687,557 fitments) → cuéntalos una vez.

4. IA no conversacional — qué construir (y en qué orden)

4.1 Lo que ya existe (reutilizable)

  • ai_chat.classify_part() (ai_chat.py:379) → número OEM a {name, brand, vehicle, category}.
  • ai_chat.chat_with_image() (ai_chat.py:309) → visión: identifica una autoparte por foto (Gemma/QWEN).
  • qwen_fitment.py → compatibilidad pieza-vehículo validada contra la maestra (con confidence).
  • whisper_local.py → ASR local (faster-whisper, CPU) para notas de voz.
  • Meilisearch (keyword + typos; soporta vectores) con índices poblados.
  • nexpart_taxonomy.py → 558 etiquetas (dataset listo para clasificador); wa_learning.get_learning_pairs_for_training() (:73) → pares texto→producto etiquetados.
  • Infra lista para OCR: tesseract + pytesseract + ffmpeg + pdftotext ya instalados.
  • No hay sklearn/torch/transformers/faiss; sin GPU (12 vCPU / 47 GB). Inferencia en CPU o vía QWEN/Hermes.

4.2 Propuestas priorizadas por viabilidad de datos (no por moda)

Prio Implementación Punto de integración Datos (reales hoy) Enfoque Beneficio
A1 Auto-categorización de productos (taxonomía Nexpart + categoría ML) inventory_bp.py:129 (hoy no persiste) y marketplace_external_service.py (publish); ML ya tiene domain_discovery en meli_service.py:280 171 K SKUs, 18 K sin categoría; taxonomía de 558 etiquetas Reglas → embeddings (Meili) → LLM (classify_part) como fallback Habilita navegación/filtros y publicación en lote sin elegir categoría a mano
A2 Deduplicación / matching de SKUs (poblar catalog_part_id + aliases) catalog_import_service.py:57-76 406 K interchange + 9 K + 4 K aliases Normalización + blocking por prefijo + similitud de embeddings Desbloquea precios de proveedor, margen y enriquecimiento (hoy link 0%)
A3 OCR/VLM de facturas de proveedor supplier_engine.receive_po:214 / compra directa inventory_bp.py:1198 Facturas PDF/foto (infra ya instalada) pdftotext+Tesseract y VLM (chat_with_image) + validación contra catálogo Elimina captura manual y alimenta supplier_catalog_prices (hoy vacío)
A4 Visión para graduar piezas usadas (Yonke) yonke_bp.py:145 (subida de fotos) Fotos de piezas (hoy 0) VLM que sugiera condition_grade (A/B/C/D) y defectos; validar encuadre antes de publicar Alta consistente <30 s, menos devoluciones, confianza del comprador
A5 Anomalías de negocio (descuentos, merma de stock, precios mal capturados) post-commit de venta pos_engine.py:462 + job nocturno sobre sale_items/inventory_operations/audit_log Ventas/ops por tenant EWMA/z-score robusto o Isolation Forest por empleado/SKU/sucursal Detecta fuga de margen que los topes no capturan (apartados/cotizaciones los evaden)
A6 Semantic search (embeddings + sinónimos) meili_search.py:23, index_meilisearch.py:47 Nombres/SKUs/cross-refs Vectores en Meili (híbrido) + sinónimos + indexar interchange "balatas"→"Brake Pad"; búsqueda por número cruzado
A7 Clasificación/priorización de preguntas de MeLi (+ auto-respuesta por plantilla) service.py:1151 (sync_questions → _upsert_question) 18 preguntas (4 sin responder desde mayo) Clasificador de intención (compat/precio/envío) + plantillas + vehicle_compatibility SLA (ML penaliza respuestas lentas) y más conversión
A8 Enriquecimiento de imágenes (scraping + tagging por nombre de parte) image_scraper.bulk_import:71, image_service.save_image:74 supplier_catalog 0 imágenes Scraping existente + VLM para validar/clasificar Desbloquea catálogo público, SEO y publicación ML
A9 Score de riesgo de crédito (fiado) validación en pos_engine.py:314, get_customer customers_bp.py:133 Clientes + aging (pocas ventas aún) Regresión logística/heurística ponderada (mora>30d) Menos incobrables; subir límites a buenos clientes
A10 Venta cruzada "esto + esto" hook muerto part_kits.build_kit_text; pos.js:403 al agregar al carrito sale_items + KIT_SUGGESTIONS Reglas de asociación/co-ocurrencia, fallback a kits +5-15% ticket típico
A11 Forecast de demanda / punto de reorden reorder_engine.py:26,78 Cold start: máx 24 ventas; única serie = Atlas historical_sales (4,582 / 19 meses) Media móvil/Exponencial (ROP = μ·LT + z·σ); ML real cuando haya volumen ⚠️ Hoy bloqueado por datos; arrancar con reglas y migrar
A12 Churn / próxima compra crm_engine.py:289 (hoy umbrales fijos) 52% de compradores de Atlas recompran BG/NBD o regresión de intervalo intercompra Campañas de reactivación dirigidas

4.3 Lo que NO vale la pena (honestidad)

  • Triage de logs con LLM: el volumen de errores es de KB/día; deduplicar por firma con reglas gana y cuesta cero.
  • Agrupación de alertas con ML: hoy hay un receiver y cero alertas útiles; arreglar el routing da el 100% del valor.
  • Predicción de capacidad con IA: predict_linear(disk[6h], 7d) en PromQL ya responde; es una alerta, no un modelo.
  • Forecast de demanda hoy: sin historial transaccional, cualquier modelo sería ruido.

5. Roadmap propuesto

Fase Foco Entregable verificable
F0 — Blindar (2-3 días) Seguridad (pg_hba/firewall/secretos), Redis arriba, alerting, validar backup timer + offsite, 500 de query params, borrar jobs muertos Celery vivo; alerta de backup llega a un humano; 5432 cerrado
F1 — Caja correcta (1 sem) Bugs P0 de pos.js, reembolsos→caja, reversa de apartado, forzar topes de descuento también en cotización/apartado, cablear/eliminar generate_cfdi Corte de caja cuadra con devoluciones; ticket offline funciona
F2 — IA de datos (2-3 sem) A1 auto-categorización, A2 dedup SKUs, A3 OCR facturas, A8 imágenes ≥90% SKUs categorizados; factura de proveedor → líneas en <1 min; catálogo con imágenes
F3 — IA en el flujo (2-3 sem) A4 visión Yonke, A6 semantic search, A5 anomalías, A7 preguntas, A10 venta cruzada Grado sugerido por foto; búsqueda por sinónimo; alerta de descuento anómalo; sugeridos en carrito
F4 — Escala y producto (3-4 sem) PgBouncer + pool, /metrics de app + pg_stat_statements, A9 crédito, A12 churn, A11 forecast cuando haya datos, WA CRM piloto 30+ tenants sin agotar conexiones; dashboard con métricas reales; score de crédito en fiado

6. Métricas de éxito

  • Seguridad/ops: 0 servicios DB con trust; 0 secretos en unit files legibles; alertas de backup/Celery entregadas; 30 días de backups verificados (local + offsite).
  • Producto: corte de caja cuadra con devoluciones; 0 ReferenceError en POS; 100% de SKUs categorizados; catálogo público con >80% de items con imagen.
  • IA: ≥90% de facturas de proveedor parseadas sin captura manual; grado de pieza usada sugerido y aceptado en ≥70% de altas; búsquedas sin resultado reducidas >30% (semantic); ≥1 alerta real de anomalía accionada por mes.