E1 — Documento de Arquitectura del Sistema¶
Estándar: IEEE 42010 + Modelo C4 · Competencia CE0213
Proyecto: LOGYX — Sistema Operativo Logístico Colaborativo para PYMEs
Equipo: Jorge Gutiérrez Miranda · Fabrizio Sanchez Saravia · Alex Coila Jarita
Versión: 1.0 · Junio 2026
1. Información General¶
| Campo | Detalle |
|---|---|
| Estilo arquitectónico | Monolito Modular → Microservicios (evolución planificada) |
| Estándar de documentación | IEEE 42010 + Modelo C4 |
| Backend | Quarkus 3.x (Java 21) |
| Frontend Web | Angular 18+ |
| Mobile | Flutter 3.x (3 apps) |
| Base de datos | PostgreSQL 16 |
| Infraestructura | Docker + Docker Compose (dev) · Cloud (prod) |
2. Decisiones Arquitectónicas Clave (ADR)¶
ADR-01 — Monolito Modular como punto de partida¶
Contexto: El equipo tiene 8 meses y 3 desarrolladores. Un sistema de microservicios desde el inicio implicaría overhead de infraestructura que consumiría tiempo de desarrollo del producto.
Decisión: Iniciar con un monolito modular en Quarkus. Cada módulo tiene su propio paquete Java con interfaces públicas bien definidas. Los módulos se comunican internamente sin llamadas de red.
Consecuencia: Despliegue simple (un contenedor), desarrollo ágil. Cuando el volumen lo justifique, los módulos de mayor carga (Pricing Engine, Matching Engine) se extraen como servicios independientes sin reescribir la lógica de dominio.
ADR-02 — Quarkus como framework backend¶
Contexto: Se necesita un framework enterprise-grade con soporte para reactive programming, bajo footprint de memoria, y ecosistema robusto para futuros microservicios.
Decisión: Quarkus con MutinyIO (reactive), Panache (ORM), RESTEasy Reactive (REST API) y Quarkus Scheduler (jobs).
Consecuencia: Compilación nativa con GraalVM disponible para producción. Curva de aprendizaje mayor que Spring Boot, pero superior en alineación con la visión enterprise del sistema.
ADR-03 — Tres aplicaciones Flutter independientes¶
Contexto: Los actores del sistema tienen necesidades radicalmente distintas. Mezclar el panel de la PYME con la app del conductor genera interfaces confusas y flujos innecesariamente complejos.
Decisión: Tres apps Flutter separadas que comparten un paquete de dominio compartido: - LOGYX Business: PYME + Empresa Transportista - LOGYX Driver: Conductor (solo ejecución de ruta) - LOGYX Operator: Panel del Operador (versión mobile)
Consecuencia: Mayor trabajo de Flutter, pero UX limpia y enfocada por rol.
ADR-04 — PostgreSQL como base de datos única¶
Contexto: El sistema tiene entidades relacionales complejas (envíos, paradas, ofertas, negociaciones) y necesita integridad referencial fuerte.
Decisión: PostgreSQL 16 con extensión PostGIS para soporte geoespacial. Redis para caché de sesiones y pub/sub de notificaciones en tiempo real.
Consecuencia: Sin base de datos NoSQL adicional en el MVP. Si analytics crece, se evalúa añadir una base columnar (TimescaleDB o ClickHouse) en Fase 2.
ADR-05 — OpenRouteService para cálculo de rutas¶
Contexto: El sistema necesita distancias y rutas reales por carretera (no distancia en línea recta) para el motor de costos y el mapa de tracking.
Decisión: OpenRouteService (ORS) en su tier gratuito (~2,000 req/día). La API key vive solo en el backend (nunca en el cliente).
Consecuencia: Sin costo en el MVP. Migración a Google Maps Distance Matrix si se requiere mayor precisión o volumen en producción.
3. Modelo C4¶
Nivel 1 — Diagrama de Contexto del Sistema¶
C4Context
title LOGYX — Contexto del Sistema
Person(pyme, "PYME", "Empresa que necesita contratar transporte de carga")
Person(carrier, "Empresa Transportista", "Empresa con flota que oferta servicios de transporte")
Person(driver, "Conductor", "Ejecuta físicamente la ruta asignada")
Person(operator, "Operador LOGYX", "Supervisor interno del marketplace")
System(logyx, "LOGYX", "Plataforma digital B2B de logística colaborativa. Marketplace, subastas, tracking, reputación.")
System_Ext(sunat, "SUNAT API", "Validación de RUC de empresas")
System_Ext(ors, "OpenRouteService", "Cálculo de distancias y rutas reales por carretera")
System_Ext(email, "Servicio de Email (SMTP)", "Envío de notificaciones por correo electrónico")
System_Ext(google, "Google OAuth", "Autenticación con cuenta Google")
Rel(pyme, logyx, "Publica cargas, ve subastas, negocia, hace tracking", "HTTPS")
Rel(carrier, logyx, "Oferta en subastas, publica viajes, gestiona flota", "HTTPS")
Rel(driver, logyx, "Ve ruta asignada, actualiza estados, sube evidencias", "HTTPS")
Rel(operator, logyx, "Supervisa operaciones, asigna carriers, gestiona incidencias", "HTTPS")
Rel(logyx, sunat, "Valida RUC en el registro", "HTTPS/REST")
Rel(logyx, ors, "Consulta distancia y ruta real", "HTTPS/REST")
Rel(logyx, email, "Envía notificaciones", "SMTP")
Rel(logyx, google, "Autentica usuarios con OAuth", "HTTPS/OAuth2")
Nivel 2 — Diagrama de Contenedores¶
C4Container
title LOGYX — Contenedores del Sistema
Person(pyme, "PYME / Transportista", "Usuario web y mobile")
Person(driver, "Conductor", "Solo app Driver")
Person(operator, "Operador", "Web y app Operator")
Container(web, "LOGYX Web", "Angular 18+", "SPA web para PYME, Transportista y Operador. Consume API REST.")
Container(mobile_biz, "LOGYX Business", "Flutter", "App mobile para PYME y Transportista")
Container(mobile_driver, "LOGYX Driver", "Flutter", "App simplificada del conductor")
Container(mobile_op, "LOGYX Operator", "Flutter", "Panel de operador en mobile")
Container(api, "LOGYX API", "Quarkus 3 · Java 21", "Monolito modular. Expone REST API. Contiene todos los módulos de negocio.")
ContainerDb(db, "Base de Datos", "PostgreSQL 16 + PostGIS", "Datos relacionales. Toda la persistencia del sistema.")
Container(cache, "Caché / Pub-Sub", "Redis 7", "Sesiones, rate limiting, notificaciones en tiempo real.")
System_Ext(sunat, "SUNAT API", "Validación RUC")
System_Ext(ors, "OpenRouteService", "Rutas y distancias")
System_Ext(email, "Email Service", "Notificaciones")
Rel(pyme, web, "Usa", "HTTPS")
Rel(pyme, mobile_biz, "Usa", "HTTPS")
Rel(driver, mobile_driver, "Usa", "HTTPS")
Rel(operator, web, "Usa", "HTTPS")
Rel(operator, mobile_op, "Usa", "HTTPS")
Rel(web, api, "REST API calls", "HTTPS/JSON")
Rel(mobile_biz, api, "REST API calls", "HTTPS/JSON")
Rel(mobile_driver, api, "REST API calls", "HTTPS/JSON")
Rel(mobile_op, api, "REST API calls", "HTTPS/JSON")
Rel(api, db, "Leer / Escribir", "JDBC / Panache")
Rel(api, cache, "Caché de sesiones / pub-sub RT", "Redis Protocol")
Rel(api, sunat, "Validar RUC", "HTTPS/REST")
Rel(api, ors, "Calcular ruta y distancia", "HTTPS/REST")
Rel(api, email, "Enviar notificaciones", "SMTP")
Nivel 3 — Diagrama de Componentes (Quarkus API)¶
C4Component
title LOGYX API — Componentes internos (Monolito Modular)
Container_Boundary(api, "LOGYX API — Quarkus") {
Component(auth, "auth-module", "Quarkus Security + JWT", "Registro, login, OAuth, validación RUC, RBAC")
Component(shipment, "shipment-module", "Panache + RESTEasy", "Solicitudes de carga, estados, tracking multi-parada")
Component(auction, "auction-module", "Quarkus Scheduler", "Subastas inversas, bids, cierre automático, price floor")
Component(trip, "trip-module", "Panache + RESTEasy", "Viajes publicados por transportistas, reservas de espacio")
Component(negotiation, "negotiation-module", "WebSocket + Redis Pub/Sub", "Chat por solicitud+carrier, contra-ofertas")
Component(pricing, "pricing-module", "ORS client + reglas", "Motor de costos, precio sugerido, price floor")
Component(routing, "routing-module", "ORS client + algoritmos", "Smart Load Planner, matching de retornos, ETA")
Component(matching, "matching-module", "Score engine", "Ranking y filtrado de cargas por perfil de transportista")
Component(reputation, "reputation-module", "Bayesian scoring", "Trust Score, reviews, badges")
Component(fleet, "carrier-module", "Panache", "Flota, vehículos, conductores, capacidad en tiempo real")
Component(notification, "notification-module", "Redis Pub/Sub + Email", "Notificaciones in-app y email")
Component(documents, "documents-module", "MinIO/S3 client", "Upload/download de documentos logísticos")
Component(incident, "incident-module", "Panache", "Incidencias, hilos de comentarios, resolución")
Component(analytics, "analytics-module", "SQL views", "Dashboards de PYME, Carrier y Operador")
}
ContainerDb(db, "PostgreSQL 16", "Base de datos principal")
Container(cache, "Redis 7", "Caché / Pub-Sub")
Rel(auth, db, "users, organizations, profiles")
Rel(shipment, db, "shipment_requests, shipments, shipment_stops")
Rel(auction, db, "auctions, bids")
Rel(trip, db, "carrier_trips, trip_bookings")
Rel(negotiation, db, "messages, counter_offers")
Rel(negotiation, cache, "Pub/Sub para chat en tiempo real")
Rel(pricing, db, "pricing_snapshots, cost_calculations")
Rel(routing, db, "shipment_stops, carrier_trips")
Rel(reputation, db, "reviews, reputation_scores")
Rel(fleet, db, "vehicles, drivers")
Rel(notification, db, "notifications")
Rel(notification, cache, "Pub/Sub para notificaciones RT")
Rel(documents, db, "documents")
Rel(incident, db, "incidents, incident_comments")
Rel(analytics, db, "Consultas analíticas (read-only)")
4. Flujo de Datos — Flujo Principal (Publicar solicitud → Aceptar oferta)¶
sequenceDiagram
participant PYME as PYME (Angular/Flutter)
participant API as LOGYX API (Quarkus)
participant ORS as OpenRouteService
participant DB as PostgreSQL
participant Redis as Redis Pub/Sub
participant Carrier as Transportista (Angular/Flutter)
PYME->>API: POST /shipments/requests (origen, destino, peso, tipo, fecha)
API->>ORS: GET /directions (origen, destino)
ORS-->>API: distance_km, duration_min, geometry
API->>API: pricing-module: calcular precio sugerido
API->>DB: INSERT shipment_request (status=open, suggested_price)
API->>DB: INSERT auction (closes_at = now + 20min, max_bids = 5)
API->>Redis: PUBLISH "new_request" → transportistas compatibles
API-->>PYME: 201 Created {request_id, suggested_price, auction}
Redis-->>Carrier: Notificación: nueva carga compatible
Carrier->>API: GET /marketplace (filtrado por perfil del carrier)
API->>API: matching-module: score y ranking de solicitudes
API-->>Carrier: Lista rankeada de solicitudes abiertas
Carrier->>API: POST /auctions/{id}/bids (precio, vehicle_id, notas)
API->>API: Validar price floor, validar capacidad disponible
API->>DB: INSERT bid (status=pending)
API->>Redis: PUBLISH "new_bid" → PYME propietaria
Redis-->>PYME: Notificación: nueva oferta recibida
PYME->>API: POST /bids/{id}/accept
API->>DB: UPDATE bid (status=accepted), UPDATE otros bids (status=rejected)
API->>DB: INSERT shipment (tracking_code=LGX-XXXXX, status=pending)
API->>DB: UPDATE shipment_request (status=matched)
API->>Redis: PUBLISH "bid_accepted" → transportista
API-->>PYME: 200 OK {shipment_id, tracking_code}
5. Estructura de Módulos del Proyecto¶
logyx-backend/ (Quarkus)
├── src/main/java/com/logyx/
│ ├── auth/
│ │ ├── AuthResource.java ← endpoints REST
│ │ ├── AuthService.java ← lógica de negocio
│ │ ├── JwtUtil.java
│ │ └── model/ ← entidades JPA del módulo
│ ├── shipment/
│ │ ├── ShipmentResource.java
│ │ ├── ShipmentService.java
│ │ ├── AuctionScheduler.java ← Quarkus Scheduler: cierre automático
│ │ └── model/
│ ├── auction/
│ ├── trip/
│ ├── negotiation/
│ ├── pricing/
│ ├── routing/
│ ├── matching/
│ ├── reputation/
│ ├── carrier/
│ ├── notification/
│ ├── documents/
│ ├── incident/
│ └── analytics/
└── src/main/resources/
├── application.properties
└── db/migration/ ← Flyway migrations
logyx-web/ (Angular 18+)
├── src/app/
│ ├── core/ ← guards, interceptors, auth service
│ ├── shared/ ← componentes reutilizables
│ ├── features/
│ │ ├── auth/
│ │ ├── marketplace/
│ │ ├── shipments/
│ │ ├── fleet/
│ │ ├── reputation/
│ │ ├── operator/
│ │ └── returns/
│ └── layout/
logyx-mobile/ (Flutter)
├── packages/
│ ├── shared_domain/ ← lógica pura compartida (cálculos, modelos)
│ ├── logyx_business/ ← app PYME + Transportista
│ ├── logyx_driver/ ← app Conductor
│ └── logyx_operator/ ← app Operador
6. Modelo de Despliegue¶
graph TD
subgraph DEV["Desarrollo Local"]
DC[Docker Compose]
DC --> BE[quarkus-api :8080]
DC --> DB[postgres :5432]
DC --> RD[redis :6379]
DC --> MN[minio :9000]
end
subgraph PROD["Producción — Cloud"]
LB[Load Balancer / Nginx]
LB --> BE_PROD[quarkus-api · Docker container]
BE_PROD --> DB_PROD[PostgreSQL managed · Cloud]
BE_PROD --> RD_PROD[Redis managed · Cloud]
BE_PROD --> S3[Object Storage · S3/MinIO]
end
subgraph CI["CI/CD — GitHub Actions"]
GH[GitHub Push] --> LINT[Lint + Tests]
LINT --> BUILD[Docker Build]
BUILD --> DEPLOY[Deploy to Cloud]
end
subgraph CLIENTS["Clientes"]
ANG[Angular SPA · Vercel/Nginx]
FL_BIZ[Flutter Business · APK/IPA]
FL_DRV[Flutter Driver · APK/IPA]
FL_OP[Flutter Operator · APK/IPA]
end
ANG --> LB
FL_BIZ --> LB
FL_DRV --> LB
FL_OP --> LB
7. Seguridad de la Arquitectura¶
| Capa | Mecanismo |
|---|---|
| Transporte | HTTPS/TLS 1.3 obligatorio en todos los endpoints |
| Autenticación | JWT (access token 1h, refresh token 7 días) + Google OAuth 2.0 |
| Autorización | RBAC a nivel de endpoint (@RolesAllowed) + filtros de datos a nivel de servicio |
| Contraseñas | bcrypt con cost factor 12 |
| API Keys externas | Solo en variables de entorno del servidor, nunca expuestas al cliente |
| Datos sensibles | RUC/DNI parcialmente ofuscados antes del contrato en respuestas de API |
| Rate Limiting | Redis-based rate limiting por IP y por usuario en endpoints de subasta y chat |
| CORS | Orígenes permitidos explícitos (dominio de producción y localhost en dev) |
| SQL Injection | Prevenido por Panache (ORM con parámetros vinculados) |
| XSS | Angular escapa HTML por defecto; CSP headers en el servidor |
8. Calidad y Estándar ISO/IEC 25010¶
| Característica | Cómo se aborda en la arquitectura |
|---|---|
| Funcionalidad | Módulos independientes por dominio de negocio, cobertura de todos los RF |
| Rendimiento | Reactive programming (MutinyIO), índices PostgreSQL, caché Redis |
| Compatibilidad | REST API estándar (JSON), Angular compatible con Chrome/Firefox/Edge, Flutter para Android/iOS |
| Usabilidad | Tres apps separadas por actor (UX enfocada), Angular Material |
| Fiabilidad | Transacciones ACID en PostgreSQL, manejo de errores centralizado |
| Seguridad | JWT + RBAC + HTTPS + bcrypt + rate limiting |
| Mantenibilidad | Monolito modular con límites claros, Flyway para migraciones, código documentado |
| Portabilidad | Docker containers, variables de entorno para configuración, sin vendor lock-in de infraestructura |
LOGYX · E1 Documento de Arquitectura · IEEE 42010 + C4 · Versión 1.0 · Junio 2026