Module XX — multi-tenancy et gestion des organisations
Le module XX n’est pas un service greffé sur le moteur — c’est une propriété du moteur lui-même. Il n’existe pas de module de tenancy distinct à attacher ; au contraire, le modèle de données du cœur porte une frontière de tenant sur chaque entité et le store l’applique sous chaque requête. Cette page est la référence de ce que cette frontière garantit aujourd’hui, et des parties de la gestion des organisations qui en sont encore au stade de la conception.
Ce que c’est
Section intitulée « Ce que c’est »La multi-tenancy vit dans la couche Engine (couche 0), aux côtés de l’API propre à la
plateforme (module XIX), car réintégrer l’isolation dans un modèle de données déjà en
service est précisément le genre de changement qu’on ne peut pas faire en sécurité plus
tard. Chaque entité du cœur porte un tenant_id, et un appelant n’en passe jamais
un comme paramètre libre : il fixe le tenant une seule fois et reçoit un scope dont
les dépôts sont déjà liés à celui-ci. Il n’existe aucun vocabulaire dans l’API pour
traverser les tenants — cette absence est la première barrière d’isolation, avant tout
mécanisme de base de données. Le scope privilégié inter-tenants (créer une organisation,
lister les organisations, supprimer un tenant) n’est accessible que par le démarrage
propre du moteur, jamais par un module.
Le contrat et les entités
Section intitulée « Le contrat et les entités »Le modèle de tenant appartient au contrat du modèle de données, non à un schéma propre
à chaque module. L’entité racine est l’Org, qui est le tenant : lorsque le
moteur amorce une organisation, son identifiant devient l’identifiant du tenant et la
chaîne d’audit propre à l’organisation est établie au même moment. Toute autre entité du
cœur — agents, sessions, ressources, identités, politiques, enregistrements de coûts,
findings, déploiements, l’access map et l’audit ledger — est créée à l’intérieur d’un
scope de tenant et estampillée avec ce tenant à l’écriture ; l’appelant ne peut pas le
surcharger.
L’isolation est appliquée au niveau de la couche de requêtes, selon le déploiement :
- Sur PostgreSQL, chaque table portant
tenant_ids’exécute sousFORCE ROW LEVEL SECURITYavec une politiquetenant_isolationliée par transaction. Une transaction qui ne parvient pas à lier un tenant lève une erreur plutôt que de renvoyer silencieusement zéro ligne (fail-closed). Le rôle applicatif est non-superutilisateur et n’a jamaisBYPASSRLS, etFORCElie la politique même pour le propriétaire de la table. La propriété, elle, est un choix de déploiement : l’installation mono-rôle par défaut laisse le rôle applicatif propriétaire de la base — la RLS le lie toujours, mais un propriétaire peut altérer ses propres tables, de sorte que cette posture est capable de détecter les altérations plutôt qu’à l’épreuve du propriétaire. La frontière dure de privilège — un rôle applicatif qui est aussi non-propriétaire — vient de la topologie scindée propriétaire/application, où un rôle propriétaire distinct exécute le provisionnement et le rôle applicatif ne reçoit que le DML dont il a besoin. - Sur SQLite (le déploiement mononœud) il n’y a pas de sécurité au niveau ligne ; l’équivalence vient de deux faits — le seul chemin vers la base est le SQL généré par descripteur qui ajoute toujours le prédicat de tenant, et des déclencheurs tripwire annulent toute écriture dont le tenant ne correspond pas au scope épinglé.
Un auto-test de démarrage interroge les garde-fous d’isolation en vigueur après la
migration et refuse d’ouvrir le store si une table portant tenant_id n’est pas
protégée — de sorte qu’un garde-fou oublié sur une nouvelle table devient un échec de
démarrage, et non une fuite silencieuse.
Ce qu’il consomme et produit
Section intitulée « Ce qu’il consomme et produit »Le module XX n’a aucune surface de bus d’événements ni aucune actuation. Il ne consomme
pas edge.observed, n’émet pas de findings et n’appelle aucun fournisseur — c’est le
substrat à travers lequel les autres modules écrivent. Son seul effet observable est
structurel : chaque entité qu’un module persiste est déjà scopée par tenant, et chaque
mutation sur une entité auditée s’ajoute à l’audit ledger chaîné par hash
de ce tenant au sein de la même transaction.
Liens connexes
Section intitulée « Liens connexes »- Catalogue des modules — où se situe le module XX et son statut d’actuation honnête.
- Identité, permissions et gouvernance — rôles et autorité déléguée au sein d’un tenant.
- Vue d’ensemble de l’architecture — la couche moteur et le modèle de données général.
- Référence du bus d’événements — l’audit ledger par tenant auquel s’ajoute chaque mutation.
- Honnêteté et limites — ce qui est construit aujourd’hui face à ce qui est au stade de la conception.