Base de données multi-tenant — contrat actuel de dynors-db¶
État contrôlé le 15 octobre 2026. Versions, compatibilité et correctifs · Ancien guide archivé, non normatif.
1. Choisir la bonne ligne¶
| Ligne DB | Socle | Catalogue / qualification |
|---|---|---|
| 1.0.14 | Ancienne ligne Boot 3 | Durcissement tenant/quotas ; script ajoutant deux colonnes, pas de création complète du catalogue |
| 2.0.0 | Boot 4.1.1 / Spring 7.0.9, Java 17 minimum | PG 15/16 ; bootstrap catalogue neuf non livré |
| 2.1.0 | Même ligne Boot 4 ; publiée et relue au registry | Catalogue packagé et PG 17 ; adoption explicite et qualification produit |
La cible immédiate est Boot 4 / PostgreSQL 17. MySQL est différé : le contrat catalogue 2.1 est PostgreSQL uniquement, pas un SQL multi-moteur qualifié. La migration du moteur PostgreSQL lui-même exige sauvegarde restaurable et preuve applicative ; le succès du SDK ne prouve pas pg_upgrade ou la reprise d'une base produit.
Le BOM Core 1.0.14 pointe vers DB 1.0.12, pas vers les dernières corrections. Le futur BOM Core 2 Boot 4 n'est pas encore publié. Une sélection explicite du module est possible après disponibilité de sa stable et autorisation d'adoption ; ne pas inventer un BOM disponible.
2. Les trois surfaces à distinguer¶
- Catalogue de contrôle : internal.tenants et internal.tenant_compliance_requirements.
- Provisionnement : contenant/schéma/base explicitement créé pour un tenant.
- Readiness : migrations métier, ACL/RLS, rôle runtime sûr et séparation des seeds prouvés.
Créer un tenant ne certifie pas sa readiness. Aucun passage à ACTIVE via le service sans TenantReadinessCheck applicatif positif. TAKKU/Forge/SIRRAT n'acquièrent pas cette preuve par leur simple présence.
Les stratégies sont des contrats choisis pour le tenant provisionné : SHARED, SCHEMA_DEDICATED ou DATABASE_DEDICATED. Aucun défaut global ne doit transformer un contexte absent/incohérent en accès à une base ou un schéma de repli.
3. Catalogue 2.1 : inclusion explicite seulement¶
Après confirmation de publication et décision d'adoption pour une application Boot 4 :
implementation("com.dynors:dynors-db:2.1.0")
Le JAR livre les ressources suivantes :
db/dynors-db/catalog/db.changelog-catalog.xml
db/dynors-db/catalog/001-catalog.sql
db/dynors-db/catalog/catalog-validation-v1.sql
Liquibase, dans le master choisi par l'application, avant les changesets dépendants :
<include file="db/dynors-db/catalog/db.changelog-catalog.xml"
relativeToChangelogFile="false"/>
Le même SQL peut être délégué depuis Flyway ou utilisé par Ops. L'exécuter en une transaction et sérialiser la migration par la procédure retenue. Aucune découverte ou migration automatique n'est installée par DB. Consommer le SQL du JAR exact, pas le template .sql.in des sources ; ne pas réécrire un changeset déjà appliqué.
La migration conserve les faits existants. Les compteurs API historiques non nuls sans période restent à classifier par DATA/OPS ; aucun reset ou date arbitraire. Le CHECK Hibernate legacy connu peut être élargi pour INTERNAL, mais une politique tier inconnue est refusée atomiquement et laissée à la revue.
La version structurelle 1 est distincte de Maven 2.1.0. Un marqueur seul ne valide pas les colonnes, contraintes et droits. Une dérive de structure reste refusée.
4. Vérification explicite avant JPA¶
Importer TenantCatalogVerificationConfiguration, activer dynors.db.catalog.verify-enabled=true et fournir un DataSource de contrôle nommé dynorsCatalogDataSource. Ne pas lui donner un pool routé tenant.
Le vérificateur ne fait que des SELECT : pas de DDL, GRANT ou seed. L'ordre qualifié avec Boot est initialisation DB explicite → vérificateur → EntityManagerFactory. Un orchestrateur personnalisé doit câbler ses dépendances. Le diagnostic DB-CATALOG-SCHEMA-INVALID, HTTP 503, indique la version attendue et la ressource à appliquer sans exposer une URL JDBC ou un mot de passe.
Ensuite seulement, utiliser ddl-auto=validate ; Hibernate update/create-drop en développement ne constitue pas une preuve d'installation de production.
5. Isolation : garanties réelles et responsabilités produit¶
search_path est un routage, pas une autorisation. Un rôle autorisé à lire un autre schéma peut le nommer explicitement. Les privilèges SQL et RLS restent obligatoires.
TenantAwareRepository est un marqueur, pas une protection automatique de toutes les recherches par identifiant, requêtes natives, écritures ou caches. Le filtre Hibernate est une aide ORM ; il ne remplace pas RLS/ACL.
Les rails qualifiés refusent les rôles administratifs/cluster-wide et les pools dont le nettoyage ne peut être prouvé. Le retour au pool vérifie rollback, DISCARD ALL et restauration du contexte ; un échec exige l'éviction physique. Le catalogue/provisionneur et le rôle runtime doivent rester séparés.
Une identité tenant vient d'un JWT déjà vérifié ou d'un transit SLY déjà vérifié. Leur contradiction est refusée. Pas de header libre, tenant dev implicite ou source de secours. Aucun transport du ThreadLocal vers l'asynchrone n'est supposé.
6. Fixtures et migration applicative¶
Le classifier test-fixtures est séparé du JAR runtime. Après publication :
testImplementation(testFixtures("com.dynors:dynors-db:2.1.0"))
En POM seul, ajouter explicitement le classifier en scope test à DB normal. TenantTestFixtures passe par le service du domaine, pas un INSERT recopié. La simulation de readiness exige le seul profil test et une base jetable reconnue ; elle est refusée hors test et ne prouve jamais les migrations/RLS de production.
Avant adoption :
- Inventorier version résolue, catalogue, données et CHECKs.
- Préparer Boot 4 séparément si l'application est encore Boot 3.
- Sauvegarder et tester l'application de la migration sur une copie isolée.
- Arrêter/isoler les anciens écrivains 1.0.x : ils n'incrémentent pas row_version. Aucun rolling upgrade mixte ancien/nouveau n'est qualifié.
- Fournir la vraie readiness, vérifier contexte signé, transactions, quotas, RLS/ACL, pools et absence de données de démonstration.
- Qualifier les tests produit et l'image finale, puis obtenir le GO d'adoption.
Références canoniques du SDK : reçu stable 2.1.0, guide catalogue 2.1, qualification locale, reçu stable 2.0.0.
Une publication de bibliothèque ne vaut aucun GO pilote, DATA, RLS applicatif ou production.