ENG-001.5J — Migration des infos pratiques vers Municipal Management
| Mission | ENG-001.5J — Préparer la migration des infos pratiques |
| Rattaché à | ENG-001.5 — Extraction de Municipal Management ; ENG-001.5 — Recalibrage roadmap ; ENG-001.5I — Rapport d'implémentation |
| Dépôt | dmv-docs |
| Type | Spécification documentaire — aucune implémentation |
| Code applicatif | Aucun changement |
| Statut | Préparation prête — décision 13.C résolue en faveur de Municipal Management |
Cette mission prépare ENG-001.5J sans modifier le code. Elle cartographie l'état réel de
commune_infos, documente tous les chemins de lecture et d'écriture, et formalise la décision
13.C désormais résolue sur commune_info_sections.
1. Objectif
Définir le périmètre exact de la migration des infos pratiques vers Municipal Management, en préservant :
- les routes existantes ;
- les payloads ;
- les validations observables ;
- les réponses JSON ;
- les comportements publics et workspace ;
- le rafraîchissement SIRENE existant.
2. État réel observé
2.1 Données concernées
commune_infos
Table observée :
idcommune_idsectionlabelvaleursubiconicon_colorhrefordrecreated_at
Aucune autre colonne métier confirmée n'a été trouvée dans le schéma actuel :
- pas de colonne de visibilité ;
- pas de
updated_at; - pas de lien SQL vers
commune_info_sections.
commune_info_sections
Voir l'audit dédié :
ENG-001.5J — Audit d'ownership de commune_info_sections.
2.2 Rôle métier constaté
commune_infosporte le contenu pratique par commune.commune_info_sectionsporte un catalogue global de rubriques, consommé uniquement par Admin.- la lecture publique
Territoryenrichit la sectionmairieavec des données Actor synthétiques ; elle n'est donc pas une simple projection brute decommune_infos.
3. Chemins de lecture et d'écriture
3.1 Lectures de commune_infos
Mairie
MairieReadService::listInfos(string $communeId)MairieCommuneController::indexInfos()- réponse :
['infos' => ...]
Admin
AdminCommuneInfoController::fullCommune()- lecture ordonnée par
section, puisordre - réponse agrégée contenant
sectionsetinfos_by_section
Territory / Public
TerritoryService::getCommuneInfos(string $communeId)TerritoryController- lecture ordonnée par
section, puisordre - fusion avec des infos synthétiques Actor pour la section
mairie
3.2 Écritures de commune_infos
Mairie
MairieWriteService :
createInfo()updateInfo()deleteInfo()
Caractéristiques observées :
- écriture directe SQL/Eloquent sur
commune_infos; - aucune validation Laravel dédiée dans la façade Mairie ;
- valeurs par défaut appliquées dans le service.
Admin
AdminCommuneInfoController :
storeInfo()updateInfo()destroyInfo()
Caractéristiques observées :
- validation Laravel explicite ;
- CRUD complet ;
- lecture de retour immédiate par
id.
Territory / SIRENE
CommuneMairieDataRefreshService :
refreshInfos()upsertInfo()
Caractéristiques observées :
- flux externe réel confirmé ;
- périmètre limité à la section
identite; - matching par triplet
commune_id + section + label; - mise à jour limitée principalement à
valeur.
3.3 Lectures de commune_info_sections
AdminCommuneInfoController::indexSections()AdminCommuneInfoController::fullCommune()
3.4 Écritures de commune_info_sections
AdminCommuneInfoController::storeSection()AdminCommuneInfoController::updateSection()AdminCommuneInfoController::destroySection()
3.5 Chemins confirmés
Les trois chemins attendus sont bien présents :
- Mairie
- Admin
- Territory / SIRENE
Aucun quatrième chemin n'a été confirmé dans les imports, jobs ou commandes.
4. Consommateurs
4.1 dmv-workspace
Consommateurs confirmés :
services/mairie/infos.ts- pages workspace mairie/commune liées aux infos pratiques
Comportement observé :
- CRUD complet sur les endpoints Mairie ;
- sections reconstruites à partir des items
commune_infos; - aucun usage direct de
commune_info_sections.
4.2 dmv-public
Consommateurs confirmés :
app/components/VilleDrawer.tsxapp/[commune]/acteur/[slug]/ActorsClient.tsx- composants publics liés au drawer commune
Comportement observé :
- lecture publique
/communes/{id}/infos; - sections reconstruites côté frontend ;
- filtres spécifiques pour éviter les doublons de données mairie déjà portées par Actor ;
- aucun usage direct de
commune_info_sections.
4.3 dmv-backoffice
Consommateur confirmé :
src/pages/Communes.jsx
Comportement observé :
- consommation de
sections+infos_by_section; - CRUD complet sur
/admin/communes/{id}/infos; - CRUD complet sur
/admin/commune-sections; - mélange entre catalogue officiel et sections présentes dans les données.
5. Ownership de commune_infos
Constat
commune_infos relève du métier municipal :
- données pratiques par commune ;
- éditées par Mairie ;
- éditées par Admin ;
- partiellement réconciliées depuis une source externe dans Territory ;
- lues publiquement via Territory.
Ownership cible
Municipal Management reste l'owner cible cohérent de commune_infos.
Conséquence
Mairie, Admin et Territory doivent devenir des adaptateurs :
- Mairie pour la façade métier protégée ;
- Admin pour la façade backoffice ;
- Territory pour la réconciliation externe et la lecture publique.
6. Analyse de commune_info_sections
La décision 13.C est détaillée dans le document dédié :
ENG-001.5J — Audit d'ownership de commune_info_sections.
Résumé opérationnel
- ce n'est pas un simple détail frontend ;
- ce n'est pas non plus une configuration transverse prouvée ;
- c'est un référentiel global de rubriques des infos pratiques ;
- il peut exister indépendamment de
commune_infos; - il est modifié uniquement par Admin ;
- il n'est pas consommé directement par Workspace/Public.
7. Décision 13.C résolue
Question
Qui possède commune_info_sections ?
Options évaluées
- A — Municipal Management
- B — Settings / Platform Service
- C — Séparation référentiel / affectation
Décision retenue
Option A — commune_info_sections appartient à Municipal Management, pour les raisons
suivantes :
- meilleure cohérence avec
commune_infos; - migration la plus simple et la plus réversible ;
- aucun consommateur transverse réel observé ;
- aucun besoin fonctionnel ne justifie un second contexte.
Effet sur ENG-001.5J
commune_info_sectionsentre dans le périmètre métier de Municipal Management ;- J1 couvre donc la lecture, les DTO et l'ownership de
commune_infoset decommune_info_sections; - J2 couvre les écritures Mairie/Admin des infos et des sections ;
- J3 reste limité à la réconciliation Territory/SIRENE de
commune_infos.
8. Contrats existants
MunicipalManagementReader
Capacité observée :
getInfos(string $communeId): Collection
État :
- signature déjà présente ;
- implémentation encore absente ou non active pour les infos pratiques dans l'état documenté préparatoire.
MunicipalManagementWriter
Capacités observées :
createInfo(string $communeId, array $data): MunicipalInfoDTOupdateInfo(string $communeId, string $infoId, array $data): MunicipalInfoDTOdeleteInfo(string $communeId, string $infoId): void
État :
- signatures présentes ;
- ne couvrent pas
commune_info_sections; - ne couvrent pas explicitement la réconciliation externe.
9. Contrats potentiellement manquants
9.1 Lecture des sections
Besoin :
Admin consomme un catalogue de sections distinct des infos.
Signature neutre proposée :
MunicipalManagementReader::getInfoSections(): Collection
Ownership visé :
- Municipal Management si l'option A est retenue ;
- sinon contexte à arbitrer.
9.2 Écriture des sections
Besoin :
Admin crée, modifie et supprime commune_info_sections.
Signatures neutres proposées :
MunicipalManagementWriter::createInfoSection(array $data): MunicipalInfoSectionDTO
MunicipalManagementWriter::updateInfoSection(string $sectionId, array $data): MunicipalInfoSectionDTO
MunicipalManagementWriter::deleteInfoSection(string $sectionId): void
Impact :
- utile uniquement si l'option A est validée ;
- sinon ces signatures n'appartiennent pas à Municipal Management.
9.3 Réconciliation externe des infos
Besoin :
Le flux SIRENE existe réellement pour la section identite.
Signature neutre proposée :
MunicipalManagementWriter::reconcileInfos(
string $communeId,
MunicipalInfosReconciliationDTO $data,
): MunicipalInfosReconciliationResultDTO
Ownership visé :
- Municipal Management pour la logique de matching et de mise à jour ;
- Territory conserve l'extraction externe et la construction du DTO.
9.4 Réordonnancement
Constat :
ordreexiste surcommune_infos;- aucun endpoint dédié de reorder n'est observé ;
- l'ordre passe aujourd'hui par création/mise à jour standard.
Conclusion :
Pas de contrat de reorder dédié requis tant que le comportement observable reste inchangé.
10. Périmètre inclus
Si ENG-001.5J est lancée après arbitrage :
- lecture
commune_infos; - écriture
commune_infosdepuis Mairie ; - écriture
commune_infosdepuis Admin ; - lecture publique conservée via Territory ;
- réconciliation SIRENE des infos ;
commune_info_sections, la décision 13.C étant désormais validée en faveur de Municipal Management.
11. Hors périmètre
Restent explicitement hors périmètre :
communes.descriptioncommunes.image_urlcommunes.site_webcommunes.email_contactcommunes.telephone- tout changement frontend
- toute migration SQL non strictement nécessaire à une future implémentation validée
- toute modification d'ADR ou de RFC
- toute fonctionnalité nouvelle sur les infos pratiques
12. Découpage proposé
Recommandation
Découper ENG-001.5J en trois PR logiques, plus sûres qu'une seule PR massive.
J1 — Fondation et lecture
- confirmer l'ownership retenu ;
- compléter DTO/contrats nécessaires ;
- implémenter lecture
commune_infos; - implémenter lecture
commune_info_sectionsseulement si l'option A est validée ; - brancher Mairie/Admin en lecture sans changer les réponses.
J2 — Écritures Mairie et Admin
- création ;
- modification ;
- suppression ;
- conservation de
ordre; - délégation Mairie et Admin vers le contrat.
J3 — Réconciliation Territory / SIRENE
- déplacer la logique de matching/upsert de
refreshInfos(); - conserver Territory comme adaptateur d'entrée externe ;
- garder les compteurs et le comportement historiques si des compteurs sont introduits.
Pourquoi ce découpage
- chaque PR reste indépendante ;
- chaque PR est testable ;
- chaque PR est réversible ;
- la décision 13.C est déjà levée avant les écritures ;
- le flux externe SIRENE est isolé dans la PR la plus risquée.
13. Risques
- divergence actuelle de validation entre Mairie, Admin et Territory ;
- lecture publique enrichie par Actor sur la section
mairie; - absence de lien SQL fort entre
commune_infos.sectionetcommune_info_sections.slug; - risque de sur-architecture si 13.C est envoyée vers Settings sans besoin prouvé ;
- risque de régression backoffice si le catalogue de sections n'est pas migré avec son vrai owner.
14. Tests attendus
Une future implémentation devra au minimum couvrir :
- lecture Mairie inchangée ;
- lecture Admin
fullCommune()inchangée ; - lecture publique Territory inchangée ;
- CRUD Mairie inchangé ;
- CRUD Admin inchangé ;
- isolation inter-communes ;
- ordre conservé ;
- section conservée ;
- compatibilité catalogue
sections+infos_by_section; - réconciliation SIRENE idempotente sur la section
identite; - garde-fous architecturaux empêchant toute écriture directe restante hors Municipal Management.
15. Critères d'acceptation
Pour considérer ENG-001.5J implémentée plus tard :
- un seul owner applicatif de
commune_infos; - zéro écriture directe restante depuis Mairie, Admin ou Territory ;
- réponses API inchangées ;
- routes inchangées ;
- payloads et validations observables inchangés ;
- aucun frontend à modifier ;
- décision 13.C reflétée explicitement dans l'ownership et les contrats.
16. Définition de Done
ENG-001.5J sera considérée terminée quand :
- la décision 13.C restera appliquée explicitement ;
- l'ownership choisi sera reflété dans les contrats et services ;
- tous les chemins d'écriture auront été unifiés ;
- les tests locaux et CI seront verts ;
- les garde-fous d'architecture empêcheront toute régression ;
- aucune modification hors périmètre n'aura été introduite.
17. Divergences et décisions requises
Divergences observées
- Mairie n'applique pas la même validation qu'Admin ;
- Territory écrit seulement une sous-partie (
identite) avec une logique d'upsert spécifique ; - Public ne consomme pas le catalogue de sections ;
- Admin consomme à la fois le catalogue et les sections réelles présentes dans les données.
Décisions requises
- Faut-il introduire un contrat de lecture/écriture des sections, l'ownership Municipal Management étant désormais acté ?
- Faut-il isoler la réconciliation SIRENE des infos dans une PR dédiée (recommandation : oui) ?
- Quelle règle de validation historique doit faire foi après unification quand Mairie et Admin divergent ?