Contexte Architecte DYNORS — À lire en premier
Pour Claude AI et tout architecte DYNORS.
Ce document est la porte d'entrée obligatoire avant toute proposition de spec, d'architecture ou de développement. Toute nouvelle application doit s'intégrer dans cet écosystème.
Qui est DYNORS ?
DYNORS est une ESN (Entreprise de Services Numériques) basée à Dakar, Sénégal. Elle conçoit et opère :
- Un socle technique partagé (
dynors-core,dynors-extensions) utilisé par toutes les apps - Des services centraux (FISCAL pour la facturation DGI, DYNORS BOOKS pour la comptabilité SYSCOHADA)
- Un gateway unique (SLY — SelebeYone) pour toutes les communications inter-applications
- Des produits SaaS métier (SuperGest, TRACIUM, Mediconnect, DAWALALE, YOBALÉ, BOOKS)
- Des outils internes (RAGNAR ERP, TAKKU générateur, HEISENBERG BI)
- Une plateforme DevOps (SIRRAT — le pont du jugement)
Modèle : multi-tenant. Chaque client a son tenantCode, propagé depuis le JWT jusque dans la base de données.
Les principes architecturaux immuables
Avant d'écrire une ligne de code ou une spec, ces principes s'appliquent sans exception :
1. Toute communication inter-app passe par SLY
App A → InterAppCallService → SLY (sly.dynors.com) → App B
Jamais d'appel direct HTTP entre deux apps DYNORS. Jamais de RestTemplate ou WebClient instancié manuellement pour appeler FISCAL, BOOKS, notify, etc.
2. Le tenant vient toujours du JWT validé
JWT (validé par dynors-security) → TenantContextFilter → TenantContext → DB + inter-app headers
Jamais depuis les headers bruts, le body, ou les query params.
3. Architecture hexagonale obligatoire
domain/ (métier pur) → application/ (use cases) → infrastructure/ (REST, DB, clients inter-app)
4. Tokens en cookies HttpOnly uniquement
Jamais de localStorage ni sessionStorage pour les JWT en production.
5. Tout backend recevant des appels inter-app vérifie la signature SLY
Via SlyTransitFilter (fourni par dynors-commons). Empêche le contournement de SLY.
La carte de l'écosystème
┌─────────────────────────────────────────────────────────────────────────────┐
│ ÉCOSYSTÈME DYNORS │
├──────────────────────────────┬──────────────────────────────────────────────┤
│ SOCLE (dynors-core) │ EXTENSIONS (dynors-extensions) │
│ ───────────────── │ ──────────────────────────── │
│ dynors-commons │ notify pdf invoicing │
│ dynors-security │ billing hr payroll │
│ dynors-db │ webhooks api-client logging │
│ dynors-events │ │
│ dynors-interapp-client │ │
├──────────────────────────────┴──────────────────────────────────────────────┤
│ GATEWAY : SLY (SelebeYone) │
│ sly.dynors.com — point d'entrée unique inter-app │
├────────────────────────────────────────────────────────────────────────────┤
│ SERVICES CENTRAUX │ APPS INTERNES │
│ ───────────────── │ ───────────────── │
│ FISCAL (facturation DGI) │ RAGNAR (ERP/CRM) │
│ DYNORS BOOKS (compta) │ TAKKU (générateur projets) │
│ │ HEISENBERG (BI) │
├────────────────────────────────────────────────────────────────────────────┤
│ PROJETS SATELLITES (dynors-projects/) │
│ ───────────────────────────────────── │
│ Mediconnect SN SuperGest TRACIUM DAWALALE YOBALÉ BOOKS │
├────────────────────────────────────────────────────────────────────────────┤
│ PLATEFORME DEVOPS │
│ ────────────────── │
│ SIRRAT (quality gates, PV recette) + GitLab CI + Container/Package Registry│
└────────────────────────────────────────────────────────────────────────────┘
Stack technique standard
| Couche | Technologie | Version cible |
|---|---|---|
| Backend | Java + Spring Boot | Java 21, Spring Boot 3.x |
| Build | Gradle | 8.5+ |
| Frontend web | Angular | 17 à 20 |
| Mobile | React Native ou Flutter | selon projet |
| Base de données | PostgreSQL | 15+ |
| Cache | Redis | 7+ |
| Message bus | dynors-events (Kafka-ready) | — |
| Architecture | Hexagonale (domain / application / infrastructure) | obligatoire |
| Déploiement | Docker + docker-compose → K8s si fort trafic | GitLab CI |
Catalogue des applications
Services centraux
=== "FISCAL"
- **Rôle** : Facturation conforme DGI Sénégal. Certification, numérotation, PDF, export FEC.
- **Code SLY** : `source-app: fiscal`
- **Route SLY** : `/fiscal/**`
- **Appelé par** : SuperGest, Mediconnect, TRACIUM, RAGNAR, TAKKU, DAWALALE, YOBALÉ, BOOKS
- **Appelle** : DGI (externe), notify
=== "DYNORS BOOKS"
- **Rôle** : Comptabilité SYSCOHADA, paie, déclarations fiscales.
- **Code SLY** : `source-app: books`
- **Route SLY** : `/books/**`
- **Appelé par** : TRACIUM, FISCAL (événements)
Apps internes
=== "RAGNAR"
- **Rôle** : ERP/CRM interne DYNORS (clients, projets, devis, contrats).
- **Appelle** : FISCAL via SLY, notify via SLY
=== "TAKKU"
- **Rôle** : Générateur de projets DYNORS. Configure et scaffolde les apps selon l'écosystème.
- **Spécial** : interroge le GitLab Package Registry en temps réel pour proposer les versions disponibles des modules.
=== "HEISENBERG"
- **Rôle** : BI / analytique sur les données multi-tenant.
Projets satellites
=== "Mediconnect SN"
- **Domaine** : Santé (RDV, dossier patient, ordonnances, pharmacie).
- **Intégrations** : FISCAL (paiements soins), notify (rappels RDV), DAWALALE.
- **Specs** : `docs/projet-nouveau/mediconnect/` (source de vérité v4.x)
=== "SuperGest"
- **Domaine** : POS, stock, back-office, comptabilité point de vente.
- **Intégrations** : FISCAL (certifications), TRACIUM (traçabilité), notify.
- **Specs** : `docs/projet-nouveau/SuperGEST/`
=== "TRACIUM"
- **Domaine** : Traçabilité supply chain (certificats, portails fournisseur/acheteur/régulateur).
- **Intégrations** : FISCAL, BOOKS, notify.
- **Specs** : `docs/projet-nouveau/Tracium/`
=== "DAWALALE"
- **Domaine** : Auto-école en ligne (leçons, examens, paiements).
- **Intégrations** : FISCAL.
=== "YOBALÉ"
- **Domaine** : Livraison dernier km (coursiers, clients, géolocalisation).
- **Intégrations** : FISCAL, notify.
Modules disponibles et versions
Voir la page complète : Versions et dépendances
BOM actuel : dynors-core-bom:1.0.2
| Module | Inclus dans BOM | Nouveauté |
|---|---|---|
| dynors-commons | ✅ | SlyTransitFilter, SlyTransitValidator, InterAppCallService |
| dynors-security | ✅ | JWT, TenantContextFilter, RBAC |
| dynors-db | ✅ | Multi-tenant PostgreSQL |
| dynors-events | ✅ | Event bus publisher/subscriber |
| dynors-interapp-client | ✅ | Client HTTP inter-app → SLY |
SLY en détail — règles de routage et sécurité
Voir : Gateway SelebeYone et Routage inter-app
Headers propagés automatiquement par InterAppCallService
| Header | Source |
|---|---|
X-Source-App |
dynors.interapp.source-app (config) |
X-Tenant-Id |
TenantContext.get() |
X-Request-Id |
UUID généré par InterAppCallService |
X-Sly-Timestamp |
Ajouté par SLY (signature HMAC) |
X-Sly-Signature |
Ajouté par SLY (HMAC-SHA256 du transit) |
Cycle de déploiement — SIRRAT (As-Sirât)
Voir : SIRRAT concept et Pipeline complet
git push
↓
CI : build → test → scan → docker image + maven JAR → dépôt (GitLab Registry)
↓
SIRRAT reçoit les résultats CI
↓
RMOA DYNORS (QA interne) ──[🚪 Porte #1]──► RMOA CLIENT (validation) ──[🚪 Porte #2+3 + PV signé]──► PROD
Checklist — toute nouvelle application
Avant toute spec ou implémentation :
- [ ]
source-appdéfini (code stable, minuscules, ex.yobale,supergest) - [ ] Modules core sélectionnés (au minimum
commons+security+db+interapp-client) - [ ] Extensions sélectionnées (
notifysi notifications,invoicingsi facturation…) - [ ] Clients inter-app créés (
FiscalClient,NotifyClient…) encapsulantInterAppCallService - [ ]
SlyTransitFilterenregistré si l'app reçoit des appels inter-app - [ ]
TenantContextalimenté par filtre JWT, jamais depuis headers directs - [ ] Routes SLY ajoutées dans
dynors-platform/selebeyone/application.yml - [ ]
sirrat.config.ymlcréé à la racine du projet - [ ]
.gitlab-ci.ymlavec stages build/test/scan/deploy par environnement - [ ] Variables CI/CD :
SLY_FORWARD_SECRET(protégée + masquée),SLY_BASE_URL, secrets DB/JWT - [ ] Documentation : page dans
dynors-docs/docs/04-bibliotheque-projets/
Anti-patterns — à ne jamais faire
// ❌ Appel direct à une app DYNORS
RestTemplate rt = new RestTemplate();
rt.postForObject("https://fiscal-service:8080/api/certify", payload, Response.class);
// ✅ Correct
fiscalClient.certify(tenant, payload); // via InterAppCallService → SLY
// ❌ Tenant depuis les headers
String tenant = request.getHeader("X-Tenant-Id");
// ✅ Correct
String tenant = TenantContext.get();
// ❌ JWT en localStorage (frontend)
localStorage.setItem("token", jwt);
// ✅ Correct
// Cookie HttpOnly posé par le backend → intercepteur Angular lit depuis le cookie
// ❌ Parsing JWT dans un controller
Claims claims = Jwts.parser().parseClaimsJws(token);
// ✅ Correct — dynors-security s'en charge dans les filtres
Liens rapides
| Besoin | Où |
|---|---|
| Comprendre le flux inter-app | routage-interapp.md |
| Configurer SLY pour une nouvelle app | gateway-selebeyone.md |
| Connaître les versions disponibles | versions-et-dependances.md |
| Mettre en place le pipeline CI/CD | environnements-ci-cd.md |
| Spec Mediconnect | docs/projet-nouveau/mediconnect/MEDICONNECT_Prototype_UI_v4.2.html |
| Spec SuperGest | docs/projet-nouveau/SuperGEST/supergest_addendum_v1_1.docx |
| Spec TRACIUM | docs/projet-nouveau/Tracium/TRACIUM_Ecosystem_Integration_v2.docx |
| Spec BOOKS | docs/projet-nouveau/Books/dynors_books_spec_v2.docx |