ADR-0031 — Le pivot framework : noyau actuariel extrait, ActuaryLab devient une vitrine de surfaces métier (β)¶
| Statut | 🟢 Accepté — 2026-06-23 ; non implémenté (plan strangler T0→T5 ci-dessous, aucune tranche démarrée). |
| Portée | Topologie de la plateforme actuarielle : extraction du moteur en repo dédié quantis-actuariat, promotion d'ActuaryLab en vitrine de surfaces métier, contrat d'engagement du noyau, modèle de session multi-surfaces, partition de la documentation. Ne touche aucun chiffre (oracles K1/K-OHADA inviolés). |
| Décision | Extraire le noyau actuariel en package versionné quantis-actuariat (ce qui déclenche le réexamen A→C pré-enregistré d'ADR-0002) ; ActuaryLab devient une vitrine, chaque métier (IFC, Assurances, Épargne) une surface déployable consommant le package (topologie β) ; le contrat d'API du noyau est conçu contre deux métiers avant d'être figé ; session par cookie de domaine parent partagé. |
| Réf. | ADR-0001 — Tables réglementaires (déclencheur données) ; ADR-0002 — Backend consomme actuariat_lib (déclencheur A→C que l'on tire) ; ADR-0003 — Identité fédérée SSO ; ADR-0005 — Tenant = groupe ; ADR-0006 — Personas staff cross-tenant ; ADR-0004 — Labo d'hypothèses |
🎯 À retenir
Erreur d'architecture reconnue : on a construit un module là où le cœur réutilisable
aurait dû être un framework. Le périmètre actuariel est vaste (IFC, épargne, assurance,
régimes complémentaires) mais le moteur est étroit, et la maths la plus riche (épargne) a
été conçue hors noyau. On pivote : un noyau actuariel large et pur (quantis-actuariat,
extrait en repo dédié) alimente plusieurs UIs métier, exposées derrière une vitrine
actuarielle, fractale de Quantis un étage plus bas. Atteint par strangler-fig (ActuaryLab
continue de tourner, on extrait et on élargit par tranches, les oracles gardent chaque pas),
validé par un n=2 réel (l'épargne salariale). Topologie β assumée : chaque métier est
une surface déployable, pour un release, un scaling et une certification indépendants par
métier ; l'alternative α (route-groups mono-surface) a été pesée et écartée.
Contexte¶
Le périmètre métier visé (IFC / IAS 19, épargne salariale, assurance, régimes spéciaux et
complémentaires) est large. Or le moteur actuariat_lib est restreint au couple IFC/DBO, et la
frontière actuelle trahit la confusion module / framework :
- God-model IFC.
HypothesesActuarielles(src/actuariat_lib/models.py:174) mélange des hypothèses générales (taux, tables, date d'évaluation) et des paramètres produit IFC (grille_ifc,base_calcul_ifc,mode_depart, plafonds). Le contrat HTTPbackend/app/dbo.py:57code en dur ce payload IFC. Le produit fuit dans le « général ». - Maths épargne hors noyau. Les briques plus riches (PM millésimée, DBO DC = valeur actuelle
des cotisations futures, vesting, décréments composites, aléatoire, sensibilité/duration) ont
été conçues dans la couche service d'un prototype Django (spec « Module Épargne salariale »
§6.1), pas dans
actuariat_lib. Ce prototype est une proposition non autoritaire : sa spec sert de cahier de largeur du noyau, pas d'actif à porter ; ses chiffres sont indicatifs, pas des oracles durs. - Conséquence. Les mathématiques sont soudées aux couches module, sans noyau large partagé. C'est la faute « module au lieu de framework », prise sur le fait.
La vision cible : cliquer ActuaryLab depuis le portail Quantis n'ouvre plus directement l'IFC, mais une vitrine d'applications actuarielles ; on y choisit l'UI d'un métier (IFC, Assurances, Épargne…) et l'on entre dans son interface, le tout alimenté par le même noyau, en conservant le SSO et la troisième porte d'accès direct existants.
Trois décisions cadrantes ont été prises (questions au PO) : périmètre = noyau actuariel large + contrat d'API stable ; migration = strangler-fig ; n=2 validant = épargne salariale.
Décision¶
-
D-EYWA-1 — Noyau actuariel large, pur, extrait en repo
quantis-actuariat. Le noyau absorbe l'union des primitives des métiers (engagements DB-PUC, DC, aléatoire, hybride ; millésimes ; vesting ; décréments composites ; taux variables ; fractionnement ; sensibilité/duration ; waterfall). Il reste pur (la « règle d'or » : aucune dépendance framework web). Ses oracles (K1, K-OHADA) voyagent avec lui. L'extraction déclenche le réexamen A→C pré-enregistré d'ADR-0002 :actuariat_libcesse d'être consommé « depuis les sources du monorepo » pour devenir un package versionné, épinglé par chaque consommateur. La pureté unidirectionnelle d'ADR-0002 est conservée et durcie (frontière désormais physique, plus seulement disciplinaire). -
D-EYWA-2 — Scinder le god-model, poser un contrat d'engagement.
HypothesesActuariellesse scinde enHypothesesGenerales(économiques / démographiques) +ParamsRégime(spécifique au produit : grille IFC, configuration d'un plan d'épargne…). Un contrat d'engagement unifie les métiers :evaluer(population, hypotheses_generales, params) -> résultat décomposable(waterfall). DB-PUC, DC, aléatoire et hybride l'implémentent. C'est l'interface de plug dans laquelle chaque métier vient se brancher. -
D-EYWA-3 — Topologie β : vitrine + surfaces métier déployables. ActuaryLab devient une vitrine actuarielle (sous-portail) ; chaque métier est une surface déployable séparée consommant
quantis-actuariat. L'alternative α (un seul déploiement, métiers en route-groups) a été pesée et écartée : le PO veut un release, un scaling et une certification indépendants par métier (pour un actuariat régulé, prouver « tel code exact a produit tel rapport » et rollback granulaire valent leur coût). β est sélectif : on ne sépare pas tout d'emblée, on promeut un métier en surface quand il atteint un déclencheur (cadence de release propre, compute lourd isolé, stack divergente, équipe et autorité de déploiement séparées, isolation de certification, tenance distincte). Frontière métier imposée : aucun import cross-métier, chaque métier auto-contenu (route-group + routeur d'API), idéalement gardé par une règle de boundary. -
D-EYWA-4 — Contrat d'API d'abord (n=2 avant gel). Sous β, un boundary repo dur rend chaque erreur d'API chère (bump de version + re-fetch dans N surfaces). On conçoit donc l'API publique de
quantis-actuariatcontre deux métiers (IFC réel + épargne/assurance depuis la spec) avant de la figer et de figer les surfaces dessus. C'est le n=2-avant-gel, non négociable. -
D-EYWA-5 — Session : cookie de domaine parent partagé. Une seule vérification SSO à l'entrée de la vitrine couvre toutes les surfaces actuarielles, via un cookie sur le domaine parent
.quantis-actuarylab.nedcore.net(pas de re-hop/sso/loginpar métier). La troisième porte/accesreste possible. Invariants préservés : jamais d'auto-grant de rôle (résolution par match d'email, ADR-0003) ; 302 vers l'étage amont, jamais un 401 JSON sur une navigation. Repli pré-enregistré si la portée de cookie ne tient pas (voir Déclencheur de réexamen). -
D-EYWA-6 — Layout des dépôts. Noyau
quantis-actuariat= repo dédié. Les surfaces vivent d'abord dans un monorepo de surfaces (vitrine + ifc + assurances…) à déploiements Dokploy indépendants par service : on garde l'isolement de release sans exploser le nombre de repos. On scinde une surface vers son propre repo le jour où l'équipe ou la cadence diverge vraiment. -
D-EYWA-7 — Documentation : co-localisée par repo + hub à la vitrine. La doc épouse la topologie. Le noyau emporte la formalisation (la maths), la référence d'API et le récit des oracles ; sa doc est versionnée avec lui (la formalisation qui a produit un chiffre doit être retrouvable à la version utilisée, même argument de certification que β). Chaque surface garde sa doc produit (tutoriels, how-to, spec, ADR de surface). La vitrine ajoute une doc-chapeau (architecture, modèle de session, principes) et un hub qui pointe vers les autres. Thème Material et convention Diátaxis partagés :
about/convention-doc.mdest promu de convention ActuaryLab en standard de la vitrine actuarielle. Partition ADR : les ADR 0001→0030 sont gelés comme journal historique (on ne relocalise aucun ADR numéroté : append-only et « Réf. » préservés) ; le noyau démarre son propre journal de décisions ; les nouveaux ADR sont scopés au repo propriétaire ; cet ADR-0031 vit au niveau plateforme. Le split par chemin emportedocs/formalisation/vers le noyau mais laisse le dossierdecisions/sur place.
Plan strangler (T0→T5)¶
| Tranche | Contenu | Garde |
|---|---|---|
| T0 | Extraire quantis-actuariat (git subtree split, historique + oracles + docs/formalisation/ préservés) ; le backend ActuaryLab le consomme comme package épinglé. |
K1/K-OHADA verts à travers le package. |
| T1 | Scinder le god-model IFC (HypothesesGenerales + ParamsRégime). |
Zéro changement chiffré : K1 garde. |
| T2 | Poser le contrat d'engagement ; l'IFC l'implémente. | Facteurs == oracle K1. |
| T3 | Bâtir la vitrine ; l'app actuelle devient la surface IFC derrière elle ; câbler la session (cookie parent). | Navigation SSO auto-réparante (302 amont). |
| T4 | Re-dériver l'épargne (puis l'assurance) dans le noyau contre le contrat ; sa surface. | Forge de nouveaux oracles épargne à la re-validation ; valide le contrat d'API. |
| T5 | API capability par métier ; déploiements Dokploy par surface ; doc fédérée. | mkdocs --strict vert par repo. |
Conséquences¶
- Positif. Un noyau large, réutilisable, versionnable et certifiable par composant ; release / scaling / certification indépendants par métier ; une vitrine qui rend l'écosystème lisible ; la frontière de calcul (l'actif certifié) physiquement isolée du web.
- Coûts assumés (β). N déploiements / configurations SSO / domaines Dokploy ; friction
cross-repo pendant les tranches de forte co-évolution (T1→T2) ; search et découvrabilité de la
doc fragmentés (mitigés par le hub) ; les liens cross-repo ne sont plus vérifiés par
mkdocs --strict. - Invariants tenus à chaque tranche. Noyau pur ; K1/K-OHADA inviolés ; oracles épargne
forgés à la re-validation (pas hérités du prototype) ; aucun import cross-métier ; toute
nouvelle colonne de modèle reste déclarée dans
_COLONNES_AJOUTEES(db.py), par surface, sinon 500 en production. - Pièges Dokploy multi-surface (rappel). Alias compose préfixés uniques (collision DNS sur
dokploy-network) ;environment:déclaré par service (sinon 404 Traefik silencieux) ;NEXT_PUBLIC_*bakés au build de chaque surface.
Déclencheur de réexamen (pré-enregistré)¶
- Friction cross-repo > gain pendant T1→T2 → garder le noyau in-monorepo (package interne)
jusqu'à T4, puis n'extraire le repo
quantis-actuariatqu'une fois le contrat d'API stabilisé par le n=2 (repli α-de-transition, l'extraction parsubtree splitrestant quasi mécanique). - Un métier n'atteint jamais un déclencheur de promotion β → le laisser en route-group d'une surface existante (β sélectif n'oblige pas à tout séparer).
- Le cookie de domaine parent ne tient pas (portée de sous-domaine, mixed-content) → bascule
vers
oauth2-proxy/ OIDC, ou un/sso/loginpar surface (un hop de plus, assumé). - Une certification réclame chaque artefact livré par version → publier
quantis-actuariatsur un index privé avec rétention des versions (la cible C d'ADR-0002, pleinement réalisée).