ADR-0001 — Où vivent les tables de mortalité réglementaires (CIMA q_x)¶
| Statut | ✅ Accepté — 2026-06-08 |
| Portée | actuariat_lib (couche de calcul DBO), module ActuaryLab |
| Décision | Embarquer les tables CIMA H/F 2012 dans la lib (src/actuariat_lib/tables/data/) |
| Contexte méthode | Temps 3 « construire » de la méthode à 4 temps — packaging de la donnée canonique |
🎯 À retenir
Les deux tables CIMA H/F 2012 sont embarquées dans actuariat_lib (src/actuariat_lib/tables/data/), source unique de vérité co-localisée avec le code. C'est une exception assumée à la politique « données réglementaires non versionnées ». Migration vers un package séparé (quantis-actuarial-data) uniquement quand un 2ᵉ module Quantis consommera les mêmes tables.
Contexte¶
Le moteur DBO (dbo_population_puc, dbo_individuelle_puc) a besoin des probabilités annuelles
de décès q_x des tables réglementaires CIMA H (décès) et CIMA F (vie), pour les
calculs clients réels. Jusqu'ici la lib est une couche pure : charger_table_mortalite
prend des tableaux lx/qx en entrée, et la lib ne livre aucune donnée. Les CSV extraits
du Code CIMA 2019 (art. 338) vivent dans references/cima-tables/ et y sont gitignorés
(politique « données réglementaires non versionnées »).
Question à trancher : où réside la copie canonique des q_x, pour que tout appelant calcule sur la même table sans ré-extraire un PDF de 21 Mo ?
Deux contraintes transverses pèsent :
- Règle d'or — la lib reste pure (aucune dépendance framework). Une donnée n'est pas une dépendance framework : embarquer un CSV ne viole pas la règle.
- Politique gitignore — les CSV réglementaires sont aujourd'hui non versionnés
(
references/.gitignore). Embarquer dans la lib suppose une exception explicite.
Options considérées¶
- A — Embarquées dans la lib :
src/actuariat_lib/tables/data/cima_*_2012.csv+ loadercharger_table_reglementaire("CIMA_H_2012"). La lib est livrée avec sa donnée canonique. - B — Fournies à l'exécution : la lib reste sans donnée ; l'appelant (backend, DB
admin-éditable, dossier de config) injecte les q_x au runtime via
charger_table_mortalite. - C — Package de données séparé : un
quantis-actuarial-dataversionné à part (dépendance optionnelle, checksums/provenance), consommable par plusieurs modules Quantis.
Comparatif pour / contre¶
| Critère | A — Embarquées dans la lib | B — Fournies à l'exécution | C — Package séparé |
|---|---|---|---|
| Source unique de vérité | ✅ co-localisée avec le code | ❌ chaque appelant a sa copie → divergence | ✅ une seule, gouvernée |
| Reproductibilité / offline | ✅ totale, aucun fetch | ⚠️ dépend de l'appelant | ✅ par version épinglée |
| API d'appel | ✅ charger_table_reglementaire("CIMA_H") |
❌ l'appelant lit PDF/CSV lui-même | ✅ import + loader |
| Testabilité de la lib | ✅ tests réels, sans fixture externe | ❌ fixture quand même nécessaire | ✅ via dép de test |
| Mise à jour d'une table | ❌ nécessite une release de lib | ✅ change côté data, lib intacte | ✅ bump du package data seul |
| Respect règle d'or (pureté) | ✅ (donnée ≠ dép framework) | ✅✅ lib 100 % calcul | ✅ lib pure + dép data optionnelle |
| Politique gitignore réglementaire | ❌ contredit (exception à décider) | ✅ inchangée | ⚠️ déplacée dans l'autre repo |
| Gouvernance / redistribution | ⚠️ la lib redistribue un extrait réglementaire | ✅ aucune donnée dans la lib | ✅ périmètre légal isolé |
| Réutilisation multi-modules | ⚠️ couplée à actuariat_lib |
⚠️ chacun se débrouille | ✅✅ conçue pour ça |
| Coût / infra aujourd'hui | ✅ quasi nul (2 petits CSV) | ✅ nul | ❌ 2e repo, publication, coordination |
| Couplage des cadences | ❌ code et donnée bumpent ensemble | ✅ découplés | ✅ découplés |
Décision¶
Option A — embarquer les tables dans la lib, et assumer l'exception à la politique gitignore pour ces deux fichiers.
Justification. Il y a 2 tables, ce sont des constantes réglementaires stables (les tables CIMA 2012 sont en vigueur depuis des années, art. 338) : la co-localisation maximise reproductibilité, simplicité d'API et testabilité réelle, à coût d'infra quasi nul. B ne répond pas à la question — il la déplace dans le backend et invite la divergence de copies. C est la bonne réponse à l'échelle plateforme (≥ 2 modules consommant la donnée), mais relève aujourd'hui du YAGNI et de la cérémonie cross-repo.
Conséquences¶
- Fichiers versionnés :
src/actuariat_lib/tables/data/cima_h_2012.csv,cima_f_2012.csv,CHECKSUMS.txt,PROVENANCE.md. Exception inscrite dans le.gitignoreracine (négation de garde) ; le PDF source (21 Mo) reste gitignoré dansreferences/. - Garde-fous d'audit :
charger_table_reglementaire(...)vérifie le SHA-256 de chaque CSV au chargement (toute altération silencieuse échoue). La provenance (Code CIMA 2019, art. 338, p. 225/226) et la procédure de régénération sont dansdata/PROVENANCE.md. - API & packaging : nouvelle fonction publique
charger_table_reglementaire(lib 1.1.0),package-datadéclaré danspyproject.tomlpour livrer les CSV à l'install. - Tests :
tests/test_tables_reglementaires.py(contenu, checksum, et bout-en-bout : la table embarquée reproduit l'oracle K1 = 2 751 205,018849 FCFA).
Déclencheur de réexamen (pré-enregistré)¶
Dès qu'un 2ᵉ module Quantis a besoin des mêmes tables CIMA, migrer A → C : extraire
actuariat_lib/tables/data/ vers un package quantis-actuarial-data. La migration est
mécanique (déplacer le dossier + publier + dépendance optionnelle), donc choisir A maintenant
ne ferme pas la porte C.