Flows transactionnels config-driven
Périmètre : architecture des 7 flows transactionnels portés par l'orchestrator (P2P, MERCHANT_PAY, CASH_IN, CASH_OUT, MA_CASH_OUT, MA_COMM_COLLECT, MASTER_AGENT_CASH_IN). Source de référence : ticket NEX-438 (Epic 1 à 7). Date : 2026-05-12.
1. Objectif
Centraliser la définition de chaque type de transaction dans une FlowDefinition DSL stockée en base (configuration.transaction_flow_schemas) plutôt que de la dispatcher dans le code via des switch (intent.type).
Bénéfices :
- Modifier la séquence d'étapes (ex : insérer un
risk_evaluationavant le récap) ne nécessite aucun déploiement — seulement une UPDATE en DB + cache invalidation. - Les apps mobiles peuvent dérouler le wizard sans coder le séquencement : elles consomment
flowSnapshot.steps[]depuis l'intent. - Le simulateur CMMS rejoue chaque flow à l'identique à partir du même schéma.
2. Anatomie d'un FlowSchema
{
"transactionType": "P2P",
"schemaVersion": "1.0.0",
"isActive": true,
"schema": {
"steps": [
{ "kind": "recipient_input", "channel": "phone", "fields": ["phone"] },
{ "kind": "amount_input", "fields": ["amount"] },
{ "kind": "risk_evaluation" },
{ "kind": "review_screen", "labels": ["recipient", "amount", "fees", "total"] },
{ "kind": "pin_challenge" }
],
"postActions": [
{ "kind": "notify_sender", "channel": "sms" },
{ "kind": "notify_receiver", "channel": "sms" },
{ "kind": "emit_receipt" }
]
}
}2.1 Étapes (steps[])
Les kind actuellement supportés par les renderers (mobile + simulator CMMS) :
kind | Rôle |
|---|---|
recipient_input | Saisie du destinataire (numéro, QR, code marchand, ID agent — pilotée par channel). |
amount_input | Saisie du montant. |
risk_evaluation | Pre-flight risk API-gated (cf. Pre-flight risk). |
review_screen | Récapitulatif sémantique (labels déclaratifs traduits côté UI). |
pin_challenge | Authentification PIN du sender. |
otp_challenge | Code OTP envoyé par SMS / WhatsApp (CASH_OUT uniquement aujourd'hui). |
biometric_challenge | Empreinte / Face ID (placeholder V2). |
Un step inconnu côté client est rendu par StepUpdateRequired qui demande de mettre à jour l'app — pas de fallback silencieux.
2.2 Post-actions (postActions[])
Déclenchées par PostActionsDispatcherService après le passage en succeeded. Chaque action enqueue un job BullMQ dédié (notification SMS, push, reçu PDF, callback marchand…). Le dispatcher est agnostique du type d'intent : il consomme flowSnapshot.postActions[] posé à la création.
3. Snapshot à la création (flowSnapshot)
Quand un intent est créé :
CreateIntentUseCaserésout leFlowSchemaactif pour letransactionTypeviaConfigurationHttpAdapter.- Il copie le
schemacomplet dansintent.flow_snapshot(JSONB). - Toute la suite du cycle de vie (
confirm,cancel, dispatch des post-actions) lit le snapshot, jamais le schéma en base.
Pourquoi snapshot ? Si on modifie le schéma en production pendant qu'un intent est en cours, le client doit pouvoir terminer son flow tel qu'il l'a démarré. Le snapshot fige la définition au moment où le user clique sur "Continuer".
4. Strategy Pattern par IntentType
Deux familles de stratégies orchestrent les variations par type de transaction sans toucher au useCase principal :
4.1 IntentCreationStrategy
Responsabilité : résoudre les comptes (sourceAccountId, destAccountId) à partir du payload de création.
| IntentType | Strategy |
|---|---|
| TRANSFER (P2P) | TransferCreationStrategy |
| MERCHANT_PAYMENT | MerchantPaymentCreationStrategy |
| CASH_IN | CashInCreationStrategy |
| CASH_OUT | CashOutCreationStrategy |
| MASTER_AGENT_CASH_IN / MA_CASH_OUT / MA_COMM_COLLECT | MasterAgentCreationStrategy (partagée) |
4.2 IntentConfirmationStrategy
Responsabilité : calculer les mouvements ledger au confirm (debits/credits, commission agent, frais). Une instance par IntentType (8 stratégies).
Toutes implémentent resolveAccounts(intent) — méthode également invoquée par PreflightRiskUseCase pour résoudre les comptes avant le pipeline risque (cf. Pre-flight risk).
5. Cycle de vie d'un intent
6. Administration & observabilité
- Page admin CMMS :
Configurations > Flows(/configurations/flows) — liste les 7 schémas avec toggleis_active, visualiseur de pipeline, JSON brut en option. - Simulateur :
Sandbox > Flow(/sandbox/flow) — rejoue n'importe quel flow actif avec impersonation du sender. Sert de référence pour valider une modification de schéma avant rollout. Voir Simulateur Flow (CMMS). - Onglet Échecs :
/transactions?tab=failed— liste les intentsfailed/pending_reviewavec motif humanisé (cf. Pre-flight risk).
7. Limites connues
schemaVersionest informatif aujourd'hui — il n'existe pas encore de mécanisme de migration multi-versions actives. Une seule versionis_active=truepartransaction_type.- Les renderers mobiles consomment le snapshot mais n'utilisent pas encore
flowSnapshot.steps[].kindVersionpour gérer la rétro-compat fine ; en cas d'écart,StepUpdateRequiredest affiché. - Les post-actions sont enqueuées en best-effort BullMQ — pas de transaction atomique avec la transition d'état (acceptable : un SMS reçu en double vaut mieux qu'un SMS perdu).
8. Références
- Endpoint admin :
GET /v1/config/transaction-flow-schemas(orchestrator → configuration:3006) - Table :
configuration.transaction_flow_schemas - Code de référence orchestrator :
services/orchestrator/src/application/use-cases/intents/ - Pre-flight risk : /services/risk-engine/preflight