Aller au contenu principal

ENG-001.1 — Rapport d'audit DMV Core

MissionENG-001.1 — Audit DMV Core
EpicEPIC-001 — Restructuration de DMV Core
StatutRapport produit
PérimètreObservation et documentation uniquement
Code applicatifAucun changement

Synthèse exécutive

DMV Core dispose déjà d'une structure modulaire nette dans api/app/Modules, avec 17 modules métier ou techniques identifiés. Cette structure est une base exploitable pour la migration cible, mais elle ne garantit pas encore les frontières de Bounded Contexts définies par l'ADR-014.

Les principaux écarts sont :

  • ownership de données non respecté sur plusieurs tables métier ;
  • dépendances directes entre modules via modèles internes, services internes ou accès DB::table ;
  • absence d'événements métier explicites ;
  • responsabilités municipales fragmentées entre Mairie et Territory ;
  • couche Admin très couplée aux tables métier ;
  • effets transverses synchrones vers Rewards, Monetization, Actor et Publication.

Conclusion : la restructuration peut être engagée de manière incrémentale, sans réécriture globale, mais l'audit confirme que le backend n'est pas encore conforme à l'architecture cible.

Références analysées

SourceRôle
dmv-docs/docs/decisions/ADR-014-dmv-core-bounded-contexts.mdRègles d'ownership, contrats, événements et dépendances autorisées
dmv-docs/docs/06-architecture/28-dmv-core-bounded-context-map.mdCartographie cible et constats d'architecture
dmv-docs/docs/06-architecture/30-dmv-core-migration-roadmap.mdRoadmap de migration cible DMV Core
api/app/ModulesImplémentation réelle de DMV Core
api/app/Modules/*/Routes/api.phpInterfaces HTTP exposées
api/app/Modules/*/Services/*.phpLogique applicative et dépendances
api/app/Modules/*/Models/*.phpOwnership implicite des tables

1. Cartographie des modules

ModuleÉtat codeResponsabilité observéeAPI exposéeDonnées principalesDépendances notables
AI4 modèles, 7 services, 1 contrôleurQuotas IA, prompts, cache, usagesOuiai_cache, ai_prompts, ai_usage_logs, ai_user_quotasLit Monetization pour quotas et boosts
Actor15 modèles, 6 services, 5 contrôleursIdentité organisationnelle, collaborateurs, modules, tags, XP localOuiacteurs, user_acteurs, acteur_collaborateurs, acteur_modules, documents, tagsÉcrit Mairie et Monetization ; appelle Rewards
Admin2 modèles, 12 services, 24 contrôleursBackoffice, supervision, imports, modération, interventions manuellesOuiimport_runs, import_sources, accès multi-tablesÉcrit directement Actor, Publication, Monetization, Community, Territory
Analytics0 modèle, 1 service, 1 contrôleurAgrégats et statistiquesOuiLecture multi-tablesLit Monetization et autres tables
AssoSuite5 modèles, 6 services, 4 contrôleursMembres, projets, cotisations d'associationOuiassosuite_*Lit Actor, utilise Settings
Chat3 modèles, 1 service, 1 contrôleurRooms, messages, accusés de lectureOuichat_rooms, chat_messages, chat_read_receiptsFaible couplage observé
Community5 modèles, 2 services, 2 contrôleursContributeurs, groupes, favorisOuicontributors, groupes, groupe_membres, contributor_favorisUtilise modèles Actor pour tags ; logique d'autorisation locale
Identity2 modèles, 2 services, 1 contrôleurProfils utilisateurs et rôles globauxOuiprofiles, users_rolesFaible couplage observé
Import0 modèle, 1 service, 0 contrôleurConnecteurs d'import et création de publicationsNonUtilise import_*, publicationsDépend d'Admin et écrit Publication
Mairie2 modèles, 2 services, 4 contrôleursAlertes/services mairie et données municipalesOuimairie_alertes, mairie_services, commune_*Écrit Territory ; appelle Publication et Actor
Monetization7 modèles, 6 services, 3 contrôleursPlans, abonnements, boosts, StripeOuiactor_subscriptions, subscription_plans, boosts, boost_catalog, subscription_logsÉcrit Actor et Publication ; appelle AssoSuite
PlayLoop5 modèles, 2 services, 2 contrôleursCampagnes, devices, playlists, médiasOuiplayloop_*Lit Publication
Publication4 modèles, 2 services, 2 contrôleursPublications, modération, rapportsOuipublications, publication_communes, publication_reports, type_publicationsLit Actor/Community ; appelle Actor XP et Rewards
Ranking0 modèle, 1 service, 0 contrôleurClassements calculésNonLecture app_settings, publicationsLit Settings directement
Rewards3 modèles, 2 services, 1 contrôleurRègles, événements d'activité, récompensesOuiactor_activity_events, reward_rules, reward_grantsÉcrit boosts Monetization
Settings3 modèles, 2 services, 1 contrôleurParamètres applicatifs et ongletsOuiapp_settings, feature_tabs, feature_tab_overridesService lu par autres modules
Territory9 modèles, 10 services, 1 contrôleurCommunes, géocodage, données territoriales et référentielsOuicommunes, commune_elus, commune_collectes, commune_infos, commune_defibrillateursÉcrit Actor et données municipales

2. Bounded Contexts

Context cibleÉtat actuelÉtat ciblePriorité
IdentityPrésent, globalement isoléSession, profil, rôles bruts uniquementP2
ActorPrésent mais mélange organisation, XP local, abonnements initiaux et alertes mairieIdentité organisationnelle, rôles acteur, collaborateurs, claimsP0
TerritoryPrésent mais écrit Actor et données municipalesDonnées strictement territoriales : commune, INSEE, géo, identité territorialeP0
Municipal ManagementFragmenté entre Mairie et TerritoryServices municipaux, élus, collectes, alertes, infos pratiquesP0
CommunityPrésent mais autorisation et tags dépendent partiellement d'autres contextesContributeurs, groupes, favoris, droits communautairesP1
PublicationPrésent mais déclenche Rewards/XP synchrones et lit Community/Actor directementCycle éditorial, modération, publication, signalementsP0
MonetizationPrésent mais modifie Actor et PublicationPlans, abonnements, boosts, billing, transactionsP0
RewardsPrésent mais crée des boosts Monetization directementRègles, grants, calculs de récompense à partir d'événementsP0
AssoSuitePrésent, plutôt isoléContexte applicatif ou app dédiéeP2
PlayLoopPrésent, plutôt isoléContexte applicatif ou app dédiéeP2
Authorization Platform ServicePartiellement présent via ActorAccessService, dupliqué dans Policies/MiddlewareService transverse unique d'autorisationP1
AI Platform ServicePrésent mais lit Monetization directementService platform consommant des contrats/quota explicitesP1
Settings Platform ServicePrésentService de configuration consommé via contratP2
Import AdapterPrésent mais dépend d'Admin et écrit PublicationAdapter d'import qui délègue aux contrats des contextes propriétairesP1
Admin AdapterPrésent mais contient des écritures métier directesAdapter backoffice sans ownership métierP0
Analytics Platform ServicePrésent en lectureRead models / agrégats sans write métierP2
Ranking Platform ServicePrésent sans API, lit tables directementCalcul de classement isolé sur contrats/read modelsP2

3. Ownership des données

TableOwner cibleLectures externes observéesÉcritures externes observéesConforme
profilesIdentityAdmin, PoliciesAdmin claims met à jour certains profilsNon
users_rolesIdentityIdentity/AdminNon significatif observéOui
acteursActorMairie, Territory, Monetization, Admin, Rewards, Analytics, AssoSuiteTerritory refresh, Monetization Stripe/badges, Admin actionsNon
user_acteursActorActor/AdminActorOui partiel
acteur_collaborateursActorActorActorOui
acteur_modulesActorActorActorOui
acteur_permissionsActorActor/AuthorizationActorOui
acteur_rolesActorActor/AuthorizationActorOui
acteur_tagsActorActor/CommunityActorPartiel
tagsActorCommunityActorPartiel
documentsActor ou Files Platform ServiceActorActorPartiel
claimsActorAdminActor/AdminNon
acteur_xp_eventsActor ou RewardsActor/PublicationPublication via Actor servicePartiel
communesTerritoryMairie, Admin, Actor, ImportMairie met à jour description/image ; Admin écrit communesNon
commune_elusMunicipal ManagementTerritory, MairieTerritory refresh et MairieNon
commune_collectesMunicipal ManagementTerritory, MairieMairiePartiel
commune_infosMunicipal ManagementTerritory, MairieTerritory refresh et MairieNon
commune_sirene_snapshotsTerritoryTerritoryTerritoryOui
commune_defibrillateursTerritoryTerritoryTerritoryOui
defibrillateurs_catalogueTerritoryTerritoryTerritoryOui
mairie_alertesMunicipal ManagementActor/MairieActor controller et MairieNon
mairie_servicesMunicipal ManagementMairieMairieOui
contributorsCommunityPublication, Admin, PoliciesAdmin actor service modifie can_publishNon
contributor_favorisCommunityCommunityCommunityOui
groupesCommunityCommunity/AdminCommunity/AdminPartiel
groupe_membresCommunityCommunity/AdminCommunity/AdminPartiel
groupe_tagsCommunityCommunityCommunityOui
publicationsPublicationImport, Admin, Mairie, PlayLoop, Rewards, Ranking, AnalyticsImport, Admin, Monetization boostsNon
publication_communesPublicationPublication/MairiePublicationPartiel
publication_reportsPublicationPublication/AdminPublication/AdminPartiel
type_publicationsPublicationPublication/Import/AdminPublication/AdminPartiel
actor_subscriptionsMonetizationActor, AI, Admin, MonetizationActor auto-subscribe, Admin subscription actionsNon
subscription_plansMonetizationAI/Admin/MonetizationMonetization/AdminPartiel
subscription_logsMonetizationAdmin/MonetizationAdmin/MonetizationPartiel
boost_catalogMonetizationRewards/Admin/AIMonetization/AdminPartiel
boostsMonetizationRewards/Admin/AIRewards and Admin create boostsNon
boost_purchasesMonetizationMonetizationMonetizationOui
push_usageMonetization ou NotificationAnalytics/MonetizationMonetizationPartiel
reward_rulesRewardsRewards/AdminRewards/AdminPartiel
reward_grantsRewardsRewardsRewardsOui
actor_activity_eventsRewardsRewardsRewardsOui
ai_cacheAIAIAIOui
ai_promptsAIAIAIOui
ai_usage_logsAIAIAIOui
ai_user_quotasAIAI/AdminAIPartiel
app_settingsSettingsRanking/SettingsSettings/AdminPartiel
feature_tabsSettingsSettingsSettingsOui
feature_tab_overridesSettingsSettingsSettingsOui
import_sourcesImport ou Admin AdapterImport/AdminAdmin/ImportPartiel
import_runsImport ou Admin AdapterImport/AdminImportPartiel
assosuite_membersAssoSuiteAssoSuiteAssoSuiteOui
assosuite_projectsAssoSuiteAssoSuiteAssoSuiteOui
assosuite_cotisationsAssoSuiteAssoSuite/Monetization webhookAssoSuite via Monetization webhook delegationPartiel
assosuite_cotisation_plansAssoSuiteAssoSuiteAssoSuiteOui
assosuite_invitationsAssoSuiteAssoSuiteAssoSuiteOui
chat_roomsChatChatChatOui
chat_messagesChatChatChatOui
chat_read_receiptsChatChatChatOui
playloop_campaignsPlayLoopPlayLoopPlayLoopOui
playloop_devicesPlayLoopPlayLoopPlayLoopOui
playloop_mediaPlayLoopPlayLoopPlayLoopOui
playloop_playlistsPlayLoopPlayLoopPlayLoopOui
playloop_playlist_itemsPlayLoopPlayLoopPlayLoopOui

4. Dépendances

DépendanceClassificationJustification
Actor → Mairie modelÀ supprimerActeurModulesController importe MairieAlerte et écrit mairie_alertes depuis Actor (api/app/Modules/Actor/Controllers/ActeurModulesController.php:11, api/app/Modules/Actor/Controllers/ActeurModulesController.php:236).
Actor → Monetization tableÀ supprimerActeurWriteService insère actor_subscriptions lors de l'auto-subscribe (api/app/Modules/Actor/Services/ActeurWriteService.php:386).
Actor → Rewards serviceÀ remplacer par eventActeurWriteService appelle RewardEngineService::recordEvent après mise à jour d'acteur (api/app/Modules/Actor/Services/ActeurWriteService.php:155).
Publication → Actor/Rewards servicesÀ remplacer par eventPublicationWriteService appelle Actor XP et Rewards de manière synchrone (api/app/Modules/Publication/Services/PublicationWriteService.php:120, api/app/Modules/Publication/Services/PublicationWriteService.php:139).
Mairie → Territory tablesÀ supprimerMairieWriteService met à jour communes et écrit commune_* (api/app/Modules/Mairie/Services/MairieWriteService.php:225, api/app/Modules/Mairie/Services/MairieWriteService.php:233).
Territory → Actor tablesÀ supprimerCommuneMairieDataRefreshService met à jour acteurs depuis Territory (api/app/Modules/Territory/Services/CommuneMairieDataRefreshService.php:84, api/app/Modules/Territory/Services/CommuneMairieDataRefreshService.php:145).
Territory → données municipalesÀ déplacerTerritory écrit commune_elus et commune_infos, qui relèvent du futur Municipal Management (api/app/Modules/Territory/Services/CommuneMairieDataRefreshService.php:232, api/app/Modules/Territory/Services/CommuneMairieDataRefreshService.php:312).
Monetization → Actor/Publication tablesÀ supprimer ou contractualiserStripe Connect écrit acteurs.stripe_account_id; les boosts modifient acteurs.featured_until et publications.featured_until (api/app/Modules/Monetization/Services/MonetizationWriteService.php:62, api/app/Modules/Monetization/Services/BoostUsageService.php:210, api/app/Modules/Monetization/Services/BoostUsageService.php:234).
Rewards → Monetization tablesÀ supprimerRewards crée directement des lignes boosts (api/app/Modules/Rewards/Services/RewardEngineService.php:284).
Import → Admin modelsÀ corrigerImportRunnerService dépend de modèles Admin pour ImportRun et ImportSource (api/app/Modules/Import/Services/ImportRunnerService.php:7).
Import → Publication tableÀ remplacer par contrat PublicationImportRunnerService lit, met à jour et crée des publications directement (api/app/Modules/Import/Services/ImportRunnerService.php:154, api/app/Modules/Import/Services/ImportRunnerService.php:172, api/app/Modules/Import/Services/ImportRunnerService.php:189).
Admin → tables métierÀ supprimer progressivementAdmin modifie directement publications, actor_subscriptions, boosts, acteurs, contributors (api/app/Modules/Admin/Services/AdminPublicationService.php:241, api/app/Modules/Admin/Services/AdminSubscriptionWriteService.php:30, api/app/Modules/Admin/Services/AdminSubscriptionWriteService.php:84, api/app/Modules/Admin/Services/AdminActeurService.php:115, api/app/Modules/Admin/Services/AdminActeurService.php:204).
Ranking → Settings tableÀ contractualiserRanking lit app_settings directement au lieu de passer par SettingsReadService.
PlayLoop → Publication read serviceAcceptable à court termeLecture orientée projection ; à formaliser comme contrat/read model.
Analytics → tables métierAcceptable en lectureRead-only observé ; doit rester agrégat sans write métier.

5. Événements métier

ÉlémentÉtat actuelÉcart cible
Classes d'événements métierAbsentes dans api/app/Modules/*/EventsAucun événement métier typé par contexte
Listeners métierAbsents dans api/app/Modules/*/ListenersAucun découplage producteur/consommateur
RewardsRewardEngineService::recordEvent écrit actor_activity_events puis évalue immédiatement les règlesJournal applicatif synchrone, pas un événement inter-contextes
Actor XPPublication et Actor appellent directement ActorXpServiceEffet externe non découplé
Boosts récompenseRewards crée directement des boostsDevrait publier une intention ou appeler un contrat Monetization
ImportsImport écrit Publication directementDevrait déléguer à un contrat Publication

Événements manquants à introduire progressivement :

  • ActorCreated
  • ActorUpdated
  • ActorClaimSubmitted
  • PublicationCreated
  • PublicationPublished
  • PublicationModerated
  • SubscriptionChanged
  • BoostPurchased
  • BoostConsumed
  • RewardGranted
  • MunicipalDataUpdated

6. API

ModuleÉtat APICohérence
AIAPI concentrée dans un contrôleurCohérente, dépendances quota à contractualiser
ActorAPI riche et utileCertaines routes gèrent des données Mairie et Monetization hors ownership
AdminAPI très largeFonctionne comme adapter mais contient des écritures métier directes
AnalyticsAPI lectureCohérente si elle reste read-only
AssoSuiteAPI isoléeCohérente, dépendances Actor/Settings à formaliser
ChatAPI isoléeCohérente
CommunityAPI cohérenteAutorisation locale à rapprocher du Platform Service
IdentityAPI limitéeCohérente
ImportPas d'API moduleOrchestration technique pilotée depuis Admin ; ownership ambigu
MairieAPI présenteMélange données mairie, Publication et Territory
MonetizationAPI présenteCohérente côté billing, mais effets sur Actor/Publication hors ownership
PlayLoopAPI présenteCohérente, lecture Publication à formaliser
PublicationAPI présenteCohérente fonctionnellement, effets externes synchrones à découpler
RankingPas d'APIService interne acceptable, dépendance Settings directe à corriger
RewardsAPI minimaleCohérente partiellement, écriture Monetization à supprimer
SettingsAPI présenteCohérente
TerritoryAPI présenteMélange territoire strict et rafraîchissement mairie/acteur

7. Platform Services

Service cibleÉtat actuelCiblePriorité
AuthorizationActorAccessService, Policies et Middleware coexistentUn service unique consommé par les contextesP1
NotificationPas de service platform structuré observé dans DMV CoreService dédié si notifications backend nécessairesP2
SearchPas de service platform isolé observéContrat Search ou read model si recherche transverseP2
StorageDocuments gérés côté Actor ; pas de Files Platform Service expliciteIsoler fichiers/documents si usage transverse confirméP2
GeocodingServices dans TerritoryAcceptable comme platform/adapter territorialP2
FilesPas de service platform expliciteÀ extraire uniquement si plusieurs contextes écrivent/lisent des fichiersP2
SettingsModule dédié existantÀ consommer via service plutôt que table directeP2
AnalyticsService lecture existantGarder read-only et hors ownership métierP2
RankingService existantIsoler les inputs via contrats/read modelsP2
ImportService existant mais couplé Admin/PublicationAdapter qui délègue aux contextes propriétairesP1

8. Violations architecturales

ÉlémentGravitéRecommandation
ActeurModulesController écrit mairie_alertes via modèle MairieP0Déplacer l'écriture derrière un contrat Municipal Management/Mairie.
ActeurWriteService crée actor_subscriptionsP0Remplacer par contrat Monetization ensureFreeSubscription ou event ActorCreated.
PublicationWriteService appelle Rewards et Actor XPP0Publier des événements métier consommés par Rewards et Actor.
MairieWriteService écrit communes et commune_*P0Séparer données Territory strictes et Municipal Management.
CommuneMairieDataRefreshService écrit acteursP0Remplacer par contrat Actor ou event de rapprochement mairie-acteur.
MonetizationWriteService écrit acteurs.stripe_account_idP0Déplacer la donnée Stripe owner vers Monetization ou exposer un contrat Actor explicite.
BoostUsageService écrit acteurs.featured_until et publications.featured_untilP0Remplacer par contrats Actor/Publication ou effets consommés par événements.
RewardEngineService crée des boostsP0Rewards doit émettre une récompense ; Monetization matérialise le boost.
ImportRunnerService écrit publicationsP1Déléguer la création/mise à jour à PublicationWriteService ou à un contrat d'import Publication.
AdminPublicationService modifie directement publicationsP0Admin doit appeler les use cases Publication.
AdminSubscriptionWriteService modifie directement MonetizationP1Admin doit appeler les use cases Monetization.
AdminActeurService modifie acteurs et contributorsP1Admin doit appeler Actor/Community via contrats.
CommunityPolicy lit contributors directementP2Déplacer vers Authorization Platform Service ou CommunityReadService.
PublicationPolicy inspecte la requête HTTP pour choisir les permissionsP1Éviter que la policy dépende de la forme de la requête ; déplacer en use case/authorization service.
Absence d'événements métier typésP0Introduire une première famille d'événements sur Actor, Publication, Monetization, Rewards.

9. Dette technique

DetteLocalisationImpact
TODO conversion boosts → crédits IAapi/app/Modules/AI/Services/AIQuotaService.php:148, api/app/Modules/AI/Services/AIQuotaService.php:160Règle de monétisation/IA incomplète.
Fallback legacy ownerapi/app/Modules/Actor/DTOs/ActeurCollaborateurDTO.php:46, api/app/Modules/Actor/DTOs/ActeurCollaborateurDTO.php:56Compatibilité historique à isoler avant durcissement.
Rôle legacy profilapi/app/Modules/Identity/Models/Profile.php:26Ambiguïté entre Identity et Authorization.
Fallback legacy Mairieapi/app/Modules/Mairie/Middleware/EnsureCommuneManager.php:23Autorisation dispersée.
Imports legacyapi/app/Modules/Admin/Routes/api.php:175, api/app/Modules/Admin/Models/ImportRun.php:14Import rattaché à Admin au lieu d'un adapter dédié.
Controllers avec logique métierapi/app/Modules/Actor/Controllers/ActeurModulesController.php:225Controller non limité à l'adaptation HTTP.
Services Admin contenant règles métierapi/app/Modules/Admin/Services/AdminPublicationService.php:252Backoffice devient owner de règles métier.

10. Plan de migration en Pull Requests

PRObjectifFichiers concernésDépendancesCritères d'acceptationRisquesPriorité
PR-001Introduire les contrats inter-contextes minimauxNouveaux contrats dans modules propriétairesAucuneAucun changement fonctionnel ; services existants compilentSur-abstraction si contrats trop largesP0
PR-002Découpler Actor → MonetizationActeurWriteService, service MonetizationPR-001Création acteur conserve abonnement free sans écriture directe Actor vers actor_subscriptionsRégression onboarding acteurP0
PR-003Découpler Actor → MairieActeurModulesController, Mairie/Municipal servicePR-001CRUD alertes mairie ne passe plus par modèle Mairie depuis ActorRégression Workspace mairieP0
PR-004Découper données municipales hors TerritoryCommuneMairieDataRefreshService, MairieWriteServicePR-001Territory n'écrit plus acteurs; responsabilités commune_* clarifiéesMigration délicate des imports INSEE/SIRENEP0
PR-005Introduire événements Publication/ActorPublicationWriteService, ActeurWriteService, Rewards/Actor listenersPR-001Publication et Actor ne déclenchent plus Rewards/XP en synchrone directOrdre d'exécution des effets secondairesP0
PR-006Découpler Rewards → MonetizationRewardEngineService, Monetization boost contractPR-001, PR-005Rewards ne crée plus boosts directementCompatibilité récompenses existantesP0
PR-007Découpler Boost effectsBoostUsageService, Actor/Publication contractsPR-001Monetization n'écrit plus acteurs.featured_until ni publications.featured_until directementRégression mise en avantP0
PR-008Transformer Admin en adapterServices Admin publication/acteur/subscription/claim/communePR-001 à PR-007Admin appelle use cases propriétaires ; plus d'écriture métier directe critiqueGros volume, découper par domaine si nécessaireP1
PR-009Découpler Import de Publication/AdminImportRunnerService, modèles Import, service PublicationPR-001Import ne dépend plus de modèles Admin et délègue à PublicationRégression imports existantsP1
PR-010Consolider Authorization Platform ServicePolicies, Middleware, ActorAccessServicePR-001Règles d'accès centralisées ; policies réduites à l'adaptationRisque de changement de droitsP1
PR-011Formaliser read models transversesAnalytics, Ranking, PlayLoop, AI quotasPR-001Lectures directes critiques remplacées par read services/contratsFaible si read-onlyP2
PR-012Nettoyer dette legacy/TODOAIQuota, DTO legacy, imports legacyPR précédentesTODO et fallbacks documentés ou supprimésFaibleP2

Score de conformité

AxeScoreArgument
Architecture68 %Modules présents et lisibles, mais frontières non garanties par contrats.
Bounded Contexts62 %Plusieurs contextes cible existent, mais Municipal Management est fragmenté et Admin/Import/Ranking restent ambigus.
Ownership48 %Nombreuses écritures cross-context sur acteurs, publications, actor_subscriptions, boosts, commune_*.
API72 %Routes par module cohérentes, mais certaines API exposent des responsabilités mélangées.
Events25 %Aucun événement métier typé ni listener inter-contexte ; effets synchrones dominants.
Platform Services45 %Settings et certains services existent, mais Authorization, Import, Search/Files/Notification ne sont pas structurés comme services platform.
Global55 %Base modulaire saine, mais conformité DDD/ADR encore insuffisante pour considérer la migration terminée.

Conclusion

La restructuration de DMV Core ne nécessite pas de réécriture globale. Le bon chemin est une migration incrémentale par ownership : contrats minimaux, suppression des écritures cross-context, puis événements métier.

Les P0 ne bloquent pas l'exploitation actuelle, mais bloquent la conformité à l'architecture cible. ENG-001.1 est donc terminé comme audit : la suite doit être exécutée via les PR proposées, en commençant par Actor, Publication, Monetization, Rewards, Territory/Mairie et Admin.