Aller au contenu

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. idUtilisateur ajouté (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 push sans perte de données.
  • Service générique : IServiceAutorisationDonnees/ServiceAutorisationDonnees (singleton, comme logger). Suppression du middleware mort scopeCommune.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 sur Accompagnement/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 avec CalculateurFactories.ts du chantier précédent.
  • Module Enfants câblé en référence : routes /:id/valider et /:id/demander-correction, ModifierEnfantUseCase vérifie peutModifier() avant d'écrire et repasse automatiquement EN_ATTENTE si l'auteur corrige un enregistrement A_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, commit e92b0b5) 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 branche feature/accompagnements-validation-workflow directement 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 sur main dans 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 --noEmit 0 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é

  1. Schéma — enum StatutValidation + 4 champs sur 20 entités racines ; idUtilisateur sur les 4 tables de participation/présence et 7 modèles qui en manquaient.
  2. 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é.
  3. 2 bugs de sécurité corrigés : faille de contournement de scope sur Enfant.lister() ; restriction stricte au créateur retirée sur Accompagnement/MaitreCoranique (le MEAL voit désormais tout dans sa commune, pas seulement ses propres saisies).
  4. 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).
  5. Verrouillage en cascade des 4 tables filles (participation/présence) qui alimentent le calcul des indicateurs — 8 use cases d'écriture protégés.
  6. Traçabilité idUtilisateur ré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é.
  7. Frontend : composants transverses (StatutValidationBadge, ValidationActions, useValidationDonnee, validation.api.ts) intégrés en référence dans EnfantsPage.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é : idUtilisateur bien 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é idUtilisateur non 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é.
  • PersonneRessourceDTO ne remonte pas encore idUtilisateur dans 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.ts
  • BackEnd/src/shared/application/{interfaces/IValidationDonneeUseCase.ts,usecases/CreerValiderDonneeUseCase.ts,services/verifierParentModifiable.ts}
  • BackEnd/src/shared/interface-adapters/handlers/{ValiderDonneeHandler,DemanderCorrectionDonneeHandler}.ts
  • FrontEnd/src/shared/components/ui/{StatutValidationBadge,ValidationActions}.tsx
  • FrontEnd/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é dans main (merge commit, aucun conflit). Vérification post-fusion sur main avec 3 modules déjà intégrés : tsc --noEmit 0 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é main avant 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/ValidationActions avec une implémentation plus faible (validation du commentaire non appliquée côté client, appel direct à apiClient au 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).

Liens connexes