00 — VARIABLES GLOBALES, STACK & STRUCTURE IaC
Objectif
Ce document est le socle de référence du projet. L'agent doit le lire avant tout autre fichier. Il contient les variables globales, la stack technique retenue avec les justifications, l'inventaire complet des services, et la structure IaC que l'agent doit respecter.
Aucun script n'est à générer à partir de ce fichier. C'est un document de contexte et de décisions.
1. IDENTITÉ DU PROJET
| Clé | Valeur |
|---|---|
| Nom du projet | Nex |
| Domaine technique | paywithnex |
| Type | Fintech — services financiers numériques (mobile money) |
| Zone cible | CEMAC (Afrique centrale) |
| Régulateur | BEAC / COBAC |
| Équipe technique | 3 développeurs + 1 CDP |
| Architecture | Microservices (11 services NestJS + 2 dashboards Nuxt + 2 apps mobiles React Native) |
2. INVENTAIRE TECHNIQUE COMPLET
2.1 Applications Front-End
| App | Framework | Mode | UI | Package Manager | Déploiement |
|---|---|---|---|---|---|
| CMMS Dashboard | Nuxt 4.2.2 | SPA (SSR désactivé) | Nuxt UI 4.3 + Tailwind | pnpm | Firebase Hosting |
| Backoffice | Nuxt 4.2.2 | SSR ou SPA | Nuxt UI 4.3 + Tailwind | pnpm | Firebase Hosting |
Stack commune front : TypeScript 5.9.x, Pinia (state), Zod (validation).
2.2 Applications Mobiles
| App | Framework | Déploiement |
|---|---|---|
| App Client | React Native | App Store (iOS) + Google Play (Android) |
| App Marchand | React Native | App Store (iOS) + Google Play (Android) |
2.3 Microservices Back-End
Socle commun à tous les services :
| Élément | Détail |
|---|---|
| Framework | NestJS 11.0.1 |
| Langage | TypeScript |
| Base de données | PostgreSQL (pg 8.16.3) — sauf logs-reporting |
| ORM | TypeORM 0.3.27 |
| Build | SWC (@swc/cli, @swc/core) |
| Tests | Jest + Supertest |
| Documentation API | Swagger / OpenAPI |
| Linting | ESLint + Prettier |
Détail par service :
| # | Service | Port | Base de données | Redis | Dépendances externes | Exposition |
|---|---|---|---|---|---|---|
| 1 | auth | 3001 | PostgreSQL | Oui (sessions, cache) | Auth0, JWT, bcrypt | Publique (via Ingress) |
| 2 | ledger-wallets | 3002 | PostgreSQL | Non | Axios, seeders wallets | Interne |
| 3 | customer-profiles-kyc | 3003 | PostgreSQL | Non | — | Interne |
| 4 | orchestrator | 3004 | PostgreSQL | Non | Axios (appels inter-services) | Publique (via Ingress) |
| 5 | notifications | 3005 | PostgreSQL | Non | Firebase FCM, Axios | Interne |
| 6 | configuration | 3006 | PostgreSQL | Non | Seeders données ref. | Publique (via Ingress) |
| 7 | file-service | 3007 | PostgreSQL | Non | Firebase Storage, Multer | Interne |
| 8 | providers-gateway | 3008 | PostgreSQL | Non | — | Interne |
| 9 | risk-engine | 3009 | PostgreSQL | Non | — | Interne |
| 10 | service-catalog | 3010 | PostgreSQL | Oui (cache) | Axios, OpenAPI Generator | Interne |
| 11 | logs-reporting | 3011 | Aucune | Non | — | Interne |
Note : ces ports correspondent au code existant dans le monorepo. Ne pas les modifier.
2.4 Architecture du monorepo
Le projet est un monorepo unique (nex/) hébergé dans un seul repo GitLab, géré par pnpm workspaces et Turborepo.
nex/ # Racine du monorepo (un seul repo GitLab)
├── apps/
│ ├── mobile-client/ # Expo SDK 53 / RN 0.79.5 — App Client (NokiPay)
│ ├── mobile-pro/ # Expo SDK 53 / RN 0.79.5 — App Marchand (NxPay Business)
│ ├── cmms/ # Nuxt 4.2.2 · SPA · Nuxt UI · Tailwind
│ └── backoffice/ # Nuxt 4.2.2 · Nuxt UI · Tailwind
├── packages/
│ ├── tokens/ # Design tokens (ZERO deps, platform-agnostic)
│ ├── ui-mobile/ # Design system React Native (raw TS, Metro transpiles)
│ ├── ui-web/ # Design system Web (CSS themes Nuxt UI)
│ ├── shared-types/ # DTOs, enums, interfaces (ZERO deps)
│ ├── shared-utils/ # Formatters, validators, CEMAC constants
│ ├── eslint-config/ # Configs ESLint partagées
│ └── tsconfig/ # Configs TypeScript partagées
├── services/
│ ├── auth/ # NestJS · PostgreSQL · Redis · Auth0
│ ├── ledger-wallets/ # NestJS · PostgreSQL · Seeders (critique)
│ ├── customer-profiles-kyc/ # NestJS · PostgreSQL
│ ├── orchestrator/ # NestJS · PostgreSQL · Cucumber (BDD tests)
│ ├── notifications/ # NestJS · PostgreSQL · Firebase FCM
│ ├── configuration/ # NestJS · PostgreSQL · Seeders
│ ├── file-service/ # NestJS · PostgreSQL · Firebase Storage
│ ├── providers-gateway/ # NestJS · PostgreSQL
│ ├── risk-engine/ # NestJS · PostgreSQL
│ ├── service-catalog/ # NestJS · PostgreSQL · Redis
│ └── logs-reporting/ # NestJS (sans BDD)
├── infrastructure/ # Tout l'IaC (voir section 6)
├── infra-2026/ # Documentation du plan de déploiement
├── pnpm-workspace.yaml
├── turbo.json
├── package.json
└── .gitlab-ci.yml # Pipeline CI/CD unique à la racineConséquences pour le CI/CD :
- Un seul
.gitlab-ci.ymlà la racine du monorepo - Turborepo pilote la détection des changements (
--filter=...[origin/staging...HEAD]) - Un seul Dockerfile templatisé pour les 11 services (voir section 6)
- Le contexte Docker est la racine du monorepo (les services dépendent des packages locaux)
3. VARIABLES GLOBALES
L'agent utilise ces variables pour paramétrer chaque script et manifest. Aucune valeur ne doit être hardcodée ailleurs.
# ============================================================
# NEX — VARIABLES GLOBALES
# ============================================================
# --- Projet ---
project_name: "nex"
project_domain: "paywithnex"
company_name: "Nex"
# --- AWS ---
aws_region_primary: "eu-west-1" # Ireland
aws_region_backup: "eu-west-3" # Paris (backups cross-région)
aws_account_id: "XXXXXXXXXXXX" # À remplir
# --- Environnements ---
environments:
staging:
shortname: "stg"
eks_cluster: "nex-staging"
rds_db: "nex_staging"
production:
shortname: "prd"
eks_cluster: "nex-production"
rds_db: "nex_production"
review:
# Environnements éphémères de review (un par epic/branche)
# Déployés comme namespaces temporaires sur le cluster staging
shortname: "rev"
eks_cluster: "nex-staging" # Réutilise le cluster staging
namespace_pattern: "nex-review-{branch}"
rds_schema_pattern: "review_{branch}" # Schema dédié dans la même instance RDS staging
replicas: 1 # Toujours 1 replica en review
ttl_hours: 48 # Détruit automatiquement après 48h sans commit
dns_pattern: "{branch}.review.paywithnex.com"
# --- Réseau (VPC) ---
vpc_cidr: "10.0.0.0/16"
subnets:
public_a: "10.0.1.0/24" # eu-west-1a — Load Balancer, NAT
public_b: "10.0.2.0/24" # eu-west-1b — Load Balancer, NAT
private_a: "10.0.10.0/24" # eu-west-1a — Pods EKS
private_b: "10.0.20.0/24" # eu-west-1b — Pods EKS
data_a: "10.0.100.0/24" # eu-west-1a — RDS, Redis
data_b: "10.0.200.0/24" # eu-west-1b — RDS, Redis
# --- Domaines ---
domains:
root: "paywithnex.com" # Adapter au TLD réel
api_staging: "staging.paywithnex.com"
api_prod: "api.paywithnex.com"
admin: "admin.paywithnex.com" # CMMS Dashboard
backoffice: "bo.paywithnex.com" # Backoffice
app: "app.paywithnex.com" # Landing page éventuelle
review_wildcard: "*.review.paywithnex.com" # Envs de review éphémères
# --- Kubernetes (EKS) ---
eks:
k8s_version: "1.29"
node_instance_type: "t3.medium" # 2 vCPU, 4 Go RAM
node_min: 2
node_max: 5
node_desired: 2 # Staging. Prod: 3.
# --- Base de données (RDS PostgreSQL) ---
rds:
engine_version: "16.4"
instance_class_staging: "db.t3.small"
instance_class_prod: "db.t3.medium"
storage: 20 # Go initial
max_storage: 100 # Go auto-scaling
backup_retention: 30 # jours
port: 5432
# --- Redis (ElastiCache) ---
redis:
engine_version: "7.1"
node_type_staging: "cache.t3.micro"
node_type_prod: "cache.t3.small"
port: 6379
# --- Tags AWS (sur TOUTES les ressources) ---
tags:
Project: "nex"
ManagedBy: "terraform"
Team: "engineering"4. SERVICES — CONFIGURATION DE DÉPLOIEMENT
4.1 Services publics (exposés via Ingress)
services_public:
- name: "auth"
path: "/auth" # Route Ingress
port: 3001
replicas_staging: 2
replicas_prod: 3
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: true
needs_postgres: true
env_specific:
- AUTH0_DOMAIN
- AUTH0_CLIENT_ID
- AUTH0_CLIENT_SECRET
- AUTH0_AUDIENCE
- JWT_SECRET
- name: "configuration"
path: "/configuration"
port: 3006
replicas_staging: 1
replicas_prod: 2
memory: "128Mi"
cpu: "125m"
health_path: "/health"
needs_redis: false
needs_postgres: true
env_specific: []
note: "Service pilote CI/CD — zéro dépendance externe"
- name: "orchestrator"
path: "/api"
port: 3004
replicas_staging: 2
replicas_prod: 3
memory: "512Mi"
cpu: "500m"
health_path: "/health"
needs_redis: false
needs_postgres: true
env_specific: []
note: "Dépend de TOUS les services internes. Déployé en dernier."4.2 Services internes (ClusterIP uniquement)
services_internal:
- name: "ledger-wallets"
port: 3002
replicas_staging: 2
replicas_prod: 3
memory: "512Mi"
cpu: "500m"
health_path: "/health"
needs_redis: false
needs_postgres: true
note: "Service critique — gère les soldes. Replicas élevés."
- name: "customer-profiles-kyc"
port: 3003
replicas_staging: 1
replicas_prod: 2
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: false
needs_postgres: true
- name: "notifications"
port: 3005
replicas_staging: 1
replicas_prod: 2
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: false
needs_postgres: true
env_specific:
- FIREBASE_PROJECT_ID
- FIREBASE_SERVER_KEY
- RESEND_API_KEY
- name: "file-service"
port: 3007
replicas_staging: 1
replicas_prod: 2
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: false
needs_postgres: true
env_specific:
- FIREBASE_PROJECT_ID
- FIREBASE_STORAGE_BUCKET
note: "Firebase Storage pour fichiers users, S3 pour backups."
- name: "providers-gateway"
port: 3008
replicas_staging: 1
replicas_prod: 2
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: false
needs_postgres: true
- name: "risk-engine"
port: 3009
replicas_staging: 1
replicas_prod: 2
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: false
needs_postgres: true
- name: "service-catalog"
port: 3010
replicas_staging: 1
replicas_prod: 2
memory: "256Mi"
cpu: "250m"
health_path: "/health"
needs_redis: true
needs_postgres: true
- name: "logs-reporting"
port: 3011
replicas_staging: 1
replicas_prod: 1
memory: "128Mi"
cpu: "125m"
health_path: "/health"
needs_redis: false
needs_postgres: false
note: "Service le plus léger — pas de base de données."4.3 Ordre de déploiement
L'agent doit respecter cet ordre. Chaque étape valide le /health du service avant de passer au suivant.
deploy_order:
# --- Phase A : Service pilote (valide la chaîne CI/CD) ---
pilot: "configuration"
# Pourquoi : zéro dépendance externe, service le plus simple.
# Valide : GitLab CI → build Docker → push registry → deploy K8s → /health OK
# --- Phase B : Généralisation (ordre de dépendance) ---
wave_1: # Services sans dépendance inter-service
- "logs-reporting" # Pas de DB, le plus léger
- "customer-profiles-kyc" # Juste PostgreSQL
- "providers-gateway" # Juste PostgreSQL
- "risk-engine" # Juste PostgreSQL
wave_2: # Services avec dépendances externes
- "auth" # Redis + Auth0
- "service-catalog" # Redis
- "file-service" # Firebase Storage
- "ledger-wallets" # PostgreSQL (critique — seeders)
wave_3: # Services qui dépendent d'autres services
- "notifications" # Firebase FCM + Resend
wave_4: # Orchestrateur — dépend de TOUT
- "orchestrator" # Appelle tous les autres via HTTP5. STACK TECHNIQUE RETENUE
5.1 Vue d'ensemble
| Couche | Provider | Service | Justification |
|---|---|---|---|
| Code + CI/CD | GitLab | GitLab.com (SaaS) + GitLab CI | Pipeline natif, registre Docker inclus |
| Registre Docker | GitLab | Container Registry | Gratuit, intégré au CI, pas de lock-in |
| CDN + WAF + DNS | Cloudflare | Pro | Meilleur WAF/DDoS, edge global |
| Dashboards (Nuxt.js) | Firebase | Hosting | SPA/SSR natif, CDN Google, CLI simple |
| Apps mobiles | Apple / Google | App Store + Play Store | Distribution standard |
| Compute | AWS | EKS (Kubernetes) | K8s standard portable + réseau AWS |
| Base de données | AWS | RDS PostgreSQL | Multi-AZ, backups auto, failover |
| Cache | AWS | ElastiCache Redis | Sessions (auth), cache (service-catalog) |
| Stockage fichiers users | Firebase | Cloud Storage | Utilisé par file-service (déjà intégré) |
| Stockage backups | AWS | S3 + Glacier | Backups DB, archivage réglementaire |
| Auth | Auth0 | Free → Essential | OAuth2/OIDC, MFA, tenant EU |
| Push notifications | Firebase | Cloud Messaging (FCM) | Gratuit, standard iOS/Android |
| Monitoring | Grafana Cloud | Prometheus + Loki + Tempo | Métriques + logs + traces, multi-cloud |
| Erreurs applicatives | Sentry | Team | Crash reporting avec contexte |
| Uptime externe | UptimeRobot | Pro | Monitoring indépendant, rapports régulateur |
| Secrets | Doppler | Team | Multi-cloud, injecte dans K8s |
| Qualité code | SonarCloud | Free | Analyse statique dans le pipeline |
| Email transactionnel | Resend | Free → Pro | Confirmations, alertes |
| SMS/OTP | À définir | — | Twilio ou Africa's Talking |
5.2 Principes directeurs
- Zéro vendor lock-in : chaque brique est remplaçable indépendamment.
- Best of breed : chaque provider sur son point fort.
- AWS pour les données et le réseau : fiabilité critique.
- Firebase pour les fichiers et le hosting : déjà intégré dans le code (file-service, notifications).
- Kubernetes comme abstraction compute : manifests portables vers n'importe quel cluster.
5.3 Ce que l'agent NE doit PAS faire
- Ne pas utiliser AWS CloudFront → Cloudflare gère le CDN
- Ne pas utiliser AWS Route 53 → Cloudflare gère le DNS
- Ne pas utiliser AWS Secrets Manager → Doppler gère les secrets
- Ne pas utiliser AWS CloudWatch comme monitoring principal → Grafana Cloud
- Ne pas utiliser AWS SES → Resend gère les emails
- Ne pas utiliser AWS ECR → GitLab Container Registry
- Ne pas utiliser AWS S3 pour les fichiers users → Firebase Storage (déjà dans file-service)
- Ne pas créer de ressources hors eu-west-1 sauf backups cross-région (eu-west-3)
6. STRUCTURE IaC (dans le monorepo)
L'infrastructure vit dans le dossier infrastructure/ du monorepo nex/. Pas de repo séparé.
nex/infrastructure/ # Tout l'IaC est ici
│
├── docker/
│ ├── Dockerfile.service # UNIQUE — templatisé pour les 11 services
│ ├── .dockerignore # Exclut node_modules, .git, tests, docs
│ ├── postgresql/ # Dev local (existant)
│ ├── redis/ # Dev local (existant)
│ └── node/ # Dev local (existant)
│
├── terraform/
│ ├── bootstrap/ # S3 state + DynamoDB lock (une seule fois)
│ ├── modules/
│ │ ├── vpc/ # VPC, subnets, NAT, IGW, routes, SG
│ │ ├── eks/ # Cluster EKS, node groups, IAM, OIDC
│ │ ├── rds/ # PostgreSQL, subnet groups, params
│ │ ├── redis/ # ElastiCache, subnet groups
│ │ ├── s3/ # Buckets backups, lifecycle, encryption
│ │ └── iam/ # Rôles globaux, policies
│ └── environments/
│ ├── staging/ # main.tf, variables.tf, outputs.tf, backend.tf
│ └── production/ # Même structure, params différents
│
├── kubernetes/
│ ├── base/ # Ressources communes (Kustomize)
│ │ ├── kustomization.yaml
│ │ ├── namespaces.yaml
│ │ ├── network-policies.yaml
│ │ ├── resource-quotas.yaml
│ │ └── ingress/
│ ├── services/ # Un dossier par microservice (11)
│ │ ├── auth/
│ │ ├── ledger-wallets/
│ │ ├── customer-profiles-kyc/
│ │ ├── orchestrator/
│ │ ├── notifications/
│ │ ├── configuration/
│ │ ├── file-service/
│ │ ├── providers-gateway/
│ │ ├── risk-engine/
│ │ ├── service-catalog/
│ │ └── logs-reporting/
│ ├── overlays/
│ │ ├── staging/ # Kustomize overlay staging
│ │ ├── production/ # Kustomize overlay production
│ │ └── review/ # Kustomize overlay review (replicas=1, resources réduits)
│ ├── monitoring/ # Grafana Agent, Prometheus, Loki, dashboards
│ └── jobs/ # CronJobs (backups, cleanup review envs)
│
├── firebase/
│ ├── firebase.json # Config Hosting (CMMS + Backoffice)
│ └── .firebaserc # Alias des projets
│
├── nginx/ # Reverse proxy dev local (existant)
├── prisma/ # Schema introspection (existant)
├── swagger/ # Swagger Hub (existant)
├── railway/ # Ancien hosting (conservé temporairement)
│
├── scripts/ # Existant + nouveaux scripts
│ ├── database/ # Migrations SQL, seeds (existant)
│ ├── setup-kubeconfig.sh # NOUVEAU
│ ├── seed-database.sh # NOUVEAU
│ ├── backup-manual.sh # NOUVEAU
│ ├── rotate-db-password.sh # NOUVEAU
│ ├── rollback.sh # NOUVEAU
│ └── review-env-cleanup.sh # NOUVEAU — supprime les envs review > TTL
│
└── docs/ # Existant + runbook
└── runbook-astreinte.md # NOUVEAULe pipeline CI/CD principal (.gitlab-ci.yml) est à la racine du monorepo nex/, pas dans infrastructure/.
Conventions pour l'agent
- Nommage Terraform :
nex-{env}-{resource}(ex:nex-staging-postgres) - Nommage K8s : namespace
nex-{env}, labelsapp: {service},project: nex,environment: {env} - Nommage K8s review : namespace
nex-review-{branch}, même labels +review: true - Nommage S3 :
nex-{env}-{usage}(ex:nex-staging-backups) - Dockerfile : UN SEUL
infrastructure/docker/Dockerfile.servicetemplatisé via build argSERVICE. Multi-stage build, image finalenode:20-alpine, user non-root, HEALTHCHECK inclus. Contexte Docker = racine du monorepo. Utilisepnpm --filter @nex/{service}...pour installer uniquement le service et ses dépendances workspace. - Build : utiliser SWC (déjà configuré dans les services) pas tsc
- Package manager : pnpm (pas npm, pas yarn)
- Pipeline CI : un seul
.gitlab-ci.ymlà la racine. Turborepo (--filter=...[origin/staging...HEAD]) détecte les services/packages impactés par les changements. Ne build que ce qui a changé. - Secrets : jamais dans Git. Tout via Doppler → External Secrets Operator → K8s Secrets
- Tags : chaque ressource AWS porte les tags définis dans les variables
7. PRÉ-REQUIS
7.1 Comptes à créer avant de démarrer
| Service | Action | Résultat attendu |
|---|---|---|
| AWS | Compte dédié + MFA root + IAM admin + CloudTrail + Budget alerts | aws sts get-caller-identity OK |
| Cloudflare | Compte + domaine paywithnex.com | Nameservers Cloudflare actifs |
| GitLab | Groupe nex + un seul repo monorepo | Repo accessible |
| Auth0 | Tenant EU + apps "Nex API" et "Nex Mobile" | Client ID/Secret dispo |
| Firebase | Projet "nex-app" + Hosting + FCM + Storage | Console accessible |
| Grafana Cloud | Compte Free + endpoints Prometheus/Loki/Tempo | URLs + API key |
| Sentry | Organisation "nex" + un projet par service | DSN récupérés |
| Doppler | Workspace "nex" + envs dev/staging/production | doppler configs OK |
| UptimeRobot | Compte Pro | Dashboard accessible |
| Resend | Compte + domaine vérifié | API key récupérée |
| SonarCloud | Organisation liée au GitLab | Projet visible |
| Apple Developer | Compte ($99/an) | Accès App Store Connect |
| Google Play | Compte ($25 one-time) | Accès Play Console |
7.2 Outils CLI
L'agent vérifie que ces outils sont installés avant de commencer :
aws(>= 2.x) configuré avec profil nex-adminterraform(>= 1.7)kubectl(>= 1.29)helm(>= 3.14)kustomizedockerdopplerfirebase-toolspnpmturbo(Turborepo — orchestration monorepo)jq,yq
8. PLAN DE DÉPLOIEMENT — VUE D'ENSEMBLE
| Fichier | Contenu | Dépend de |
|---|---|---|
| 01_infra_base.md | VPC, EKS, RDS, Redis, S3, DNS, certificats | Ce fichier (00) |
| 02_cicd_et_services.md | GitLab CI + deploy pilote (configuration) + généralisation (11 services) | 01 |
| 03_gateway_cdn_securisation.md | Cloudflare, WAF, network policies, SG, secrets, hardening | 02 |
| 04_monitoring_alertes.md | Grafana, Sentry, UptimeRobot, alertes, dashboards, runbook | 03 |
| 05_deploy_mobile_stores.md | Build React Native, Fastlane, App Store, Play Store, CI/CD mobile | 02 |
Le fichier 05 (mobile) peut être exécuté en parallèle du 03 et 04 — il n'a pas de dépendance sur la sécurisation ni le monitoring.
Ce document est la référence absolue du projet. En cas de conflit entre ce fichier et un autre, ce fichier fait autorité.