Une application française doit accueillir une filiale belge. Le formulaire reçoit un champ « pays », puis les premiers tests révèlent que les numéros de facture, les droits, les modèles de documents et les exports comptables supposent tous une seule société. Une commande peut être affichée en Belgique tout en restant facturée par la France, et aucun identifiant ne permet de prouver le propriétaire réel du dossier.
Le symptôme n’est pas seulement une accumulation de conditions. Les données historiques n’ont aucun contexte, les administrateurs voient tout, les batchs utilisent un fuseau implicite et les intégrations envoient vers un établissement fixe. Chaque correction locale augmente le risque de fuite, la charge support et le coût caché de la prochaine entité.
Le vrai enjeu est de transformer les hypothèses invisibles en concepts versionnés sans interrompre le produit existant. La reprise doit attribuer chaque donnée, décision et intégration à un périmètre, migrer l’historique avec une balance et ouvrir le nouveau chemin par tranches. Ajouter une abstraction partout avant d’avoir un cas réel créerait une plateforme théorique tout aussi difficile à exploiter.
Une démarche de développement web sur mesure permet de reprendre le modèle, les droits, les workflows et les flux dans un ordre contrôlé. Ce guide détaille les preuves attendues, les arbitrages et le plan de bascule.
Inventorier les hypothèses mono-pays
Chercher dans les décisions, pas seulement dans le code
Reconstituez cinq parcours : créer un utilisateur, ouvrir un client, accepter une commande, produire un document et traiter un incident. Pour chaque étape, demandez qui possède l’objet, quelle règle s’applique, dans quelle langue, devise, zone horaire et juridiction, puis où la preuve est conservée. Une valeur codée en dur est visible ; une réunion qui suppose « le siège décide toujours » l’est moins.
Inspectez configuration, base, files, tâches planifiées, modèles PDF, exports, caches, journaux et procédures support. Cherchez les identifiants de société absents, les jointures sans périmètre, les formats locaux et les comptes techniques partagés. Les noms génériques comme default_company ou main_currency signalent une décision devenue implicite.
Qualifier chaque hypothèse
Classez-la comme invariant groupe, valeur locale, relation entre entités, contrainte historique ou inconnue. Associez un dossier et un propriétaire. « Toutes les commandes utilisent l’euro » peut devenir une valeur de contrat ; « un client appartient à une société » peut être faux pour les comptes groupe. La modélisation part des cas contradictoires.
Définir entité, organisation et périmètre
Une entité métier n’est ni un pays ni un tenant d’identité. Elle peut représenter une société légale, une filiale opératoire, une marque ou un établissement selon les décisions à isoler. Nommez le concept avec ses responsabilités : facturer, employer, posséder un contrat ou traiter une commande. Un pays reste un attribut lorsque plusieurs sociétés y opèrent.
Le modèle peut contenir organisation, entité légale, unité opérationnelle et relation d’accès. Ne créez ces niveaux que s’ils portent une règle ou un cycle de vie. La documentation Microsoft sur les architectures multi-tenant rappelle qu’un tenant est un groupe d’utilisateurs et doit être distingué des utilisateurs eux-mêmes. Dans un produit interne, le découpage métier peut encore différer du tenant technique.
Chaque objet possède une entité d’autorité ou une relation explicite de partage. Un client groupe peut être visible par plusieurs filiales, mais le contrat et la commande restent détenus par une entité. Le partage est une relation auditable ; il ne se déduit pas d’un pays identique ni d’une adresse e-mail.
Backfiller les données avec une preuve
L’ajout d’une colonne non nulle avec une valeur par défaut masque les ambiguïtés. Commencez par une colonne nullable ou une table de rattachement, puis calculez la cible depuis des règles documentées : établissement ERP, centre de coût, préfixe de facture ou propriétaire historique. Chaque règle produit un nombre de dossiers, un taux de confiance et une liste d’exceptions.
La migration s’exécute par lots idempotents. Elle conserve l’ancienne valeur, la règle appliquée, la version et la date. Un même lot rejoué ne change pas le résultat sans nouvelle version. La balance compare total avant, total attribué, inconnus, doublons et agrégats métier, par exemple montants et documents. Une somme correcte ne garantit pas que chaque commande appartient à la bonne société.
Les inconnus ne sont pas forcés vers l’entité historique. Ils passent dans une file de qualification avec contexte et responsable. Une décision manuelle devient une entrée de mapping réutilisable si le cas se répète. Lorsque le taux d’inconnus dépasse le budget local, la bascule s’arrête ; le seuil dépend du risque et du volume, pas d’un pourcentage universel.
Refondre les droits sans fuite de périmètre
Séparez capacité et portée. Le rôle « approuver » dit ce qu’une personne peut faire ; le rattachement à une entité, un montant ou un portefeuille dit où et jusqu’où. Une délégation ajoute une période, un motif et un donneur. Le support groupe utilise une élévation temporaire, jamais un compte administrateur partagé.
La règle est fermée par défaut. L’Authorization Cheat Sheet d’OWASP recommande le moindre privilège, le refus par défaut et la validation des permissions à chaque requête. Dans l’application, le périmètre est appliqué dans la couche d’accès ou le service de domaine, pas seulement dans le menu ou le contrôleur.
Testez les droits négatifs : un utilisateur français ne lit pas le document belge, un manager belge ne valide pas au-dessus de son plafond, une délégation expirée échoue, un identifiant deviné ne contourne pas le filtre. Les exports, API, workers et notifications utilisent les mêmes règles. Un écran protégé devant un export global reste une fuite.
Isoler les règles locales du socle
Une valeur locale réversible, comme un calendrier ou un libellé, relève d’une configuration versionnée. Une décision dépendante du contexte, comme une validation ou un plafond, devient une politique testable. Une capacité avec données, droits et run propres peut former un module. Le choix dépend du cycle de vie, pas de la préférence pour un framework.
Contre-intuitivement, rendre tout configurable fragilise souvent le produit. Une option sans contrainte autorise des combinaisons jamais testées et déplace le développement vers le support. Conservez les invariants dans le code ou le domaine ; exposez seulement les variations possédées, bornées et auditables.
Chaque politique garde date d’effet et version. Un dossier existant conserve la règle qui a produit sa décision, sauf migration explicite. Modifier le plafond belge aujourd’hui ne doit pas réécrire silencieusement les approbations du mois précédent.
Cas concret : ouvrir une deuxième société
L’application historique gère les interventions de techniciens français. Un contrat, un planning et une facture sont reliés au client, sans société. La filiale belge partage certains clients, emploie ses techniciens et facture séparément. Les comptes groupe doivent consulter les deux activités, mais chaque responsable local ne voit que ses équipes.
La cible ajoute une entité légale aux contrats et factures, puis une unité opérationnelle aux interventions. Les clients sont partagés par une relation explicite. Le contexte actif de l’utilisateur est choisi parmi ses rattachements et validé côté serveur. Une intervention hérite de l’unité du contrat ; changer ce rattachement après facturation exige un cas d’usage audité.
Le backfill utilise le préfixe de facture et l’agence du technicien. Sur vingt mille interventions, cent trente restent ambiguës parce que le technicien a changé d’agence. Elles sont rapprochées des contrats et qualifiées. La balance compare interventions, heures et montants par société avant de rendre le champ obligatoire.
Piloter sans exposer tout le périmètre
Le pilote ouvre cinquante utilisateurs belges et deux workflows. L’équipe simule un changement d’entité, une délégation expirée, un export comptable indisponible et une notification rejouée. Le go exige zéro lecture croisée non autorisée, une balance sans inconnu sur les dossiers du pilote et un diagnostic sous quinze minutes depuis l’identifiant d’intervention.
Le rollback ferme les nouvelles créations belges, mais conserve le traitement des dossiers acceptés. Il ne remet pas toutes les lignes en France. Les demandes en cours sont exportées, rapprochées puis soit terminées sur le nouveau chemin, soit transférées avec une décision explicite. Ces seuils et gestes sont adaptés au risque contractuel local.
Reprendre les contrats d’intégration
Chaque flux transporte l’entité, sa version de mapping et une corrélation métier. L’ERP peut avoir un code société différent ; l’annuaire un tenant technique ; le prestataire de paiement un compte marchand. La table de mapping nomme source, cible, date d’effet et responsable. Une valeur inconnue met le dossier en attente au lieu de choisir l’entité historique.
Les clés d’idempotence incluent le périmètre lorsque deux entités peuvent produire le même numéro local. Les files sont partitionnées seulement si l’ordre l’exige. Un worker traite avec un compte technique dont les droits sont limités aux entités nécessaires et journalise la décision. Le secret d’une filiale ne donne pas accès aux autres par commodité.
La réconciliation compare objets locaux, accusés externes et effets attendus. Elle met en avant les dossiers absents, doublons et mauvais rattachements. Un flux techniquement vert peut rester faux s’il envoie toutes les factures vers la société France ; la mesure porte sur le résultat métier.
Migrer par tranches réversibles
Évitez le grand basculement de toutes les tables, règles et équipes. Commencez par rendre le contexte explicite en lecture, sans modifier les décisions. Ajoutez ensuite les écritures sur un parcours, puis une deuxième entité. Chaque tranche ferme données, droits, intégrations, support et rollback.
Une stratégie de double lecture compare ancienne et nouvelle attribution, mais une seule décision reste autoritative. La double écriture durable crée des divergences ; si elle est temporaire, nommez son propriétaire, sa durée et sa balance. Le drapeau d’activation s’applique par entité et cas d’usage, pas par navigateur.
Le schéma évolue en étapes compatibles : ajouter, backfiller, lire, écrire, rendre obligatoire, puis retirer l’ancien implicite. Les workers et déploiements anciens doivent continuer pendant la fenêtre prévue. Une contrainte en base renforce le modèle seulement après traitement des inconnus.
Instrumenter cohérence et retour arrière
La mise en œuvre décrit les entrées, sorties, responsabilités, dépendances, seuils et journalisation de chaque tranche. L’instrumentation porte entité, cas d’usage, corrélation et version de politique. Le monitoring suit lectures refusées, rattachements inconnus, écarts de balance, messages en erreur et interventions manuelles. Chaque alerte déclenche une action nommée.
Le rollback désactive les nouvelles écritures, conserve les dossiers acceptés et choisit leur traitement. Le repli ne modifie pas les propriétaires historiques pour retrouver un écran vert. Une sortie exige une balance, une file qualifiée et la validation du responsable local. Les dépendances SSO, ERP, cache d’autorisation et batch ont chacune leur test de panne.
Les journaux évitent les données sensibles, mais conservent qui, quoi, entité, décision et motif. Un support autorisé retrouve le parcours depuis l’identifiant métier. L’exploitation doit pouvoir distinguer une absence de droit, un mapping inconnu, une règle locale et un retard d’intégration sans interroger directement la base.
Pour qui cette reprise devient nécessaire
La démarche concerne un produit stable dans un premier pays qui doit accueillir filiales, franchises, marques ou sociétés légales sans créer une copie par entité. Elle devient prioritaire lorsque les utilisateurs changent de périmètre, que les documents ont une portée juridique ou que les flux externes varient.
Un site éditorial dont seule la langue change peut utiliser localisation et contenu sans modèle multi-entités complet. À l’inverse, une application qui gère argent, stock, contrat, donnée personnelle ou responsabilité doit expliciter l’autorité et les droits avant l’ouverture.
Le sponsor possède le risque et l’ordre des entités. Le produit possède le modèle et les invariants. Les relais locaux fournissent les dossiers et valident les modes dégradés. La technique construit migration et contrats ; le run possède diagnostic et reprise. Dans une petite équipe, les personnes peuvent cumuler, pas les responsabilités.
Erreurs fréquentes de transformation
Ajouter un champ pays partout
Le pays ne dit pas qui facture, possède ou autorise. Modélisez l’entité liée à la décision et gardez la géographie comme donnée. Sinon, une société opérant dans deux pays ou un client groupe casse aussitôt le raccourci.
Attribuer tout l’historique au défaut
Une valeur par défaut ferme le schéma mais peut falsifier les balances et les droits. Utilisez des règles de backfill, mesurez la confiance et qualifiez les inconnus. Le champ devient obligatoire après la preuve, pas avant.
Ouvrir les droits puis les réduire
Les accès excessifs persistent dans les exports, caches et scripts. Commencez fermé, ajoutez les délégations utiles et testez les refus. Il est plus simple d’accorder une portée prouvée que de retrouver toutes les fuites après ouverture.
Arbitrer refactorisation ou reconstruction
Bloc de décision. Refactorisez lorsque le domaine historique reste valide, que les tests de caractérisation existent et que les migrations peuvent être tranchées. Isolez un nouveau module lorsque le cycle de vie est distinct. Reconstruisez un périmètre si les données, les droits et les règles ne peuvent pas être expliqués, tout en préparant la coexistence et le retrait.
Si une deuxième entité utilise le même cœur avec quelques politiques, alors priorisez la reprise progressive. En revanche, des obligations incompatibles et des équipes autonomes peuvent justifier plus d’isolation. Choisissez un pilote étroit plutôt qu’une plateforme universelle. À éviter : dupliquer l’instance pour tenir la date sans financer la convergence.
- Prioriser identité d’entité, données et droits avant les variantes d’écran.
- Différer l’ouverture si la balance ou le rollback reste manuel et inconnu.
- Refactoriser les invariants partagés et isoler les capacités réellement autonomes.
- Reconstruire seulement avec une stratégie de coexistence, migration et retrait mesurable.
Plan d’action sur six semaines
Semaines un à trois : découvrir et rendre compatible
Rejouez cinq parcours et inventoriez les hypothèses dans code, données, intégrations et run. Fermez les concepts organisation, entité, unité et partage. Choisissez les règles de backfill, construisez la balance et qualifiez un échantillon. Écrivez les tests actuels avant de modifier les décisions.
Ajoutez le contexte en lecture et les nouvelles relations sans casser les déploiements existants. Centralisez les filtres de périmètre, écrivez les tests négatifs et instrumentez les inconnus. Les premières métriques observent seulement ; elles n’autorisent pas encore une création dans la nouvelle entité.
Semaines quatre à six : écrire, perturber et ouvrir
Activez un workflow d’écriture pour des utilisateurs pilotes. Mettez à jour les mappings externes et les clés d’idempotence. Provoquez une délégation expirée, un cache obsolète, un mapping absent et une panne ERP. Le support suit le runbook et la balance sans correction directe.
Ouvrez la deuxième entité après deux cycles représentatifs si les seuils locaux sont tenus. Le rollback ferme le nouveau flux et traite les dossiers engagés. Le compte rendu consigne les inconnus, les droits refusés, les écarts d’intégration et le temps de diagnostic, puis décide la tranche suivante. Il compare également les agrégats financiers, le volume de corrections manuelles et les versions de politiques encore actives. Toute anomalie reçoit un propriétaire, une échéance et une condition de clôture avant l’ouverture d’un nouveau workflow ou d’une troisième entité.
- Cartographier les hypothèses depuis des parcours réels.
- Backfiller avec version, balance et traitement des inconnus.
- Fermer droits, politiques et intégrations pour un pilote.
- Tester les pannes, ouvrir une entité et étendre depuis les preuves.
Approfondir le produit multi-entités
Modéliser l’organisation cible
Le guide scalabilité organisationnelle et croissance géographique prolonge la reprise sur délégations, consolidation et support.
Encadrer les variations locales
Pour choisir entre configuration, politique et module, consultez la modélisation des variations locales sans casser le cœur produit. Ces lectures doivent être appliquées à un dossier historique et à une entité pilote.
- Relier organisation, droits et données au même contexte d’entité.
- Conserver la version de règle sur les dossiers historiques.
- Tester le support et la réconciliation avant d’ajouter un troisième périmètre.
Conclusion : migrer le modèle avant l’interface
Un produit mono-pays devient multi-entités lorsque ses données, droits, règles et intégrations portent un contexte explicite. Un sélecteur de pays ou une copie d’instance ne remplace pas ce modèle.
La reprise réussie rend les hypothèses visibles, backfille avec une balance, teste les refus et ouvre de petites tranches. Les dossiers historiques gardent leur preuve ; les inconnus restent qualifiés plutôt que forcés vers un défaut commode.
Le meilleur signal est opérationnel : un utilisateur agit dans son périmètre, un compte groupe consulte selon une relation accordée et le support explique chaque écart depuis un identifiant métier. Le produit peut alors accueillir l’entité suivante sans multiplier les exceptions.
- Nommer avant de généraliser.
- Rapprocher avant de rendre obligatoire.
- Refuser avant d’ouvrir par défaut.
Dawap peut accompagner cette transformation de développement web sur mesure : audit mono-pays, modèle d’entité, migration, droits, intégrations, pilote et préparation du run.