Repository navigation
Attribution du super-admin : écrire contre le schéma réel de user_roles - #6
Merged
Merged
Conversation
Le script échouait en production avec « column "id" of relation "user_roles" does not exist ». La table de production vaut exactement (user_id, role), avec role en type ENUM ; le modèle SQLAlchemy déclare en plus id, tenant_id et created_at. Comme le schéma de test est construit depuis les modèles, l'écart était invisible : le code passait les tests et ne pouvait qu'échouer en prod. L'INSERT est désormais construit d'après `information_schema`, donc valable sur les deux schémas. Le ON CONFLICT, qui supposait une contrainte unique (tenant_id, user_id, role) absente en production, est remplacé par un contrôle d'existence explicite. Les comparaisons sur `role` sont castées en texte pour valoir aussi bien contre l'ENUM que contre le varchar. `--list` ne réclame plus created_at quand la colonne n'existe pas. Vérifié sur base jetable contre les DEUX schémas : attribution, idempotence, listage, retrait, compte introuvable. Test unitaire sur la construction de l'INSERT pour que la CI protège les deux cas. Le modèle porte désormais un avertissement : il ne décrit pas la table de production, et tout code écrit d'après ses colonnes échouera en prod tout en passant les tests.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Le symptôme
En production, sur le shell Render :
La cause
La table de production vaut exactement :
Le modèle
app/models/user_role.pydéclare en plusid,tenant_idetcreated_at. Comme le schéma de test est construit depuis les modèles (Base.metadata.create_all), l'écart est invisible en test : le code passait les 152 tests et ne pouvait qu'échouer en production. C'est exactement le piège déjà documenté en tête deapp/models/screening_db.py.Bon à savoir :
SUPER_ADMINest une valeur de l'ENUM, etuser_id/roleexistent bien — la modification deauth_service.pylivrée en PR #5 tourne donc sans risque en production. C'est ce que confirme le401propre observé sur/auth/login.Le correctif
INSERTest construit d'aprèsinformation_schema: valable sur le schéma de production comme sur celui des modèles ;ON CONFLICT (tenant_id, user_id, role)supposait une contrainte unique absente en production → remplacé par un contrôle d'existence explicite ;rolesont castées en texte, pour valoir contre l'ENUM comme contre le varchar ;--listne réclame pluscreated_atquand la colonne n'existe pas ;Vérifications
Exécuté sur base jetable contre les deux schémas — attribution, idempotence, listage, retrait, compte introuvable :
Plus un test unitaire sur la construction de l'
INSERT, pour que la CI protège les deux cas — c'est le seul niveau où le test peut voir l'écart, puisque la base de test ne connaît que le schéma des modèles.Reste ouvert
Le vrai assainissement serait d'aligner le modèle sur la base par une migration dédiée, ou d'aligner la base sur le modèle. Tant que les deux divergent, tout code écrit d'après le modèle est un piège. Hors périmètre de ce correctif.