Décisions d'architecture (ADRs)
Version : 1.0 Date : 22 avril 2026 Auteur : Chaouki Barkia
Ce document regroupe les 6 décisions d’architecture initiales à valider par l’équipe technique au démarrage du projet. Chaque ADR suit un format standard (statut, contexte, décision, conséquences, alternatives). Toute modification ultérieure doit faire l’objet d’un nouvel ADR daté, conservant la traçabilité.
Sommaire
Section intitulée « Sommaire »- ADR-001 — Moteur de workflow : Temporal.io
- ADR-002 — Multi-tenant : shared schema + Row Level Security PostgreSQL
- ADR-003 — OCR : build hybride (moteur interne + fallback commercial)
- ADR-004 — Moteur de règles métier : DSL Kotlin + OPA pour politiques
- ADR-005 — Stockage des documents : MinIO / S3 compatible + couche d’abstraction
- ADR-006 — Gestion des listes AML : pipeline incrémental avec support air-gap
- ADR-007 — Form Designer : scope MVP (no-code, configurable par tenant)
- ADR-008 — Génération PDF : Apache PDFBox + Gotenberg
- ADR-009 — i18n : ICU MessageFormat + CSS logique + RTL arabe
- ADR-010 — Distribution SDKs : NPM + Maven Central + Swift PM
- ADR-011 — E-signature : DocuSign + Yousign FR + TunTrust/ANCE (Tunisie) + module natif SES + option QES
- ADR-012 — Zero-downtime upgrades on-prem + Oracle + air-gap
ADR-001 — Moteur de workflow : Temporal.io
Section intitulée « ADR-001 — Moteur de workflow : Temporal.io »Statut : Proposé — à valider par l’équipe technique au kickoff Date : 2026-04-22 Décideurs : Tech Lead, Architecte
Contexte
Section intitulée « Contexte »La plateforme VitaKYC orchestre des workflows longs, durables, multi-étapes, avec retry et interventions humaines :
- Un dossier KYC peut rester ouvert plusieurs jours (capture document, attente de revue agent, suites éventuelles).
- Le screening AML ongoing tourne en continu pendant toute la relation client.
- La revalidation FATCA (formulaires W-8) a un horizon de 3 ans.
- Les corrections FATCA 3+1 doivent attendre une fenêtre DGI → IRS avant d’envoyer la réémission (contrainte temporelle stricte).
Un moteur maison serait long à durcir (retry, idempotence, historique, signals). Les candidats sérieux sont Temporal.io, Camunda 8 (Zeebe), et dans une moindre mesure AWS Step Functions.
Décision
Section intitulée « Décision »Adopter Temporal.io (self-hosted) comme moteur de workflow pour tous les traitements long-running.
Justification
Section intitulée « Justification »- Modèle de programmation : on écrit des workflows en Kotlin/Java comme du code impératif avec garanties de durabilité (reprise après crash, retry automatique, signals). C’est plus proche du code métier que BPMN.
- Fiabilité : Temporal est éprouvé chez Uber, Stripe, Coinbase ; activités idempotentes natives, exactly-once execution.
- Support long-running : sommeils de plusieurs mois, voire années, gérés nativement (
workflow.sleep(Duration.ofDays(365*3))— idéal pour revalidation W-8). - Observabilité : UI Temporal = debug puissant (history d’un workflow, état actuel, replay).
- Communauté et écosystème : Kotlin SDK mature, métriques Prometheus natives, déploiement Kubernetes documenté.
- Licence : MIT — utilisable on-prem sans surcoût.
Conséquences
Section intitulée « Conséquences »Positives
- Réduction du code de plomberie (retry, état, persistance) de ~30-40 %.
- Chaînage FATCA 1/3 facile à implémenter comme un workflow :
fatca3puisworkflow.sleep(untilDgiIrsWindowClosed)puisfatca1. - Tests reproductibles (replay d’historique).
Négatives
- Courbe d’apprentissage : les ingénieurs doivent comprendre les determinism constraints (code workflow ≠ code activity).
- Infrastructure additionnelle : cluster Temporal (historyservice + matchingservice + frontend + workers) à opérer en on-prem, ~3 pods minimum.
- Dépendance PostgreSQL ou Cassandra pour le store Temporal.
Risques & mitigations
- Risque : verrouillage autour de Temporal. Mitigation : garder la logique métier dans des services découplés, les workflows étant des orchestrateurs minces. On peut porter vers Camunda 8 au prix d’un refactoring contenu.
- Risque : montée en charge imprévue de l’historique Temporal. Mitigation : retention configurable par namespace, archivage S3.
Alternatives considérées
Section intitulée « Alternatives considérées »| Option | Pourquoi non retenue |
|---|---|
| Camunda 8 (Zeebe) | Excellent produit, mais modèle BPMN moins fluide pour du code métier riche ; licence freemium avec limites de volume. |
| AWS Step Functions | Cloud-locked, impossible en on-prem — contraire à la promesse hybride de VitaKYC. |
| Moteur interne (ad hoc) | Risque élevé de réinventer la roue imparfaitement ; 6-12 mois perdus avant production robuste. |
| Airflow / Dagster | Orientés data pipelines, pas orchestration métier long-running avec signals. |
Références
Section intitulée « Références »- temporal.io
- VitaKYC Architecture Technique §4.4, §7.4
ADR-002 — Multi-tenant : shared schema + Row Level Security PostgreSQL
Section intitulée « ADR-002 — Multi-tenant : shared schema + Row Level Security PostgreSQL »Statut : Proposé Date : 2026-04-22
Contexte
Section intitulée « Contexte »VitaKYC doit supporter trois modes de déploiement :
- SaaS multi-tenant partagé — plusieurs clients sur la même infrastructure.
- SaaS dédié — infra dédiée par client (enterprise).
- On-premise — single-tenant par construction.
La décision porte surtout sur le mode 1 : comment isoler les données de plusieurs tenants sur la même base de données tout en permettant l’exploitation opérationnelle (backups, migrations, analytics cross-tenant) ?
Les trois schémas d’isolation courants sont :
- Database per tenant — isolation maximale, coût opérationnel exponentiel.
- Schema per tenant — bon compromis mais multiplication des objets, migrations complexes.
- Shared schema avec discrimination par
tenant_id— simple à opérer, risque de fuite si erreur applicative.
Décision
Section intitulée « Décision »Adopter shared schema avec tenant_id sur chaque table métier, renforcé par Row Level Security (RLS) PostgreSQL activée par défaut, et chiffrement des données sensibles avec clé par tenant (HashiCorp Vault Transit).
Justification
Section intitulée « Justification »- Opérabilité : une seule base, une seule migration, une seule stratégie de backup. Critique pour une équipe lean au démarrage.
- RLS PostgreSQL : garantit en profondeur que même une requête SQL mal formée ne peut pas fuir entre tenants (ceinture + bretelles vs sécurité applicative seule).
- Chiffrement par tenant : un compromis d’une base ne révèle pas les PII en clair ; rotation possible par tenant.
- Coût : ~10× moins cher que database-per-tenant à volume équivalent.
- Dégradation simple vers SaaS dédié et on-prem : même code, infrastructure différente.
Implémentation
Section intitulée « Implémentation »-- Chaque table métier porte tenant_idCREATE TABLE kyc_case ( case_id UUID PRIMARY KEY, tenant_id UUID NOT NULL, -- ...autres colonnes);
-- RLS activéeALTER TABLE kyc_case ENABLE ROW LEVEL SECURITY;ALTER TABLE kyc_case FORCE ROW LEVEL SECURITY;
-- Policy : le tenant est récupéré d'une variable de session positionnée-- par l'application à l'ouverture de connexionCREATE POLICY tenant_isolation ON kyc_case USING (tenant_id = current_setting('app.current_tenant')::uuid);
-- L'app fait :-- SET app.current_tenant = '<uuid>';Conséquences
Section intitulée « Conséquences »Positives
- Simplicité opérationnelle maximale.
- Possibilité d’analytics cross-tenant (anonymisés) pour l’équipe VitaKYC (benchmarks, product analytics).
Négatives
- Obligation absolue de positionner la session
app.current_tenantavant toute requête — middleware dédié requis dans Spring Boot (filtre JPA). - Test automatisé obligatoire à chaque release qui vérifie qu’un tenant ne voit pas les données d’un autre (§14.3 du doc archi).
- PostgreSQL-bound (RLS n’existe pas de la même façon en MySQL) — acceptable vu que PostgreSQL est le choix principal.
Alternatives considérées
Section intitulée « Alternatives considérées »| Option | Pourquoi non retenue |
|---|---|
| Database per tenant | Coût opérationnel trop élevé au MVP ; retardera le time-to-market. |
| Schema per tenant | Migrations multipliées par N tenants ; complexité inutile vu que RLS donne 95 % du bénéfice. |
| Isolation uniquement applicative (sans RLS) | Insuffisant pour un produit compliance : une seule requête WHERE oubliée = fuite. |
Exception prévue
Section intitulée « Exception prévue »Le plan Regulated On-Prem et le plan SaaS dédié déploient une base par tenant — même code, topologie différente. Le tenant_id reste présent mais contient une seule valeur.
ADR-003 — OCR : build hybride (moteur interne + fallback commercial)
Section intitulée « ADR-003 — OCR : build hybride (moteur interne + fallback commercial) »Statut : Proposé Date : 2026-04-22
Contexte
Section intitulée « Contexte »L’OCR est central pour le KYC (passeports, CNI, justificatifs domicile, extraits RNE). Les contraintes sont :
- Multilinguisme critique : français, anglais, arabe (impératif pour MENA), chiffres hindi (documents égyptiens).
- Précision : ≥ 98 % sur documents nominaux sinon drop-off client.
- Coût unitaire : OCR représente le poste 1 du coût par vérification (~0,05 à 0,50 $ selon fournisseur).
- Portabilité on-prem : certains clients interdisent l’appel à un SaaS externe.
Options : 100 % fournisseur commercial (Google Vision, AWS Textract, Mistral OCR, Veryfi, Regula), 100 % moteur interne (Tesseract + modèles custom ONNX), ou hybride.
Décision
Section intitulée « Décision »Stratégie hybride avec routage :
- Moteur interne par défaut : Tesseract 5 + modèles de détection de champ fine-tunés sur documents MENA (pipeline PyTorch → export ONNX) ; déployé dans
ocr-svc. - Fallback commercial configurable par tenant : si le score de confiance du moteur interne < seuil, bascule sur un fournisseur commercial (ordre de préférence configurable).
- Mode air-gap : en on-prem sans accès Internet, seul le moteur interne est actif — les clients sont informés du trade-off (précision un peu inférieure sur documents rares).
Justification
Section intitulée « Justification »- Coût marginal maîtrisé : sur le gros des documents courants (CNI TN/FR/MA, passeports ICAO), le moteur interne suffit → 0 coût marginal externe.
- Qualité sur le long tail : les fournisseurs commerciaux gardent l’avantage sur documents rares ou dégradés ; le fallback permet de ne pas rejeter inutilement.
- Flexibilité commerciale : les clients enterprise peuvent négocier avec leur propre fournisseur data et le brancher ; VitaKYC reste neutre.
- Roadmap d’internalisation : au fur et à mesure que le dataset d’entraînement grandit, le moteur interne dépasse le fallback et le fallback devient exceptionnel.
Architecture
Section intitulée « Architecture » ┌────────────┐doc ────▶│ ocr-svc │ │ │ │ 1. route │ └─────┬──────┘ │ ┌───────┴────────┐ ▼ ▼ ┌───────────┐ ┌──────────────┐ │ moteur │ │ adapter │ │ interne │ │ commercial │ │ (ONNX) │ │ (Google, │ │ │ │ Regula, …) │ └────┬──────┘ └──────┬───────┘ │ score < seuil │ └────────┬─────────┘ ▼ ┌────────────┐ │ résultat │ │ consolidé │ └────────────┘Conséquences
Section intitulée « Conséquences »Positives
- Coût marginal réduit de 40-60 % vs 100 % commercial.
- Compatibilité air-gap.
- Négociation commerciale facilitée (pas de surcoût visible pour le client).
Négatives
- Deux systèmes à maintenir (interne + adapters commerciaux).
- Nécessite un data engineer / ML engineer dès M+6 pour entraîner et mesurer.
- Courbe d’apprentissage sur MLOps (monitoring de drift, retrain).
Alternatives considérées
Section intitulée « Alternatives considérées »- 100 % commercial : simple mais coût marginal élevé et incompatible air-gap.
- 100 % interne : impossible à la précision requise au MVP sans dataset massif.
- Build custom à partir de zéro (CNN + CTC maison) : hors budget et hors délai au MVP.
Métriques cibles
Section intitulée « Métriques cibles »- Moteur interne : précision character-level ≥ 97 % sur passeports FR/TN/EG au MVP ; ≥ 99 % à V2.
- Taux de fallback vers commercial ≤ 15 % au MVP, ≤ 5 % à V2.
ADR-004 — Moteur de règles métier : DSL Kotlin + OPA pour politiques
Section intitulée « ADR-004 — Moteur de règles métier : DSL Kotlin + OPA pour politiques »Statut : Proposé Date : 2026-04-22
Contexte
Section intitulée « Contexte »VitaKYC a deux natures de règles à gérer :
- Règles métier riches — décisions KYC, détection d’indicia FATCA, calcul de risque AML composite. Elles changent souvent, dépendent de données métier, et doivent être versionnées avec des tests unitaires.
- Politiques d’accès / compliance — qui peut voir quoi, quel tenant peut exporter vers quelle résidence de données. Elles changent rarement mais doivent être auditables.
Options évaluées : Drools, OPA (Open Policy Agent), DMN via Camunda, DSL Kotlin maison, règles en base avec éditeur UI.
Décision
Section intitulée « Décision »Approche double :
- Règles métier → DSL Kotlin (type-safe, versionné dans le monorepo, testé) + interface admin pour les paramètres numériques et listes (seuils, pondérations, listes de pays) stockés en base.
- Politiques d’accès / compliance → Open Policy Agent (OPA) avec policies Rego, déployé en sidecar
opasur les services.
Justification
Section intitulée « Justification »Pour le DSL Kotlin :
- Réutilisation immédiate des compétences équipe.
- Tests unitaires triviaux (JUnit + Kotest).
- Pas de dépendance runtime supplémentaire.
- Refactoring sûr via IDE.
Pour OPA :
- Standard de facto pour policy-as-code en Kubernetes / microservices.
- Découplage fort : les politiques peuvent être modifiées sans redéploiement de service.
- Bundles signés pour distribution sécurisée des policies (air-gap friendly).
Exemple — règle métier KYC (Kotlin)
Section intitulée « Exemple — règle métier KYC (Kotlin) »object KycDecisionRules { fun evaluate(ctx: KycContext): Decision { val score = ctx.aggregateRiskScore() return when { score >= ctx.tenantConfig.autoApproveThreshold -> Decision.AutoApprove(score) score >= ctx.tenantConfig.manualReviewThreshold -> Decision.ManualReview(score, reasons = ctx.flaggedReasons) ctx.fatcaIndiciaCount >= 2 && ctx.usPersonSelfCertified.not() -> Decision.ManualReview(score, reasons = listOf("FATCA_INDICIA_UNCONFIRMED")) ctx.amlHitsHigh.isNotEmpty() -> Decision.Escalate(score, reasons = ctx.amlHitsHigh.map { it.key }) else -> Decision.Reject(score, reasons = listOf("INSUFFICIENT_VERIFICATION")) } }}Exemple — policy OPA (Rego)
Section intitulée « Exemple — policy OPA (Rego) »package vitakyc.export
# Un agent ne peut exporter les données d'un dossier que si :# - il appartient au tenant du dossier# - il a le rôle supervisor ou admin# - la résidence des données du tenant autorise la région cibleallow { input.user.tenant_id == input.resource.tenant_id input.user.roles[_] == role role == "supervisor" data.tenants[input.user.tenant_id].residency_regions[_] == input.export.target_region}Conséquences
Section intitulée « Conséquences »Positives
- Règles métier : versionnées, testées, rapide à écrire.
- Politiques : modifiables indépendamment du code, auditables, cross-language.
Négatives
- Les équipes doivent apprendre Rego (OPA) — courbe courte mais réelle.
- Éviter la tentation de tout migrer vers OPA — garder la séparation nette.
Alternatives considérées
Section intitulée « Alternatives considérées »- Drools : puissant mais lourd, syntaxe DRL vieillissante, outillage daté.
- DMN via Camunda : bon pour décisions tabulaires simples, surdimensionné pour règles riches.
- Règles en base avec éditeur UI : attrayant mais typage perdu, testabilité faible ; reporté à V2 comme extension OPA + UI low-code.
ADR-005 — Stockage des documents : MinIO / S3 compatible + couche d’abstraction
Section intitulée « ADR-005 — Stockage des documents : MinIO / S3 compatible + couche d’abstraction »Statut : Proposé Date : 2026-04-22
Contexte
Section intitulée « Contexte »Chaque dossier KYC génère des documents : scans recto/verso, selfies, vidéos VideoKYC, PDFs signés W-8/W-9, fichiers XML FATCA, exports de rapports. Le stockage doit être :
- Chiffré au repos (AES-256) avec clé par tenant.
- Immutable après finalisation (legal hold, rétention 10 ans).
- Portable (SaaS AWS/GCP, on-prem datacenter).
- Signable pour URLs temporaires (téléchargement client / agent).
Décision
Section intitulée « Décision »API S3 comme contrat unique :
- SaaS : AWS S3 (Frankfurt) ou GCS selon région.
- On-prem : MinIO déployé dans le cluster Kubernetes (4 nœuds minimum en erasure coding).
- Un service dédié
doc-storeencapsule l’accès : le code métier n’appelle jamais directement l’API S3.
Justification
Section intitulée « Justification »- API S3 = standard universel : SDK Kotlin/Java (AWS SDK v2), Python (boto3) — fonctionne identiquement sur AWS, GCS (via interopérabilité), MinIO.
- MinIO : compatibilité S3 à 99 %, performance élevée, chiffrement SSE-KMS natif intégrable avec Vault.
- Couche d’abstraction
doc-store: permet d’ajouter des politiques transverses (legal hold, retention, anonymisation, watermarking) sans disperser le code.
Organisation des buckets
Section intitulée « Organisation des buckets »Pattern : vitakyc-{env}-{region}-{purpose}Exemples : vitakyc-prod-eu-docs # documents clients chiffrés vitakyc-prod-eu-exports # exports générés (FATCA XML, rapports) vitakyc-prod-eu-audit-archive # archives immutables (WORM)
Préfixe objet : {tenant_id}/{kind}/{YYYY}/{MM}/{case_id}/{file_id}Exemple : c9e1.../kyc-documents/2026/04/abc123.../passport-recto.jpg.encConsequences
Section intitulée « Consequences »Positives
- Portabilité totale SaaS ↔ on-prem.
- Un seul SDK à maintenir.
- Audit unifié des accès documents.
Négatives
- Coût MinIO on-prem : opération cluster 4-node minimum pour HA.
- Surcharge CPU pour chiffrement client-side quand imposé.
Alternatives considérées
Section intitulée « Alternatives considérées »- NFS / filesystem : pas de chiffrement granulaire, scalabilité limitée.
- Azure Blob : API différente, forcerait du code conditionnel.
- Ceph Object Gateway : puissant mais opérer Ceph est un métier à part ; MinIO est plus léger.
ADR-006 — Gestion des listes AML : pipeline incrémental avec support air-gap
Section intitulée « ADR-006 — Gestion des listes AML : pipeline incrémental avec support air-gap »Statut : Proposé Date : 2026-04-22
Contexte
Section intitulée « Contexte »Le screening AML dépend de listes mises à jour en permanence :
- Sanctions : OFAC SDN, OFAC Consolidated, UN 1267, EU consolidated, HMT UK, listes nationales (BCT Tunisie, SEPBLAC, CB UAE).
- PEP : fournisseurs tiers (Dow Jones, LSEG World-Check, ComplyAdvantage data).
- Adverse media : flux NLP continu.
En mode SaaS, on peut poller régulièrement les flux officiels et les providers. En mode on-prem air-gap, les clients interdisent les connexions sortantes — les listes doivent être distribuées sous forme de fichiers signés.
Décision
Section intitulée « Décision »Pipeline en quatre étapes centralisé côté VitaKYC, puis distribution :
- Ingestion : poller les sources officielles (OFAC, UN, EU…) et les APIs des providers ; normaliser vers un format commun
VKL v1(VitaKYC Lists). - Normalisation : canonicalisation des noms (arabe → latin + unicode normalization), extraction des identifiants (dates de naissance, nationalité, AKA), scoring de confiance.
- Publication : trois canaux
- SaaS : mise à jour directe dans OpenSearch (index miroir par source).
- On-prem avec Internet : pull quotidien depuis un endpoint sécurisé
lists.vitakyc.io(bundle signé). - On-prem air-gap : export mensuel ou hebdomadaire sur support physique (USB chiffré) ou transfert fichier sFTP one-way, avec vérification de signature côté client.
- Consommation :
aml-svcinterroge OpenSearch ; le pipeline de matching est identique quels que soient le mode de distribution.
Format VKL v1 (extrait)
Section intitulée « Format VKL v1 (extrait) »{ "vkl_version": 1, "source": "OFAC_SDN", "snapshot_id": "ofac-sdn-2026-04-22T06:00:00Z", "published_at": "2026-04-22T06:15:00Z", "signature": "ed25519:MEUCIQ...", "records": [ { "id": "SDN-12345", "type": "individual", "names": ["John Doe","ДЖОН ДОУ","جون دو"], "dob": ["1965-03-12"], "nationalities": ["IR"], "aka": ["Johnny Doe"], "addresses": [{"country":"IR","city":"Tehran"}], "programs": ["IRAN"], "sanctions_since": "2015-06-10", "last_modified": "2024-11-08" } ]}Consequences
Section intitulée « Consequences »Positives
- Matching identique entre modes de déploiement.
- Les clients air-gap ne sont pas désavantagés fonctionnellement, juste en fraîcheur.
- Les providers commerciaux peuvent être substitués sans toucher au code métier.
Négatives
- Responsabilité éditoriale VitaKYC : maintenir le pipeline, monitorer la qualité des sources.
- Risque juridique : toute erreur de liste peut avoir des conséquences pour les clients. → Clause contractuelle de best-effort + mention de responsabilité du client sur la décision finale.
Questions ouvertes
Section intitulée « Questions ouvertes »- Sourcing initial des données PEP : build interne impossible au MVP (coût d’un dataset mondial ~200-500 k€/an) → recommandation : partenariat avec ComplyAdvantage ou Dow Jones en revente au lancement, build progressif ensuite.
- Fréquence d’actualisation air-gap : négociée contractuellement (hebdomadaire = standard, quotidien = premium).
Processus de révision
Section intitulée « Processus de révision »- Tout ADR doit être revu par le tech lead + 1 ingénieur senior minimum avant passage au statut Accepté.
- Un ADR Accepté peut être Superseded par un nouvel ADR (nouveau numéro) qui référence explicitement l’ancien.
- Aucun ADR ne doit être supprimé — la traçabilité des décisions est un livrable produit.
ADR-007 — Form Designer : scope MVP (no-code, configurable par tenant)
Section intitulée « ADR-007 — Form Designer : scope MVP (no-code, configurable par tenant) »Statut : Accepté Date : 2026-04-22
Contexte
Section intitulée « Contexte »Au premier cadrage, nous avions proposé de reporter le Form Designer (éditeur no-code de parcours KYC) à la V1, en s’appuyant sur des templates YAML pré-livrés. Retour terrain du marché tunisien :
« En Tunisie, on ne peut pas vendre si tu n’as pas le form designer. »
Les raisons observées :
- Les AO publics et cahiers des charges bancaires tunisiens expriment explicitement une exigence de « paramétrage » et de « personnalisation » des parcours.
- Les banques locales disposent de multiples produits (compte courant, compte jeune, compte pro, crédit, cartes) avec des formulaires distincts qu’elles veulent répliquer exactement.
- Les concurrents régionaux (uqudo, Valify) affichent des parcours configurables comme fonctionnalité standard.
- Une position « parcours standards + YAML backend » est perçue comme un manque de maturité produit et ferme la porte commerciale.
Décision
Section intitulée « Décision »Le Form Designer est inclus dans le périmètre MVP (V0) avec le périmètre fonctionnel décrit au §4.1.0 du cahier des charges : drag-drop de champs, règles de visibilité, localisation FR/AR/EN, versioning par tenant, templates sectoriels, preview live, rendu dynamique via le SDK Web.
Justification
Section intitulée « Justification »- Gate commercial : sans Form Designer, pas de deal MENA au M+6. Le MVP perd sa raison d’être.
- Différenciation : renforce la promesse « hybride + modulaire + MENA-first » avec un attribut produit concret.
- Effet boule de neige : le Form Designer crée la surface d’intégration pour les futurs modules (AML screening inline, TCR indicia capture), donc le construire tôt évite de refactorer plus tard.
Conséquences
Section intitulée « Conséquences »Positives
- Déblocage commercial du marché tunisien et plus largement MENA.
- Capacité à répondre aux AO publics avec un produit “paramétrable” par l’acheteur.
- Architecture plus extensible dès le MVP.
Négatives
- + 67 SP au backlog MVP (épic E17) — dépassement de ~15 % de la capacité initiale des 12 sprints.
- Nécessite un frontend senior de plus (ou extension du MVP à 14 sprints).
- Complexité DB accrue (JSONB pour définitions + données collectées), plus de tests de non-régression.
Décisions secondaires
Section intitulée « Décisions secondaires »- Pas d’A/B testing au MVP — reporté à V1.
- Pas de logique avancée (boucles, sous-formulaires dynamiques) au MVP — règles simples seulement.
- Pas d’intégration Webhook/API sur événement de champ au MVP.
Revue de cette décision
Section intitulée « Revue de cette décision »- À confirmer en démo fin S08 : le Form Designer doit être montrable à un prospect en direct.
- En cas de dérapage de charge > 20 %, revue Architecture + Product Management avant extension ou réduction de scope.
Alternatives considérées et écartées
Section intitulée « Alternatives considérées et écartées »| Option | Pourquoi écartée |
|---|---|
| YAML templates + code-only customization | Rejetée par le marché tunisien ; perçue comme non mature. |
| Form Designer reporté V1 avec “promesse roadmap” | Ne gagne pas les AO ; perd 6 mois de revenu. |
| OEM ou revente d’un form designer tiers (Formspree / Form.io) | Intégration profonde requise avec les briques KYC (OCR, liveness, signature) — coût d’intégration supérieur au build ciblé. |
Références
Section intitulée « Références »VitaKYC_Cahier_des_Charges.md§4.1.0VitaKYC_Plan_Projet_MVP.mdépic E17- Feedback terrain VitaKYC (avril 2026)
ADR-008 — Génération PDF : Apache PDFBox + Gotenberg pour rendus riches
Section intitulée « ADR-008 — Génération PDF : Apache PDFBox + Gotenberg pour rendus riches »Statut : Proposé · Date : 2026-04-22
Contexte
Section intitulée « Contexte »Plusieurs artefacts PDF à produire : formulaires W-8BEN / W-8BEN-E / W-9, résumés KYC, rapports d’audit BCT/AMF, bordereaux FATCA + AD. Options : PDFBox (OSS Apache 2.0), iText (AGPL ou licence payante), wkhtmltopdf (archivé 2023), Puppeteer/Playwright (coût RAM), Gotenberg (service Chromium + LibreOffice en docker).
Décision
Section intitulée « Décision »- Apache PDFBox pour les formulaires réglementaires figés (W-8 / W-9, templates IRS) — contrôle précis des champs et fidélité visuelle.
- Gotenberg comme service docker isolé pour les rendus riches (rapports stylés, dashboards exportables) — HTML + CSS print + graphiques via API simple.
Justification
Section intitulée « Justification »- Apache 2.0 compatible SaaS commercial (pas iText AGPL).
- Gotenberg isole Chromium sans embarquer Puppeteer dans chaque service.
- Couverture complète en deux outils simples.
Alternatives écartées
Section intitulée « Alternatives écartées »iText AGPL / commercial cher · wkhtmltopdf mort · Puppeteer embarqué → empreinte RAM non maîtrisée.
ADR-009 — i18n : ICU MessageFormat + CSS logique + RTL arabe de bout en bout
Section intitulée « ADR-009 — i18n : ICU MessageFormat + CSS logique + RTL arabe de bout en bout »Statut : Proposé · Date : 2026-04-22
Contexte
Section intitulée « Contexte »VitaKYC est MENA-first. L’arabe RTL est une langue de première classe, pas une traduction tardive. Doit couvrir : back-office React, SDK Web, emails / SMS / PDFs, messages API, formats (dates Hijri optionnel, chiffres latin/indo-arabes, monnaies).
Décision
Section intitulée « Décision »- ICU MessageFormat (pluralisation, sélection, formats imbriqués) partout.
- Front React : react-intl / FormatJS.
- Backend Kotlin : kotlinx-serialization + formatter custom ICU.
- CDLR data pour formats locaux.
- CSS logique (
margin-inline-start,padding-inline-end,text-align: start) pour tout nouveau composant. dir="rtl"sur<html>activé par la locale ; chaque composant validé en miroir dans Storybook.- Polices : Inter (latin) + IBM Plex Sans Arabic (chargement conditionnel).
- OpenSearch avec analyseurs
arabic,french,englishpour recherche multilingue.
Standards
Section intitulée « Standards »- BCP 47 (
ar-TN,fr-TN,ar-SA,en-US). - ISO 4217 monnaies.
- ISO 8601 dates/heures en API.
Conséquences
Section intitulée « Conséquences »Conformité culturelle forte = différenciation MENA réelle. Coût : test de chaque composant UI en RTL.
ADR-010 — Distribution SDKs : NPM + Maven Central + Swift PM (public) + registries privés (enterprise)
Section intitulée « ADR-010 — Distribution SDKs : NPM + Maven Central + Swift PM (public) + registries privés (enterprise) »Statut : Proposé · Date : 2026-04-22
Décision
Section intitulée « Décision »| SDK | Canal public | Canal enterprise |
|---|---|---|
| Web TypeScript | @vitakyc/sdk-web sur npmjs.com | GitHub Packages privé |
| iOS Swift | Swift Package Manager depuis repo public | CocoaPods privé (spec repo) |
| Android Kotlin | Maven Central io.vitakyc:sdk-android | JFrog Artifactory privé |
| React Native | @vitakyc/sdk-react-native | — |
| Flutter (V2) | pub.dev vitakyc | — |
Publication automatisée via CI tag-triggered (vX.Y.Z) depuis le monorepo SDK. SemVer strict, cosign sur artefacts, SBOM CycloneDX joint.
Deprecation policy
Section intitulée « Deprecation policy »6 mois minimum de support après release d’une MAJOR. Headers Deprecation + doc changelog publique.
Alternatives écartées
Section intitulée « Alternatives écartées »Self-hosted only (frein adoption), JitPack Android (peu pro).
ADR-011 — E-signature : DocuSign + Yousign FR + TunTrust/ANCE (Tunisie) + module natif SES + option QES
Section intitulée « ADR-011 — E-signature : DocuSign + Yousign FR + TunTrust/ANCE (Tunisie) + module natif SES + option QES »Statut : Proposé · Date : 2026-04-22 · Révision : 2026-04-22 (ajout Tunisie)
Contexte
Section intitulée « Contexte »Les formulaires W-8BEN / W-8BEN-E / W-9, les consentements de traitement et les contrats de délégation nécessitent une signature électronique. Enjeux :
- Couverture géographique MENA (en particulier Tunisie) + UE + mondial
- Conformité au cadre juridique local (force probante devant tribunal)
- Coût par signature
- Traçabilité intégrée à la piste KYC
Décision
Section intitulée « Décision »Approche multi-provider configurable par tenant avec 5 options :
- DocuSign — provider par défaut Growth / Enterprise, couverture mondiale, API mature.
- Yousign / Universign (France) — eIDAS AES / QES, moins cher que DocuSign sur la zone UE.
- TunTrust / ANCE (Tunisie) — NOUVEAU — signature électronique qualifiée tunisienne conforme à la loi n°2000-83 du 9 août 2000 relative aux échanges et au commerce électroniques. TunTrust (filiale de La Poste Tunisienne) est émetteur principal des certificats qualifiés, reconnus par tribunaux tunisiens et utilisables par les banques, assurances et administrations.
- Module natif VitaKYC — signature simple (SES) intégrée au parcours KYC pour les cas standards (consentement GDPR, W-8BEN individu) — évite le coût externe de 2-5 €/signature. Basé sur canvas HTML5 + timestamp + hash + piste audit WORM.
- Option QES on-prem — Cryptolog Evidency, Signaturit ou Universign QES pour clients exigeant PKI dédiée.
Pourquoi TunTrust / ANCE
Section intitulée « Pourquoi TunTrust / ANCE »- Infrastructure déjà requise : le cahier des charges DGI V1.0-2019 FATCA exige un certificat ANCE pour l’accès à la plateforme IDES (cf. §12.3.2 du cahier des charges VitaKYC). Les clients banque / IF tunisiens possèdent déjà ces certificats.
- La Poste Tunisienne est actionnaire de TunTrust — alignement stratégique fort avec notre AO cible N°1.
- Force probante locale : les contrats bancaires et consentements KYC signés avec TunTrust sont reconnus devant les tribunaux tunisiens, contrairement à DocuSign ou Yousign FR qui supposent un rattachement à une juridiction étrangère.
- Écosystème TEIF — TunTrust/ANCE porte aussi les signatures TEIF (Tunisian Electronic Invoice Format) utilisées pour la facturation électronique. Supporter TunTrust à travers VitaKYC ouvre une optionalité V2/V3 pour un module e-invoicing TEIF (nouveau produit adjacent).
Architecture d’intégration TunTrust / ANCE
Section intitulée « Architecture d’intégration TunTrust / ANCE »- API : TunTrust expose une API de signature distante (Remote QES) via SOAP/REST selon offre ; alternative : client-side avec TUN-PKCS11 pour utilisation de cartes à puce / tokens USB ANCE-issued.
- Certificats acceptés :
- TunTrust Certificat Qualifié Personne Physique (pour signataires individuels dirigeants).
- TunTrust Certificat Qualifié Personne Morale (cachet électronique IF déclarante).
- Autres CAs reconnus par ANCE (SOTRACT, autres).
- Formats produits : PAdES (PDF), XAdES (XML — utile pour FATCA XML v2.0 et TEIF), CAdES (CMS/PKCS7).
- Validation : service de validation long-terme (LTV) pour garantir la validité dans le temps.
- Stockage VitaKYC : les signatures et certificats associés sont archivés WORM 10 ans + horodatage qualifié.
Critères par cas d’usage (mis à jour)
Section intitulée « Critères par cas d’usage (mis à jour) »| Cas | Niveau exigé | Provider recommandé |
|---|---|---|
| Consentement GDPR au KYC | SES | Module natif VitaKYC |
| W-8BEN individu | SES + timestamp | Module natif VitaKYC |
| W-8BEN-E entité — tenant tunisien | AES/QES locale | TunTrust / ANCE |
| W-8BEN-E entité — tenant UE | AES | DocuSign / Yousign |
| Mandat SEPA — tenant FR | AES | Yousign |
| Contrat compte bancaire TN | QES tunisienne | TunTrust / ANCE |
| Contrat compte bancaire FR | QES eIDAS | Yousign QES / Universign |
| Dépôt FATCA à IDES (cachet électronique IF) | QES tunisienne | TunTrust / ANCE (certificat obligatoire IDES) |
| Signature de rapport BCT généré | QES tunisienne | TunTrust / ANCE |
Conséquences
Section intitulée « Conséquences »Positives
- Alignement fort avec le marché tunisien et les AO publics (La Poste Tunisienne en tête).
- Force probante locale assurée.
- Mutualisation de l’infrastructure PKI ANCE déjà requise pour IDES.
- Ouvre une optionalité produit TEIF en V2/V3.
Négatives
- 5 intégrations à maintenir (vs 3 initialement).
- TunTrust API moins mature que DocuSign — documentation partielle, support local à cultiver.
- Onboarding certificat ANCE par client ≈ 2-4 semaines côté client (pas de VitaKYC) — à intégrer au plan d’onboarding.
Hors périmètre VitaKYC (à noter)
Section intitulée « Hors périmètre VitaKYC (à noter) »- Module e-invoicing TEIF complet n’est pas dans le scope V1. Le support TunTrust permet de le construire en V2/V3 comme produit adjacent si un client en exprime le besoin.
- Module de facturation B2G (Kassiopia, TTN) n’est pas dans le scope VitaKYC.
ADR-012 — Zero-downtime upgrades on-prem, y compris Oracle + support air-gap
Section intitulée « ADR-012 — Zero-downtime upgrades on-prem, y compris Oracle + support air-gap »Statut : Proposé · Date : 2026-04-22
Contexte
Section intitulée « Contexte »Clients banque on-prem exigent PostgreSQL ou Oracle. SLA 99,9 % requis. Certains environnements sont air-gap (pas de phone-home possible).
Décision
Section intitulée « Décision »Stratégie blue-green au niveau pod + migrations DB backward-compatibles :
- Rolling update Kubernetes (maxUnavailable=0, maxSurge=1) par défaut.
- Flyway multi-SGBD (PostgreSQL + Oracle + SQL Server) avec règle absolue : toute release N+1 fonctionne avec le schéma N (pattern expand/contract).
- Tests CI obligatoires : image N+1 bootée sur schéma N avant approbation release.
- Runbook trimestriel on-prem livré avec chaque release, incluant pré-requis Oracle (privilèges, tablespaces, backups).
- Rollback documenté step-by-step, testé sur env client de test avant upgrade prod.
- Bundle air-gap signé cosign : images OCI + Helm chart + migrations SQL + release notes, transféré sur support amovible chiffré si requis.
Alternatives écartées
Section intitulée « Alternatives écartées »Liquibase (plus complexe qu’on en a besoin MVP) · Schema-per-version (impossible multi-tenant Oracle) · Downtime toléré (inacceptable banque tier-1/2).
ADRs à produire ultérieurement (backlog)
Section intitulée « ADRs à produire ultérieurement (backlog) »- ADR-013 — Stratégie de recherche full-text multilingue (arabe, français) — OpenSearch analyzers + plugin ICU.
- ADR-014 — Real-time transaction streaming : Kafka Streams vs Flink pour transaction monitoring (cf. AML TxMon).
- ADR-015 — Certificats mTLS gestion : Cert-Manager + CA privée interne.
- ADR-016 — Mobile SDK size budget + lazy loading modèles ONNX.
Fin du document ADRs.