El trigger trg_lock_vehicle_capacity_on_shipment asume que weight_kg existe en la solicitud al momento de crear el envío. Si la solicitud fue modificada después de la subasta, puede haber inconsistencia.
Media
auction / tracking
⬜ Pendiente — ver nota
HLZ-002
El Smart Load Planner ejecuta cada 30 min pero no tiene mecanismo de deduplicación: si una sugerencia no fue respondida, podría generarse otra igual.
Baja
smartload
⬜ Pendiente (Módulo 15 aún no implementado)
HLZ-003
El campo price_floor es GENERATED ALWAYS AS (suggested_price * 0.75). Si suggested_price es NULL (antes de calcular costos), price_floor también es NULL y la subasta podría abrirse sin precio mínimo.
Alta
auction / pricing
✅ Corregido (2026-07-06)
Corrección aplicada — HLZ-003 (2026-07-06): este hallazgo estuvo activo en código desde
Sprint 2 hasta ahora — ShipmentRequestService.create() tomaba suggestedPrice directo del
body del cliente (la PYME), sin invocar nunca al motor de precios (Módulo 11, que en ese
momento ni existía). Se corrigió inyectando PricingService en ShipmentRequestService:
create() calcula suggestedPrice siempre con PricingService.calculate(...).totalEstimate()
a partir de origen/destino/peso/tipo de carga (ya obligatorios en el DTO), y el campo
suggestedPrice se eliminó de CreateShipmentRequestRequest/UpdateShipmentRequestRequest —
ya no es posible que suggested_price llegue NULL ni que el cliente lo fije directamente. Como
efecto, la subasta ahora se abre siempre e incondicionalmente al publicar (antes dependía de que
el cliente enviara el campo), lo cual además corrige de paso una lectura literal más estricta de
RF15. Ver detalle en ROADMAP.md, Módulo 6.
Nota sobre HLZ-001: sigue sin corregirse (no se cachea weight_kg en auctions). El riesgo
es menor de lo que parece porque ShipmentRequest.assertEditable() solo permite PATCH mientras
status='open', y desde la corrección de HLZ-003 toda solicitud pasa a auction_open de forma
inmediata e incondicional al crearse — en la práctica ya no queda ventana para editar weightKg
con una subasta abierta usando el flujo normal de creación. Se mantiene el hallazgo abierto por
disciplina (no se verificó exhaustivamente que no haya otro camino de código que reabra ese
estado), pero el escenario que lo originaba dejó de ser alcanzable en el flujo estándar.
Plan de corrección:
ID
Corrección propuesta
Sprint
HLZ-001
Cachear weight_kg al momento de crear la subasta (snapshot en tabla auctions)
S3
HLZ-002
Agregar constraint UNIQUE (carrier_org_id, vehicle_id, request_ids) en smart_load_suggestions y verificar antes de insertar
S7
HLZ-003
~~Bloquear apertura de subasta si suggested_price IS NULL. Forzar cálculo de costos antes de publicar solicitud.~~ ✅ Corregido 2026-07-06 (ver arriba)
// k6-load-test.js — Prueba de carga básica para el marketplaceimporthttpfrom'k6/http';import{check,sleep}from'k6';exportconstoptions={stages:[{duration:'1m',target:50},// Ramp-up a 50 usuarios{duration:'3m',target:100},// Sostener 100 usuarios{duration:'1m',target:0},// Ramp-down],thresholds:{http_req_duration:['p(95)<2000'],// 95% de requests < 2shttp_req_failed:['rate<0.01'],// < 1% de errores},};exportdefaultfunction(){consttoken=__ENV.TEST_TOKEN;// Simular PYME revisando el marketplace (carga más frecuente)constres=http.get(`${__ENV.BASE_URL}/api/v1/shipment-requests?status=open`,{headers:{Authorization:`Bearer ${token}`}});check(res,{'status es 200':(r)=>r.status===200,'respuesta en < 2s':(r)=>r.timings.duration<2000,'lista no está vacía':(r)=>JSON.parse(r.body).data.length>=0,});sleep(1);}
Optimizaciones previstas:
Optimización
Impacto esperado
Sprint
Índice compuesto (status, required_date) en shipment_requests
-40% tiempo del marketplace
S1 (ya incluido en V6)
Caché Redis para el ranking del marketplace (TTL: 60s)
-60% carga en BD en horas pico
S7
PgBouncer en modo transaction (pool 20 conexiones)
Soportar 200 conexiones concurrentes
S8
Índice parcial WHERE status IN ('open','filling') en carrier_trips
Las URLs presignadas de MinIO (7 días) son muy largas para documentos sensibles.
Media
Reducir expiración a 24h y regenerar si el usuario vuelve a pedir
SEC-003
El campo org_type puede ser cambiado manualmente en la BD. Un carrier podría convertirse en operator.
Media
Agregar trigger que audite y bloquee cambios de org_type después del onboarding
SEC-004
No hay límite de intentos fallidos de login (brute force).
Alta
Implementar bloqueo temporal (5 intentos → 15 min de espera) con Redis
SEC-005 (agregado 2026-07-06, verificado contra el código)
Row-Level Security (E2_Seguridad.md sección 2.3) está completamente diseñado pero no implementado: ninguna migración habilita RLS ni crea las políticas rls_*, y el backend nunca ejecuta SET app.current_org_id. Hoy el único control de acceso por organización es a nivel de aplicación (filtros en repository/service) — si algún endpoint futuro olvida ese filtro, no hay defensa en profundidad a nivel de BD.
Media
Implementar las políticas RLS de E2_Seguridad.md §2.3 antes de producción, o documentar explícitamente que se acepta el riesgo mientras el filtro de aplicación sea la única defensa
SEC-006 (agregado 2026-07-06, verificado contra V8__triggers.sql)
De las 6 tablas que E2_Seguridad.md §4.1 documenta como auditadas, solo 4 tienen trigger real (trg_audit_shipments/bids/auctions/incidents). Cambios de organizations.verified y profiles.role — ambos catalogados como "críticos" en el mismo documento y cubiertos por RNF15 — no quedan en audit_log.
Media
Agregar trg_audit_organizations y trg_audit_profiles (mismo patrón que los 4 existentes)
67 de 67 RF documentados y trazados. 3 hallazgos de diseño identificados y con plan de corrección.
Rendimiento
★★★☆☆
Índices definidos, configuración de PG optimizada, pruebas de carga pendientes de ejecutar.
Seguridad
★★★☆☆
Base sólida (JWT, bcrypt, TLS, RLS). 4 hallazgos identificados con plan de mitigación en S1–S6.
Mantenibilidad
★★★★☆
Arquitectura modular, CI/CD con Conventional Commits, cobertura de pruebas pendiente de alcanzar objetivo.
Portabilidad
★★★★★
Docker + Flyway + variables de entorno garantizan reproducibilidad completa.
Veredicto: El sistema LOGYX está correctamente concebido y arquitecturado para su desarrollo. Los hallazgos identificados son abordables dentro del plan de sprints. No existen bloqueadores críticos para el lanzamiento del MVP.
LOGYX · E4 Auditoría Técnica · Competencia CE0244 · Versión 1.0 · Junio 2026