Dans un SaaS où une personne peut travailler dans plusieurs organisations ou espaces de travail, la question « qui a créé cette ressource ? » ne répond pas nécessairement à la question « à qui appartient-elle ? ». Cette différence influe sur les personnes qui peuvent la consulter, la modifier, la transférer ou la conserver lorsqu’un membre quitte une équipe. La résoudre tardivement conduit souvent à disperser les règles entre les requêtes, les contrôleurs et les tâches en arrière-plan.
La propriété des ressources dans un SaaS multiutilisateur est une décision de domaine : elle détermine quelle entité détient une ressource et quelles conséquences en découlent. Elle n’est synonyme ni d’authentification, ni d’appartenance à une organisation ou à un espace de travail, ni d’autorisations. La modéliser explicitement permet aux équipes produit, données et développement de partager une règle cohérente.
L’identité, l’appartenance et la propriété sont des relations distinctes

Un utilisateur représente une identité qui peut se connecter. L’appartenance indique que cette identité participe à une organisation ou à un espace de travail, éventuellement avec un rôle ou un état. La propriété indique quelle entité répond d’une ressource au regard des règles du produit. Une personne peut appartenir à plusieurs espaces et, en même temps, créer un document qui appartient à l’un d’eux.
Il convient également de distinguer l’auteur de l’action initiale. Le champ created_by peut conserver l’identité de la personne à l’origine de l’action, mais ne devrait pas, à lui seul, déterminer la propriété. Si la personne qui a créé l’enregistrement quitte l’organisation, la ressource peut continuer à appartenir à l’organisation. À l’inverse, une personne peut acquérir une ressource créée à l’origine par quelqu’un d’autre.
Il est utile de documenter les réponses à trois questions : qui est propriétaire, qui peut agir sur la ressource et qui a effectué chaque action importante. Si le même champ ou la même relation est censé répondre à toutes ces questions, le modèle mélange probablement plusieurs concepts.
Choisir entre propriété personnelle, organisationnelle ou partagée
- Personnelle : la ressource appartient à un utilisateur. Ce choix convient lorsque son cycle de vie dépend de cette personne et non d’une équipe, comme pour une préférence privée. Il faut décider de ce qui se passe si le compte est désactivé ou supprimé.
- Organisationnelle : elle appartient à une organisation ou à un espace de travail. Cette option convient lorsque la ressource doit rester accessible à l’équipe même si sa composition change. L’appartenance de l’utilisateur autorise l’accès, mais ne fait pas de lui le propriétaire individuel.
- Partagée : plusieurs entités peuvent avoir un lien de propriété ou de responsabilité. N’adoptez cette option que si le domaine requiert réellement une copropriété. Si le besoin consiste à permettre à plusieurs personnes de consulter ou de modifier la ressource, il s’agit généralement d’un accès accordé par des appartenances ou des autorisations, et non de plusieurs propriétaires.
La décision doit suivre le cycle de vie de la ressource et les règles métier, et non une préférence visant à simplifier une table. Demandez-vous qui peut la conserver, décider de sa suppression et en répondre lorsque l’équipe change. Distinguez également « espace de travail » et « organisation » : si le premier est une véritable subdivision, avec son propre cycle de vie et ses propres limites, il peut constituer le propriétaire approprié ; s’il s’agit seulement d’une vue ou d’un contexte de navigation, ce n’est peut-être pas le cas.
Représenter le domaine sans déduire le propriétaire
Dans un modèle simple, une table de ressources peut avoir un propriétaire explicite, par exemple owner_type et owner_id, ou des références distinctes comme user_id et organization_id. La première option peut faciliter la prise en charge de plusieurs types de propriétaires, mais elle nécessite de valider les références et de tenir compte des limites d’intégrité référentielle des relations polymorphes. Les références distinctes rendent les liens plus explicites, mais imposent d’empêcher les combinaisons invalides.
Une autre solution consiste à créer une entité commune, par exemple workspace, si le domaine regroupe réellement sous cette entité les comptes personnels et les équipes. Ne l’ajoutez pas simplement pour masquer des différences : elle doit avoir une signification et des règles stables. Quelle que soit la conception retenue, définissez des contraintes qui empêchent une ressource d’être associée simultanément à des propriétaires incompatibles ou à aucun propriétaire lorsque la propriété est obligatoire.
Modélisez séparément les appartenances, par exemple au moyen d’une relation entre l’utilisateur et l’organisation incluant un état et un rôle. Le contexte actif de l’interface peut indiquer où la personne travaille actuellement, mais il ne fait pas autorité : il doit être validé pour chaque opération. De même, le propriétaire ne doit pas être calculé comme étant « la personne qui a créé la ressource » ou « l’organisation actuellement sélectionnée ».
Appliquer la propriété aux lectures, aux écritures et aux processus automatisés
Les requêtes doivent intégrer le périmètre de propriété et une vérification d’accès appropriée. Il ne suffit pas de charger la ressource à partir de son identifiant et de compter sur l’interface pour masquer celles auxquelles l’utilisateur n’a pas accès. Dans une application PHP, centralisez la résolution du contexte et les règles d’autorisation dans une couche réutilisable, et évitez de répliquer des conditions incomplètes dans chaque contrôleur.
Lors des écritures, validez le propriétaire autorisé et l’appartenance active de l’acteur. Vérifiez également que les ressources associées — par exemple un dossier de destination — appartiennent à un périmètre compatible ; sinon, une mise à jour peut créer des associations croisées. Pour les opérations d’administration, distinguez explicitement les autorisations exceptionnelles des règles ordinaires et consignez qui les a exécutées et pourquoi.
Les files d’attente, les commandes planifiées, les webhooks et les imports ne sont pas toujours associés à un utilisateur interactif. Ils doivent transporter un identifiant de propriétaire ou un contexte validé, plutôt que de dépendre d’une session implicite. Le processus doit appliquer les mêmes règles de périmètre que l’application web. S’il fonctionne avec des privilèges élevés, limitez-les et auditez-les.
Traiter le transfert comme une opération de domaine
Changer de propriétaire ne devrait pas être une simple modification générique d’un champ. Définissez des préconditions : qui peut lancer le transfert, quel lien le destinataire doit avoir avec l’espace et que faire en cas d’invitation en attente ou de compte inactif. Lorsque l’opération met à jour plusieurs relations et effets associés, elle devrait être atomique.
Déterminez également ce qu’il advient des dépendances, telles que les fichiers, les intégrations, la facturation ou les automatisations. Ne partez pas du principe que tout doit être transféré avec la ressource : cette politique dépend du produit. S’il est impossible d’effectuer toutes les modifications dans une transaction, concevez un processus récupérable, doté d’états explicites et idempotent en cas de nouvelle tentative.
Conservez une piste d’audit comprenant l’acteur, l’ancien propriétaire, le nouveau propriétaire, la date et le motif, le cas échéant. Cela permet de distinguer la personne qui a autorisé le changement de celle qui a exécuté l’action technique. L’identité de l’auteur d’origine peut être conservée sans modification, même si la propriété change.
Tester les limites qui révèlent les erreurs de modélisation
Automatisez des tests de service et d’intégration pour vérifier les accès autorisés comme ceux qui doivent être refusés. Une matrice utile comprend une personne présente dans deux organisations, des ressources lui appartenant ou non dans chacune d’elles, des appartenances suspendues ou révoquées, un transfert vers une destination non éligible et un accès à l’aide d’identifiants connus. Vérifiez les réponses et les effets sur les données : masquer un bouton ne constitue pas un test d’autorisation.
Testez également les ressources sans propriétaire valide, les relations en double et les échecs survenant pendant un transfert. Si le schéma exige un propriétaire, les contraintes de la base de données doivent étayer cette exigence, et les migrations doivent détecter les enregistrements historiques incohérents avant l’ajout de ces contraintes. Pour les tâches en arrière-plan, vérifiez que le contexte est conservé et qu’une nouvelle tentative ne duplique pas les modifications.
Liste de contrôle avant d’étendre le SaaS

- Est-il défini si chaque type de ressource appartient à une personne, à une organisation ou à un espace ?
- La propriété est-elle distinguée de l’identité de l’auteur, de l’appartenance, du rôle et du contexte actif ?
- Les requêtes de lecture et d’écriture valident-elles le propriétaire et l’appartenance actuelle ?
- Les tâches automatisées reçoivent-elles un périmètre explicite et appliquent-elles des contrôles équivalents ?
- Le transfert comporte-t-il des préconditions, des effets définis, une piste d’audit et une stratégie de récupération ?
- Existe-t-il des tests pour les utilisateurs présents dans plusieurs espaces, les départs, les accès croisés et les données incohérentes ?
Si une réponse dépend de conventions non documentées, il est préférable de les clarifier avant d’ajouter d’autres types de ressources ou de flux de collaboration. Un modèle explicite ne supprime pas tous les cas complexes, mais rend les décisions visibles et permet de les vérifier dans le schéma, les requêtes et les tests.



