# Architecture — Xpeditis **Xpeditis** est une plateforme B2B SaaS de réservation de fret maritime, construite en monorepo avec une architecture hexagonale stricte côté backend. --- ## Vue d'ensemble système ``` ┌─────────────────────────────────────────────────────────────┐ │ Frontend (Next.js 14 + App Router) │ │ React 18 · TanStack Query · Socket.IO · next-intl (i18n) │ └──────────────────────────┬──────────────────────────────────┘ │ HTTPS / WSS ┌──────────────────────────▼──────────────────────────────────┐ │ Backend (NestJS 10) │ │ JWT Auth · Rate Limiting · Swagger OpenAPI │ └────┬──────────┬──────────┬──────────┬──────────┬────────────┘ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ Rates Bookings Users Carriers CSV System Service Service Service Service Service │ │ │ │ │ └──────────┴──────────┴──────────┴──────────┘ │ ┌──────────────────┼──────────────────┐ ▼ ▼ ▼ PostgreSQL 15 Redis 7 MinIO (S3) (données) (cache 15min) (documents) ``` --- ## Architecture hexagonale (backend) ``` apps/backend/src/ ├── domain/ # Logique métier pure — zéro dépendance framework │ ├── entities/ # 17 entités métier │ ├── value-objects/ # Objets valeur immuables │ ├── services/ # Services métier purs │ ├── ports/in/ # Interfaces use-case (execute()) │ └── ports/out/ # Interfaces repository/SPI │ ├── application/ # Controllers, DTOs, Guards │ ├── controllers/ # REST controllers avec Swagger │ ├── dto/ # DTOs class-validator │ ├── mappers/ # Domain ↔ DTO │ ├── guards/ # JwtAuthGuard, RolesGuard, ApiKeyGuard │ ├── gateways/ # WebSocket (Socket.IO) │ └── services/ # Services applicatifs (audit, notification) │ └── infrastructure/ # Adaptateurs externes ├── persistence/ # TypeORM (entities, repositories, mappers, migrations) ├── carriers/ # Connecteurs carriers + CSV loader ├── cache/ # Adaptateur Redis ├── email/ # MJML + Nodemailer ├── storage/ # S3/MinIO + CSV storage ├── stripe/ # Abonnements et paiements ├── external/ # Pappers (SIRET) ├── pdf/ # Génération PDF (pdfkit) └── monitoring/ # Sentry, logging Pino ``` **Règles de dépendance** : - Domain : aucune dépendance externe (TypeScript pur) - Application : dépend uniquement du domain - Infrastructure : dépend uniquement du domain - Le flux de dépendances pointe toujours vers le centre --- ## Stack technique ### Backend | Composant | Technologie | |-----------|-------------| | Framework | NestJS 10.x | | Langage | TypeScript 5.3+ strict | | ORM | TypeORM 0.3.x | | Base de données | PostgreSQL 15+ | | Cache | Redis 7+ (ioredis) | | Auth | JWT (15min) + Refresh tokens (7j) + OAuth2 | | Auth alternative | API Keys (Argon2 hash) | | WebSocket | Socket.IO | | Email | Nodemailer + MJML templates | | PDF | pdfkit | | Paiements | Stripe | | Stockage fichiers | S3 / MinIO | | Validation | class-validator + class-transformer | | Docs API | Swagger/OpenAPI | | Logging | nestjs-pino (pino-pretty dev) | | Monitoring | Sentry | | i18n | nestjs-i18n | | Circuit breaker | opossum (5s timeout carriers) | ### Frontend | Composant | Technologie | |-----------|-------------| | Framework | Next.js 14 (App Router) | | Langage | TypeScript | | Styling | Tailwind CSS | | State serveur | TanStack Query v5 | | Tables | TanStack Table v8 + Virtual | | Formulaires | react-hook-form + zod | | Temps réel | Socket.IO client | | Graphiques | recharts | | Cartes | react-leaflet | | i18n | next-intl (fr, en) | | Éditeur riche | Tiptap | | État global | zustand | | Animations | framer-motion | --- ## Modules NestJS **Guards globaux** : `JwtAuthGuard` (toutes les routes protégées par défaut), `CustomThrottlerGuard` **Feature modules** : - Auth, Rates, Ports, Bookings, CsvBookings, Organizations, Users - Dashboard, Audit, Notifications, Webhooks, GDPR, Admin - Subscriptions, ApiKeys, Blog, Logs **Infrastructure modules** : - CacheModule (Redis), CarrierModule, SecurityModule - CsvRateModule, StripeModule, PdfModule, StorageModule, EmailModule --- ## Flux clés ### Recherche de tarifs (FCL) ``` POST /api/v1/rates/search → Vérification cache Redis (TTL 15min) → Si cache miss : appel parallel carriers API (5s timeout + circuit breaker) → Normalisation résultats → stockage Redis → Réponse JSON paginée ``` ### Réservation standard ``` POST /api/v1/bookings → Validation DTO → Génération WCM-YYYY-XXXXXX → Persistance PostgreSQL → Audit log → Notification WebSocket → Déclenchement webhooks → Email confirmation (MJML) → PDF booking ``` ### Portail Carrier (CSV Bookings) ``` Admin crée CSV booking → assigne carrier → Email magic link (1h expiry) → Carrier s'authentifie via token → Accept/Reject → Activité logguée ``` ### Abonnements ``` Stripe webhook → /api/v1/subscriptions/webhook → Vérification signature HMAC → Mise à jour subscription + license ``` --- ## Sécurité | Mesure | Implémentation | |--------|---------------| | Rate limiting | 100 req/min global, 5/min auth, 30/min search | | Password hashing | Argon2id | | JWT | Access 15min + Refresh 7j avec rotation | | API Keys | Argon2 hash, préfixe xped_ | | Brute force | Exponential backoff après 3 échecs | | Headers sécurité | Helmet.js (CSP, HSTS, XSS) | | Validation | class-validator sur tous les DTOs | | RBAC | 5 rôles : ADMIN, MANAGER, USER, VIEWER, CARRIER | | CORS | Origines strictes | | Upload fichiers | Validation MIME, max 10MB | | GDPR | Export/suppression données utilisateur | --- ## Performances - Recherche tarifs (avec cache) : < 2s (p90) — ~500ms observé - Création booking : < 3s — ~1s observé - Dashboard (5k bookings) : < 1s - Cache hit ratio cible : > 90% --- ## Déploiement L'application est containerisée (Dockerfile dans chaque app). - **Développement** : docker-compose (PostgreSQL + Redis + MinIO) - **Production** : Portainer / Docker Swarm ou Kubernetes (Hetzner) - **CI/CD** : GitHub Actions (`.github/workflows/`) Voir [../deployment/portainer.md](../deployment/portainer.md) et [../deployment/hetzner/README.md](../deployment/hetzner/README.md). --- *Dernière mise à jour : Mai 2026*