Aller au contenu

ActuaryLab — Plan d'implémentation Feature-First

Positionnement : ActuaryLab est l'un des modules verticaux de la plateforme Quantis (incubateur de modules métier du cabinet BFEV). Ce plan ne concerne que le module ActuaryLab — le socle Quantis (Beta Launcher, propagation SSO, catalogue de modules) fait l'objet d'un chantier distinct dans le dépôt Quantis-app/.

Stack arrêté : FastAPI · Next.js 15 · PostgreSQL · MinIO · Docker Compose — stack déjà éprouvé sur le module sœur EmpreinteCarbone (BFEV-Projects/Empreinte_Carbone/platform/).

Auth dès le départ : SSO Quantis (patron YODICORE) — ActuaryLab n'a pas d'auth interne. Il consomme des JWT signés émis par le socle Quantis (lui-même émetteur pour ses modules, et consommateur des JWT YODICORE en amont). Cf. ../../../../Docs/protocoles_externes/yodicore_sso/.

Place dans la roadmap : ce module correspond à l'étape 2 de la roadmap maître ../../../Quantis-app/docs/ROADMAP.md. Le socle Quantis (Producer) est construit avant — étape 1. ActuaryLab se branche donc dès Jalon 0 sur un vrai service Quantis, pas sur un émetteur factice.

Principe directeur

Renverser le sens du chantier : au lieu de bâtir tout le socle infra (Postgres multi-domaines, Traefik, OTel, ELK, Helm…) avant la première fonctionnalité, on livre des tranches verticales centrées sur un parcours utilisateur réel. L'infrastructure n'est introduite que lorsqu'une fonctionnalité l'exige, dans sa forme la plus simple qui marche (SQLite → Postgres, dossier local → MinIO, in-process → Celery…).

Cinq personæ identifiés dans ../architecture/system-context-v2.svg : Consultant Client · Actuaire Junior · Actuaire Senior · Actuaire Externe · Super Admin

Ces personæ sont des rôles RBAC propagés par le socle Quantis dans le JWT (roles: [...]). ActuaryLab les mappe en permissions internes mais ne les crée pas.

Chaque jalon = un parcours bout-en-bout démontrable.

Références à consulter avant chaque jalon : - ../architecture/system-context-v2.svg — contexte système - ../architecture/Containers_diagram-v0.svg — décomposition en conteneurs - ../architecture/rôles_des_utilisateurs_quantis.svg — rôles détaillés par persona - ../specs/SFD_ActuaryLab_v2_0.md — spécification fonctionnelle détaillée - ../specs/SFDI_ActuaryLab_v1_0.md — spécification des interfaces & navigation (HTMX, à transposer Next.js) - ../specs/Module_IFC_ActuaryLab_v1_0.md — module IFC - ../specs/Module_Epargne_Salariale_ActuaryLab_v2_0.md — module Épargne Salariale - ../specs/NOTE_TECHNIQUE_MOTEUR_CALCUL_DBO.md — moteur de calcul DBO - ../../refs/actuariat_lib/ — bibliothèque actuarielle réutilisable (API déjà conçue) - ../../../../Docs/protocoles_externes/yodicore_sso/ — protocole SSO normatif


Jalon 0 — Squelette SSO-only (≈ 3 j) — étape 2 de la roadmap

Pré-requis : le squelette Producer du socle Quantis (étape 1) existe et expose POST /api/v1/beta/sso/verify/.

Livrable : une app FastAPI + Next.js qui démarre via docker-compose up, exposant un endpoint /sso/login/?token=<jwt> qui consomme un JWT Quantis et crée la session locale. Aucun login form, aucune table users locale.

  • src/backend/ (FastAPI)
  • app/sso.py : endpoint /sso/login/, validation JWT (V2 — appel POST /verify/ du socle Quantis via QUANTIS_VERIFY_URL), création session, scoping tenant_schema.
  • app/session.py : middleware FastAPI qui charge {tenant_schema, user_id, roles} depuis le cookie de session.
  • Page /dashboard minimale scopée tenant_schema, affichant user + tenant — la preuve visible que la chaîne SSO fonctionne.
  • src/frontend/ (Next.js, App Router) : middleware qui lit le cookie de session, redirige vers le portail Quantis si absent.
  • src/actuariat_lib/ packagé (sous-modules tables/, probabilites/, financier/, engagements/, utils/ à compléter — l'API publique est déjà déclarée dans refs/actuariat_lib/__init__.py).
  • Persistance : SQLite. La table Tenant est créée à la volée au premier SSO d'un nouveau tenant_schema.
  • Infra introduite : Docker Compose pour l'app, rien d'autre.

Jalon 1 — Parcours Consultant Client : « solliciter un produit » (≈ 1 sem)

Le plus court chemin vers de la valeur visible, tout scopé au tenant_schema reçu du JWT.

  • Page produits + formulaire de sollicitation (l'inscription est gérée par Quantis en amont — ici le user existe déjà).
  • Upload des documents RH dans ./storage/<tenant_schema>/... (filesystem isolé par tenant).
  • Tableau « Mes demandes » + statuts (soumis, en cours, livré), filtré au tenant_schema du user.
  • Infra introduite : rien de neuf.

Jalon 2 — Parcours Actuaire Junior : « importer → hypothèses → calcul → résultat » (≈ 2 sem)

Cœur métier du module — actuariat_lib est mobilisée.

  • Portail Junior : liste des dossiers reçus du client (filtrés par tenant_schema).
  • Import RH avec validation de schéma (Pydantic) ; canal de discussion si invalide. Données d'exemple dans data/samples/.
  • Éditeur d'hypothèses (jeux nommés, versionnés) — voir HypothesesActuarielles dans actuariat_lib.models.
  • Moteur de calcul DBO v0 : exécution synchrone in-process via actuariat_lib.engagements.dbo_population_puc, résultats en JSON. Première règle : IFC (cf. spec Module_IFC_ActuaryLab_v1_0.md).
  • Visualisation : tableaux + 1 ou 2 graphiques (Recharts) — waterfall IAS 19.
  • Génération d'un rapport PDF (WeasyPrint ou Quarto).
  • Infra introduite : toujours rien de neuf.

Jalon 3 — Workflow Senior + Externe : audit en chaîne (≈ 1,5 sem)

  • Portail Senior : assignation dossier→junior, revue, validation/invalidation, critique des hypothèses.
  • Transmission du rapport à l'actuaire externe — l'externe est un user Quantis avec le rôle actuaire_externe. ActuaryLab ne crée pas le compte, il émet une notification (via Quantis) qui amène l'externe à se SSO-iser dans ActuaryLab.
  • Portail Externe : consulter rapport, explorer paramètres (analyse de sensibilité), déposer critiques, renvoyer audit.
  • Notifications : email (SMTP simple — Mailhog en dev) OU via une API de notification du socle Quantis si elle existe à ce moment-là.
  • Transmission du rapport définitif au client → boucle bouclée avec Jalon 1.
  • Infra introduite : Mailhog (1 service compose).

Jalon 4 — Mapping rôles & permissions ActuaryLab (≈ 2 j)

Remplace l'ancien « Super Admin + RBAC » — celui-ci se réduit à du mapping.

  • Tableau RoleMapping : quantis_role → permissions_actuarylab. Ex : CONSULTANT_CLIENT → [voir_propres_dossiers], ACTUAIRE_JUNIOR → [importer_rh, calculer, generer_rapport], etc.
  • Décorateurs FastAPI @requires_permission("calculer") qui lisent les roles du JWT et résolvent via RoleMapping.
  • Middleware Next.js équivalent côté frontend (masquage des liens non autorisés).
  • Aucun CRUD users dans ce module — c'est le travail de Quantis.
  • Infra introduite : rien.

Jalon 4 bis — Second module métier : Épargne Salariale (≈ 2 sem)

Validation du caractère « moteur générique » de la couche DBO.

  • Implémentation du module Épargne Salariale (cf. spec Module_Epargne_Salariale_ActuaryLab_v2_0.md).
  • Workflow 4 phases : Sélection des Données → Paramétrage 7 blocs → Calcul → Résultats.
  • Ajout des familles de règles manquantes au moteur DBO (TAUX_REMPLACEMENT, CAPITAL_ACCUMULE, MONTANT_FIXE, CAPITAL_MILLESIMES, ALEATOIRE) — GRILLE_ANCIENNETE étant déjà couvert par l'IFC.

⟶ Point de bascule : ActuaryLab couvre 2 produits actuariels et les 5 rôles. On ensuite durcit.


Jalon 5 — Durcissement juste-à-temps (≈ 1,5 sem)

Chaque ajout est justifié par une douleur déjà rencontrée :

Douleur observée Réponse infra
SQLite verrouille sous charge PostgreSQL 16 + Alembic
Filesystem pas partageable / sauvegardable MinIO (scoping par tenant_schema/)
Calculs longs bloquent l'UI (populations 1 000+) Celery + Redis
URLs en localhost:8000, :3000, :9001 peu pro Traefik + hosts *.actuarylab.local
Mots de passe / secrets en clair → Docker Secrets
Plantages opaques → logs JSON structurés

Jalon 6 — Observabilité & sécurité (≈ 1 sem)

  • OpenTelemetry → Jaeger.
  • Trivy + Bandit dans une CI GitHub Actions minimale.
  • Chiffrement au niveau champ pour PII (salaires, identifiants) avec cryptography.
  • Service d'anonymisation pour la donnée de dev.

Jalon 7 — Production (≈ 1,5 sem, optionnel/différé)

  • Helm chart, déploiement K8s, HPA, ingress TLS.
  • Seulement si un vrai besoin de prod multi-tenant arrive. Sinon, Compose sur un VPS suffit longtemps. Précédent à observer : Empreinte_Carbone/platform/ tourne déjà en Compose.

Articulation avec Quantis (socle)

ActuaryLab dépend de Quantis pour son auth, dès le premier commit. Cette dépendance est réalisée via deux contrats :

  1. Endpoint /sso/login/?token=<jwt> (côté ActuaryLab) : reçoit un JWT signé par Quantis, l'envoie à POST <quantis>/api/v1/beta/sso/verify/, reçoit {tenant, user, app, roles}, crée la session locale, redirige vers /dashboard.
  2. Variable d'env QUANTIS_VERIFY_URL : URL du service Quantis (le squelette Producer de l'étape 1 de la roadmap).

Conformément à la roadmap, le squelette Quantis est construit avant ce module (étape 1 → étape 2). ActuaryLab se branche donc dès Jalon 0 sur le vrai endpoint /verify/ — pas d'émetteur factice. Le branchement effectif des deux services (docker-compose commun) est l'étape 3.

Les 5 personæ ActuaryLab deviennent des rôles RBAC propagés par Quantis. ActuaryLab les mappe localement (Jalon 4) mais ne gère ni leur attribution ni leur cycle de vie.

Le précédent module Quantis, EmpreinteCarbone (déjà en production, auth locale legacy), sera SSO-isé plus tard via une branche topic/quantis-sso une fois le protocole éprouvé sur ActuaryLab.


Comparatif avec l'ancien plan infra-first

Ancien plan (infra-first) Plan feature-first
Première démo utilisable ~ semaine 10-11 fin semaine 3 (Jalon 2)
Risque de surdimensionner élevé faible — chaque brique infra arrive après preuve de besoin
Onboarding nouveau dev doit comprendre Traefik+ELK+Jaeger+Helm avant tout clone + docker-compose up + voir une page
Retour client possible tard dès Jalon 1
Auth invention locale puis migration future SSO Quantis dès Jalon 0 — pas de migration

Contrepartie assumée

Migrations mécaniques à venir : SQLite→Postgres, fs→MinIO, sync→Celery. Bien outillées (Alembic, scripts mc cp). Coût connu et accepté en échange d'un time-to-feature drastiquement raccourci.