Exécution live — Workflow de validation des données + RBAC par commune¶
Note mise à jour en continu pendant l'exécution. Dernière mise à jour : voir horodatage de chaque section.
Contexte¶
Suite à ProjetESM/Documents/20260708_1759_conception-validation-donnees-rbac-commune (conception validée par l'utilisateur), plan d'implémentation validé le 2026-07-08. Objectif : remplacer les 3 patterns d'ownership/scope-commune incohérents actuellement dans le code par un mécanisme unique, et ajouter un vrai workflow de validation MEAL (EN_ATTENTE/VALIDE/A_CORRIGER) avec verrouillage en cascade sur les données qui alimentent le calcul automatique des indicateurs (voir ProjetESM/debug/execution-sous-activites-indicateurs, chantier précédent).
Plan complet : /home/kanmaber/.claude/plans/bright-roaming-narwhal.md.
Statut global¶
| Étape | Statut |
|---|---|
| 0 — Schéma Prisma (StatutValidation + idUtilisateur) | ✅ fait |
| 1 — Service d'autorisation générique + nettoyage | ✅ fait |
| 2 — Fix bug Enfant + harmonisation Accompagnements/MaitreCoranique | ✅ fait |
| 3 — Factory de validation + module Enfants (référence) | ✅ fait |
| 4 — Réplication module par module | ✅ fait |
| 5 — Verrouillage en cascade (4 tables participation/présence) | ✅ fait |
| 6 — idUtilisateur sur les 7 modèles sans ownership | ✅ fait (5/7, 2 chemins morts écartés) |
| 7 — Frontend (composants génériques) | ✅ fait (test navigateur non effectué) |
| 8 — Vérification finale | ✅ fait — chantier clos |
Journal d'exécution¶
2026-07-08 18:10 — Démarrage¶
Plan validé, note de suivi créée, 10 tâches enregistrées. Début de l'étape 0 (schéma Prisma).
2026-07-08 18:25 — Schéma, service générique, 2 bugs corrigés¶
- Schéma : enum
StatutValidation+ champs validation sur 20 entités racines.idUtilisateurajouté (scalaire simple, sans relation Prisma — cohérent avec le pattern déjà en place dans ce projet pour les modèles ajoutés lors du chantier précédent, évite 20+ relations nommées) sur les 4 tables de participation/présence et 5 modèles sans ownership.db pushsans perte de données. - Service générique :
IServiceAutorisationDonnees/ServiceAutorisationDonnees(singleton, commelogger). Suppression du middleware mortscopeCommune.middleware.ts. - 2 bugs corrigés : faille de contournement de scope sur
Enfant.lister()(le scope de sécurité ne peut plus être écrasé par un paramètre de requête) ; restriction stricte au créateur retirée surAccompagnement/MaitreCoranique(obtenirParId/lister), remplacée par un scope commune — le MEAL voit désormais tout dans sa commune. - Décision de scope : la factorisation de
getCommuneCode()(dupliqué dans 10 controllers) a été volontairement écartée — duplication cosmétique sans bug associé, pas de valeur à corriger dans ce chantier au regard du temps investi. - Vérifié : 0 erreur TypeScript, serveur démarré (242 routes).
Prochaine étape : factory de validation + module Enfants comme référence.
2026-07-08 18:35 — Référence Enfants opérationnelle¶
- Factory partagée
creerValiderDonneeUseCase()+ 2 handlers génériques réutilisables tels quels par tous les modules (ValiderDonneeHandler/DemanderCorrectionDonneeHandler), au lieu de 18+ use cases quasi identiques — pattern Strategy cohérent avecCalculateurFactories.tsdu chantier précédent. - Module Enfants câblé en référence : routes
/:id/valideret/:id/demander-correction,ModifierEnfantUseCasevérifiepeutModifier()avant d'écrire et repasse automatiquementEN_ATTENTEsi l'auteur corrige un enregistrementA_CORRIGER. - Vérifié par script ad hoc (jetable) sur la vraie base : agent non-MEAL refusé, MEAL_COMMUNAL même commune accepté, MEAL_COMMUNAL autre commune refusé. 0 erreur TypeScript, serveur démarré (244 routes).
Prochaine étape : réplication du pattern sur les modules restants (Accompagnements+4 volets, Formations, Insertion+4 événements, Mobilisation+5 modèles, Pilotage/EtudeDiagnostique).
2026-07-08 18:40 — 5 agents en parallèle pour l'étape 4¶
5 agents en arrière-plan (worktrees isolés), chacun avec le pattern Enfants détaillé en référence
et les particularités de dérivation du communeCode par entité (relation directe, via enfant,
via parcours.enfant, ou null forcé quand aucun scope commune n'existe — SupportCommunication,
EtudeDiagnostique) :
1. Accompagnements (+ AppuiAlimentaire, SoutienPsychologique, PriseEnChargeSanitaire, SeanceAlphabetisation)
2. Formations (FormationSensibilisation, SupportCommunication)
3. Insertion (ParcoursInsertion + 4 événements : InscriptionFormationInsertion, AccompagnementPlanAffaires, MicroSubvention, InstallationCQM)
4. Mobilisation (ComiteVillageois, ReunionComite, CadreConcertation, SessionConcertation, SessionParoleJeunes)
5. Pilotage/EtudeDiagnostique
Chaque agent : ajoute les 3 méthodes repository (obtenirPourValidation/valider/demanderCorrection),
câble la factory partagée, ajoute les routes, migre son/ses Modifier*UseCase avec peutModifier(),
vérifie tsc + démarrage serveur, commit sur sa propre branche. Fusion et vérification finale à suivre.
2026-07-08 23:16 — Limite de session sur les 5 agents, reprise, 1er merge¶
Les 5 agents ont atteint la limite de session Claude peu après leur lancement (reset 22h10). Tous repris via message une fois le reset passé.
- EtudeDiagnostique : terminé avec succès (nouveau worktree recréé par l'agent après la perte du
précédent). 10 fichiers, 0 erreur TypeScript, serveur démarré (246 routes). Fusionné dans
main(fast-forward, commite92b0b5) via un worktree temporaire dédié à la fusion. - Point d'attention : l'agent Accompagnements, en reprenant après la limite de session, n'a pas
retrouvé son worktree isolé (
.claude/worktrees/...disparu) et a basculé sa branchefeature/accompagnements-validation-workflowdirectement dans le checkout principal (/home/kanmaber/projets/ProjetESM), avec des modifications non commitées en cours. Décision : ne pas toucher au checkout principal tant que cet agent n'a pas terminé (risque de perturber un travail en cours) — attente de sa notification de fin avant de commit/fusionner son travail et de revenir surmaindans le checkout principal. - Formations, Insertion, Mobilisation : toujours en cours (worktrees isolés intacts sous
.claude/worktrees/). - Insertion : terminé avec succès, worktree isolé propre (recréé car le checkout principal était
occupé par l'agent Accompagnements). 28 fichiers (5 entités : ParcoursInsertion,
InscriptionFormationInsertion, AccompagnementPlanAffaires, MicroSubvention, InstallationCQM).
Fusionné dans
main(merge commit, aucun conflit). Vérification post-fusion :tsc --noEmit0 erreur, serveur démarré, 270 routes. Plus qu'un module en attente : Mobilisation. - Mobilisation : terminé avec succès (worktree isolé recréé après reset, aucune perte car rien
n'avait encore été écrit au moment de l'interruption). 31 fichiers (5 entités : ComiteVillageois,
ReunionComite, CadreConcertation, SessionConcertation, SessionParoleJeunes). Fusionné dans
main(merge commit, aucun conflit).
Bilan étape 4 — les 5 modules sont fusionnés dans main, vérification finale combinée :
npx tsc --noEmit → 0 erreur, serveur démarré sans erreur, 280 routes (soit +38 par rapport aux
242 de fin d'étape 2 : 2 pour Enfants, 10 pour Accompagnements, 4 pour Formations, 10 pour
Insertion, 10 pour Mobilisation, 2 pour EtudeDiagnostique). Worktrees et branches temporaires
nettoyés après fusion. Étape 4 terminée.
Prochaine étape : verrouillage en cascade des 4 tables de participation/présence (étape 5).
2026-07-08 23:30 — Étape 5 : verrouillage en cascade terminé¶
Helper partagé verifierParentModifiable.ts (parentEstVerrouille(statutValidationParent)).
8 use cases d'écriture sur les 4 tables sans statut propre chargent désormais leur parent avant
d'écrire et refusent (PARENT_VALIDE_VERROUILLE) si celui-ci est VALIDE :
- Formations (parent FormationSensibilisation) : Ajouter/Modifier/SupprimerParticipation,
TogglePresence.
- Mobilisation (parent ReunionComite) : Ajouter/ModifierPresenceReunion.
- Mobilisation (parent SessionConcertation) : Ajouter/ModifierPresenceSession.
- Mobilisation (parent SessionParoleJeunes) : Ajouter/SupprimerParticipation.
Vérifié par script ad hoc (supprimé après usage) sur la vraie base : ajout de participation accepté
avant validation de la formation, refusé avec PARENT_VALIDE_VERROUILLE après. tsc --noEmit 0
erreur, serveur démarré (280 routes, inchangé — étape purement métier, pas de nouvelle route).
Prochaine étape : idUtilisateur sur les 7 modèles sans ownership (étape 6 — déjà fait au niveau
schéma lors de l'étape 0, vérification de complétude à faire).
2026-07-08 23:35 — Étape 6 : idUtilisateur réellement persisté (5/7 modèles)¶
Audit du code (pas seulement du schéma) : la colonne existait depuis l'étape 0 mais 5 des 7 flux de
création ne l'écrivaient jamais réellement.
- Bug corrigé (Tuteur, Parent, PersonneRessource) : le use case Creer recevait idUtilisateur
mais ne le transmettait qu'à l'audit, jamais au repository → colonne restée null pour toujours.
- Bug corrigé, plus impactant (ComiteVillageois, CadreConcertation — entités racines avec statut
de validation) : idUtilisateur totalement absent du flux de création. Sans ce correctif, le
créateur d'un comité/cadre aurait été immédiatement verrouillé hors de peutModifier() dès la
création (un idUtilisateur null ne correspond jamais à un utilisateur réel).
- Décision de scope : DistributionSupport et EducateurPair volontairement laissés de côté —
aucun code n'appelle actuellement leur repository.creer() (pas de use case, pas de route) ;
câbler la traçabilité sur un chemin mort n'apporte rien.
Vérifié par script ad hoc (supprimé après usage) sur la vraie base : Tuteur, Parent et
ComiteVillageois persistent bien idUtilisateur. tsc --noEmit 0 erreur, serveur démarré (280
routes, inchangé).
Prochaine étape : frontend (composants génériques + intégration, étape 7).
2026-07-08 23:40 — Étape 7 : frontend générique + référence Enfants¶
Composants transverses (pas un écran par module) : StatutValidationBadge.tsx,
ValidationActions.tsx (boutons Valider/Demander correction, visibles seulement pour
MEAL_COMMUNAL/MEAL_NATIONAL/ADMIN/SUPER_ADMIN, masqués si déjà VALIDE, modale de commentaire
obligatoire), useValidationDonnee.ts + validation.api.ts (hook/API génériques paramétrés par
basePath REST + clés TanStack Query à invalider).
Intégrés en référence dans EnfantsPage.tsx (tableau + carte mobile) : badge, boutons d'action,
verrouillage visuel du bouton Modifier si VALIDE pour les rôles non validateurs (le backend reste
la source de vérité via peutModifier() — la fusion, ni discutée, n'a été un enjeu ici).
Vérifié : tsc --noEmit 0 erreur, npm run build réussi. Non vérifié : test interactif en
navigateur (pas d'outil d'automatisation navigateur disponible dans cet environnement) — à valider
manuellement par l'utilisateur avant mise en production.
Prochaine étape : vérification finale complète + rapport de clôture (étape 8).
Bilan de clôture (2026-07-08 23:45)¶
Chantier terminé. 16 commits sur main (aucun push), de feat(schema): workflow de validation
MEAL + traçabilité idUtilisateur à feat(rbac): composants frontend génériques….
Ce qui a été livré¶
- Schéma — enum
StatutValidation+ 4 champs sur 20 entités racines ;idUtilisateursur les 4 tables de participation/présence et 7 modèles qui en manquaient. - Service d'autorisation générique unique (
IServiceAutorisationDonnees) remplaçant 3 patterns d'ownership/scope incohérents trouvés à l'audit initial. Middleware mort supprimé. - 2 bugs de sécurité corrigés : faille de contournement de scope sur
Enfant.lister(); restriction stricte au créateur retirée surAccompagnement/MaitreCoranique(le MEAL voit désormais tout dans sa commune, pas seulement ses propres saisies). - Factory de validation générique (
creerValiderDonneeUseCase, pattern Strategy) + 2 handlers partagés réutilisés tels quels par tous les modules — 18 entités racines au total câblées avec les actions Valider/Demander correction (Enfants, Accompagnements + 4 volets, Formations + 1, Insertion + 4 événements, Mobilisation + 4, EtudeDiagnostique). - Verrouillage en cascade des 4 tables filles (participation/présence) qui alimentent le calcul des indicateurs — 8 use cases d'écriture protégés.
- Traçabilité
idUtilisateurréellement persistée à la création sur 5 modèles (2 bugs corrigés où le champ existait en schéma mais n'était jamais écrit) ; 2 modèles avec un chemin de création mort volontairement laissés de côté. - Frontend : composants transverses (
StatutValidationBadge,ValidationActions,useValidationDonnee,validation.api.ts) intégrés en référence dansEnfantsPage.tsx.
Vérifications finales¶
- Backend :
npx tsc --noEmit→ 0 erreur. Serveur démarré, 280 routes (12 publiques, 268 privées), Redis connecté. - Frontend :
npx tsc --noEmit→ 0 erreur.npm run build→ succès. - Tests fonctionnels ad hoc sur la vraie base (scripts jetables, supprimés après usage) :
- Workflow de validation : agent non-MEAL refusé, MEAL_COMMUNAL même commune accepté, MEAL_COMMUNAL autre commune refusé.
- Verrouillage en cascade : ajout de participation accepté avant validation du parent, refusé
(
PARENT_VALIDE_VERROUILLE) après. - Traçabilité :
idUtilisateurbien persisté en base pour Tuteur/Parent/ComiteVillageois. - Scope commune : un agent ne peut pas contourner son scope via un paramètre de requête ;
MEAL_NATIONAL (scope
null) voit toutes les communes.
Limitations connues / décisions de scope assumées¶
- Test interactif navigateur non effectué (pas d'outil d'automatisation navigateur disponible dans cet environnement) — à valider manuellement par Bernard avant toute mise en production.
- Frontend : seul le module Enfants a l'intégration visuelle complète (badge + actions + verrouillage). Les composants génériques sont prêts et documentés pour être branchés sur les 17 autres entités câblées côté backend — travail mécanique restant, pas un chantier de conception.
- DistributionSupport et EducateurPair : traçabilité
idUtilisateurnon câblée — ces 2 modèles n'ont actuellement aucun chemin de création actif dans le code (ni use case, ni route). À revoir si un jour un écran de création leur est ajouté. - Factorisation de
getCommuneCode()(dupliqué dans 10 controllers) : écartée dès l'étape 1, décision assumée — duplication cosmétique sans bug associé. PersonneRessourceDTOne remonte pas encoreidUtilisateurdans les réponses API (colonne persistée en base mais non exposée) — aucun consommateur n'en a besoin actuellement.
Fichiers/dossiers clés créés¶
BackEnd/src/shared/domain/interfaces/services/IServiceAutorisationDonnees.ts+BackEnd/src/shared/infrastructure/services/ServiceAutorisationDonnees.tsBackEnd/src/shared/application/{interfaces/IValidationDonneeUseCase.ts,usecases/CreerValiderDonneeUseCase.ts,services/verifierParentModifiable.ts}BackEnd/src/shared/interface-adapters/handlers/{ValiderDonneeHandler,DemanderCorrectionDonneeHandler}.tsFrontEnd/src/shared/components/ui/{StatutValidationBadge,ValidationActions}.tsxFrontEnd/src/shared/hooks/useValidationDonnee.ts+FrontEnd/src/shared/infrastructure/api/validation.api.ts- Conception validée :
wiki/ProjetESM/Documents/20260708_1759_conception-validation-donnees-rbac-commune.md
Chantier clos.
- Formations : terminé avec succès (worktree isolé recréé proprement après le reset). 20
fichiers, 0 erreur TypeScript, +4 routes confirmées (244→248). Fusionné dans
main(merge commit, aucun conflit). - Accompagnements : terminé avec succès — a bien commité son travail (
7c6132b) sur sa branche avant de rendre la main, checkout principal propre à la reprise. 39 fichiers (5 entités : Accompagnement, AppuiAlimentaire, SoutienPsychologique, PriseEnChargeSanitaire, SeanceAlphabetisation). Fusionné dansmain(merge commit, aucun conflit). Vérification post-fusion surmainavec 3 modules déjà intégrés :tsc --noEmit0 erreur, serveur démarré, 260 routes.
2026-07-09 07:35 — Correction post-clôture : peutModifier() trop permissif¶
Bernard a précisé la règle métier après clôture : les données de mise en œuvre (celles qui alimentent le calcul des indicateurs) ne doivent être modifiables que par l'agent de terrain qui les a saisies — ni le MEAL (communal ou national) ni l'ADMIN/SUPER_ADMIN n'ont de droit d'écriture, seulement lecture/validation/demande de correction. La conception d'origine (et son implémentation) donnaient à tort un accès en modification à MEAL_COMMUNAL (sa commune), MEAL_NATIONAL et ADMIN/SUPER_ADMIN.
Corrigé : ServiceAutorisationDonnees.peutModifier() (source unique, propagée automatiquement à
tous les modules qui l'utilisent) + verrouillage visuel frontend (EnfantsPage.tsx, désormais basé
sur enfant.idUtilisateur !== user?.id, plus sur le rôle). peutValider() inchangé — le MEAL
valide/invalide toujours normalement.
Vérifié par script ad hoc (supprimé après usage) : seul l'auteur peut modifier tant que
EN_ATTENTE/A_CORRIGER ; MEAL et ADMIN refusés dans tous les cas ; personne ne peut modifier un
enregistrement VALIDE. tsc --noEmit 0 erreur backend + frontend, serveur démarré (280 routes).
Documentation de conception mise à jour en conséquence.
2026-07-09 09:25 — Frontend branché sur les 17 entités restantes¶
Suite à la demande de Bernard, les composants génériques (jusque-là intégrés seulement sur Enfants) ont été branchés sur tous les modules restants : Accompagnements (5 entités, fait directement), puis 4 agents en parallèle (worktrees isolés) pour Formations+Sensibilisation, Insertion (5), Mobilisation (5), Pilotage/EtudeDiagnostique.
- 3 agents sur 4 ont correctement détecté que leur worktree était basé sur un commit obsolète et
ont fast-forward-mergé
mainavant de travailler — fusion propre pour ces trois. - 1 agent (Mobilisation) a travaillé sur une base très obsolète (avant même le début de
l'étape 4 du chantier backend) sans le détecter, et a donc réinventé en double
StatutValidationBadge/ValidationActionsavec une implémentation plus faible (validation du commentaire non appliquée côté client, appel direct àapiClientau lieu du hook partagé) tout en affirmant à tort que le backend Mobilisation n'avait pas encore ses routes de validation (fausse prémisse — vérifiée et infirmée avant fusion). Correction : seuls les fichiers spécifiques à Mobilisation (dtos.ts+MobilisationPage.tsx) ont été récupérés et réappliqués sur les composants canoniques déjà en place ; les doublons n'ont pas été fusionnés.
Toutes les 18 entités du workflow de validation ont désormais leur intégration frontend complète (badge + actions Valider/Demander correction + verrouillage du bouton Modifier réservé à l'auteur) : Enfants, Accompagnements+4 volets, FormationSensibilisation, SupportCommunication, ParcoursInsertion+4 événements, ComiteVillageois/ReunionComite/CadreConcertation/ SessionConcertation/SessionParoleJeunes, EtudeDiagnostique.
Vérification finale combinée : tsc --noEmit 0 erreur (backend + frontend), npm run build
frontend réussi, serveur backend démarré (280 routes). Toujours non vérifié : test interactif
en navigateur (pas d'outil d'automatisation disponible dans cet environnement).