Accès à une base PostgreSQL pour les générateurs d’applications IA
Configurez l’accès à une base PostgreSQL pour un générateur d’applications IA avec découverte en lecture seule, identifiants limités, migrations approuvées et pool sûr.

Un générateur d’applications IA peut se connecter à une base PostgreSQL existante sans posséder son schéma, à condition de rendre cette limite réelle dans PostgreSQL. Une instruction qui dit « ne modifiez pas la production » n’est pas un contrôle. Un rôle séparé, des valeurs par défaut de transaction, une revue explicite des migrations et des vérifications de schéma le sont.
Le modèle sûr répartit le travail sur la base en trois voies. La découverte lit les métadonnées et des échantillons de données autorisés. L’application lit et écrit uniquement dans les tables et avec les opérations dont elle a besoin. Les changements de schéma passent par une identité de migration distincte, après qu’une personne a approuvé le SQL exact. J’ai vu des équipes réunir ces voies sous un identifiant de propriétaire pratique, puis constater qu’un agent avait pris un nom de colonne plausible pour l’autorisation de redessiner une table en production. Le confort a duré un après-midi, le nettoyage beaucoup plus longtemps.
La découverte doit être en lecture seule par conception
Une connexion de découverte doit avoir suffisamment d’accès pour comprendre le schéma autorisé, pas suffisamment pour l’améliorer. Créez un rôle de connexion qui ne peut ni créer de bases ni créer de rôles, ne peut pas contourner la sécurité au niveau des lignes et ne peut pas hériter de privilèges inattendus d’un groupe étendu. PostgreSQL crée les nouveaux rôles sans ces pouvoirs, mais les déclarer explicitement rend l’intention vérifiable.
CREATE ROLE app_discovery
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
NOINHERIT
NOBYPASSRLS
CONNECTION LIMIT 3
PASSWORD 'replace-through-secret-manager';
ALTER ROLE app_discovery SET default_transaction_read_only = on;
GRANT CONNECT ON DATABASE customer_portal TO app_discovery;
GRANT USAGE ON SCHEMA app TO app_discovery;
GRANT SELECT ON ALL TABLES IN SCHEMA app TO app_discovery;
default_transaction_read_only bloque les écritures ordinaires dans les sessions qui conservent cette valeur par défaut. C’est une ceinture utile, pas le seul dispositif de sécurité. L’absence de INSERT, UPDATE, DELETE, TRUNCATE, CREATE et de propriété maintient le rôle dans ses limites si un client change son paramètre de transaction. N’accordez pas à ce rôle l’appartenance à un groupe de propriétaires de l’application et ne le faites pas propriétaire d’un schéma.
Examinez les droits existants avant que le générateur se connecte. La requête suivante produit une ligne par privilège de table, afin qu’un examinateur puisse repérer tout droit au-delà de SELECT :
SELECT table_schema, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'app_discovery'
ORDER BY table_schema, table_name, privilege_type;
Un résultat sain ressemble à app | invoices | SELECT. Un résultat vide peut signifier que la découverte ne voit pas une table nécessaire ; une ligne se terminant par UPDATE signifie que le rôle est trop puissant. Vérifiez aussi les privilèges de schéma avec has_schema_privilege et ceux de base avec has_database_privilege, car les droits sur les tables ne révèlent pas si le rôle peut créer des objets ailleurs.
N’utilisez pas un instantané de production pour justifier le partage d’un identifiant de propriétaire. Une copie peut toujours contenir des données clients, et un agent propriétaire peut la modifier au point de rendre les comparaisons ultérieures inutiles. Donnez à la découverte une identité dédiée dans chaque environnement.
L’inspection du catalogue doit rester dans une liste autorisée
Le générateur ne doit découvrir que les schémas approuvés et enregistrer ce que PostgreSQL rapporte réellement. information_schema fournit des vues portables sur les tables, les colonnes, les contraintes et les privilèges. pg_catalog expose des détails propres à PostgreSQL, comme les index, les types, les expressions générées et la sécurité au niveau des lignes. Ces deux sources sont plus fiables que le souvenir d’un LLM sur une table client typique.
Commencez par une liste autorisée, par exemple app et reporting. Refusez pg_catalog, information_schema, les schémas temporaires, les schémas d’extensions et tout schéma de locataire absent de la liste comme cibles d’application. La requête doit filtrer au niveau de la base, du rôle et du SQL. Une liste autorisée seulement dans l’instruction peut disparaître lors d’une conversation ultérieure.
SELECT
c.table_schema,
c.table_name,
c.ordinal_position,
c.column_name,
c.data_type,
c.is_nullable,
c.column_default
FROM information_schema.columns AS c
WHERE c.table_schema IN ('app', 'reporting')
ORDER BY c.table_schema, c.table_name, c.ordinal_position;
Enregistrez le résultat comme un instantané du schéma avec l’heure de récupération et un identifiant de base. L’instantané prouve ce que le générateur a vu. Ce n’est pas une vérité permanente. PostgreSQL peut changer entre la découverte et la génération du code : comparez donc une empreinte récente avant le déploiement. Une empreinte pratique peut hacher les descriptions ordonnées des tables, colonnes, types, valeurs de nullité, valeurs par défaut, contraintes et index. Si l’empreinte diffère, arrêtez-vous et redécouvrez le schéma au lieu de deviner quel changement est inoffensif.
L’échantillonnage de lignes relève d’une décision d’autorisation distincte. Les métadonnées de colonnes contiennent rarement des données personnelles, alors que les exemples de lignes en contiennent souvent. Préférez ne prélever aucune ligne pour générer le code. Si des exemples sont nécessaires, exposez une vue qui retire ou masque les secrets et les identifiants directs, puis accordez SELECT uniquement sur cette vue. LIMIT 10 ne rend pas une requête sensible sûre, il réduit seulement la fuite.
Le chemin de recherche mérite le même traitement. Réglez-le sur le schéma approuvé et pg_catalog, qualifiez les noms de tables générés et ne vous fiez jamais au premier objet que PostgreSQL résout. Un attaquant ou une migration négligente peut créer un objet du même nom dans un schéma accessible en écriture. Des noms qualifiés comme app.orders lèvent cette ambiguïté.
Le rôle d’exécution doit correspondre aux actions réelles des utilisateurs
La découverte et l’exécution sont deux tâches différentes. L’application en cours d’exécution peut avoir besoin d’insérer une commande, de mettre à jour un brouillon ou d’appeler une fonction soigneusement conçue, mais cela ne justifie pas un large accès en écriture à tout le schéma découvert. Établissez une matrice de permissions à partir des actions utilisateur, puis traduisez chaque action en droit PostgreSQL minimal.
Par exemple, une interface de consultation de factures peut nécessiter SELECT sur app.invoices et app.invoice_lines, tandis qu’une fonction de notes nécessite SELECT et INSERT sur app.invoice_notes. Elle n’a probablement pas besoin de DELETE sur les factures, d’accéder aux enregistrements de réinitialisation de mot de passe ni de créer des schémas. Accordez l’usage d’une séquence uniquement lorsqu’une insertion dépend réellement de cette séquence. PostgreSQL traite les séquences comme des objets séparés, ce qui surprend les générateurs testés avec un compte propriétaire.
Les vues et les fonctions peuvent encore réduire la surface d’accès. Une vue peut exposer les colonnes approuvées tout en cachant les champs internes. Une fonction SECURITY DEFINER peut effectuer une opération contrôlée que les droits ordinaires ne savent pas exprimer, mais elle a besoin d’un search_path fixe, de contrôles stricts des entrées et d’un propriétaire sans pouvoirs inutiles. Traitez une telle fonction comme du code privilégié, pas comme un raccourci qui contourne le modèle de permissions.
La sécurité au niveau des lignes ajoute une limite de données dans une table partagée. Elle ne remplace pas les droits sur la table. PostgreSQL vérifie d’abord que le rôle peut effectuer l’opération, puis applique les politiques de sécurité des lignes lorsqu’elles sont activées et pertinentes. Testez avec le rôle d’exécution exact, car les propriétaires de tables et les rôles avec BYPASSRLS peuvent échapper aux politiques. Un test sous le propriétaire de migration ne prouve presque rien sur ce qu’un utilisateur final peut voir.
Gardez les secrets hors des instructions, du code généré, des bundles de navigateur, des journaux de construction et des captures d’écran. Placez l’identifiant d’exécution dans le stockage de secrets de l’environnement d’hébergement et injectez-le seulement dans le processus serveur. Les applications mobiles et de navigateur ne peuvent pas garder un mot de passe PostgreSQL secret : elles doivent appeler une API serveur plutôt que se connecter directement. Faites tourner séparément les identifiants de découverte, d’exécution et de migration. Une fuite dans une voie ne doit pas ouvrir les deux autres.
Le pouvoir de migration appartient à un parcours d’approbation séparé
Un générateur d’applications peut proposer des migrations, mais ne doit pas les exécuter avec sa session de découverte ou d’exécution. Donnez au travail de migration un rôle distinct, ou laissez un système de déploiement établi endosser ce rôle pour une tâche approuvée. Gardez son identifiant indisponible pendant les conversations ordinaires et les sessions de prévisualisation.
L’approbation doit couvrir le SQL exact, l’identité de la base cible, l’empreinte du schéma utilisée pour le préparer ainsi que le comportement attendu des verrous ou des réécritures. Approuver une phrase en langage naturel comme « ajouter le statut du client » laisse trop de place. Le changement exécutable pourrait ajouter une colonne de texte nullable, reconstruire une grande table, inventer une énumération ou mettre à jour toutes les lignes existantes. Ce sont des opérations différentes, avec des modes d’échec différents.
J’utilise un dossier de migration concis :
- La raison du changement et la version de l’application qui l’exige.
- Le SQL exact pour l’application et, lorsque c’est honnête, le SQL exact pour le retour arrière.
- Les objets, privilèges et lignes que les commandes peuvent affecter.
- Les requêtes de contrôle préalable, les résultats attendus et une empreinte récente du schéma.
- Le délai d’attente de verrou, le délai d’exécution, la référence de sauvegarde ou d’instantané et le responsable de la livraison.
Un script de retour arrière n’est pas toujours une annulation. Supprimer une colonne nouvellement ajoutée peut inverser le changement de catalogue, mais détruit aussi les données écrites après la livraison. Le DDL transactionnel de PostgreSQL aide pour de nombreuses opérations de catalogue, mais une transaction ne peut pas restaurer des effets externes ni des données supprimées par une commande ultérieure. Indiquez clairement les retours arrière destructeurs au lieu de traiter DOWN comme une formule magique.
Réglez lock_timeout afin qu’une migration échoue plutôt que d’attendre derrière une transaction occupée tout en bloquant le nouveau travail. Réglez statement_timeout selon l’opération examinée. Relancez les requêtes préalables pendant la fenêtre de changement. Si la taille de la table, des objets en conflit, le nombre de valeurs nulles ou l’empreinte du schéma s’écartent des hypothèses approuvées, abandonnez. L’agent doit produire un rapport d’écart, pas improviser une nouvelle migration contre la production.
N’approuvez jamais automatiquement une migration parce que les tests générés ont réussi. Les tests s’exécutent généralement sur un schéma réduit et propre, et ne détectent pas les files de verrous, les anciennes valeurs nulles, les contraintes inhabituelles, les extensions ni les versions de l’application encore en service. L’approbation est le moment où une personne rapproche l’intention générée du système réel.
Le pool de connexions modifie le calcul de sécurité
Un pool réutilise des sessions de base de données. L’état de session peut donc survivre à la requête qui l’a créé. Si une requête lance SET search_path, change de rôle, crée un objet temporaire ou désactive un délai d’attente, l’emprunteur suivant peut en hériter. L’application doit éviter l’état de session modifiable ou le réinitialiser de façon fiable quand une connexion revient au pool.
Le pool de transactions rend la limite plus stricte. Après chaque transaction, un client peut recevoir une autre session serveur, ce qui brise les hypothèses sur les requêtes préparées de session, les tables temporaires, les verrous consultatifs et les paramètres au niveau de la session. Les générateurs produisent souvent du code qui fonctionne avec une connexion directe et échoue derrière un pool parce qu’ils ne modélisent jamais cette différence. Décidez si le pool fonctionne en mode session ou transaction, puis incluez ce mode dans la génération et les tests.
Établissez le budget de connexions avant le déploiement. Commencez par le nombre de connexions autorisées par la base, réservez de la capacité pour l’administration, les migrations, la supervision et les autres services, puis répartissez le reste entre les instances de l’application. Si dix instances ouvrent chacune vingt connexions, PostgreSQL voit deux cents sessions potentielles même lorsque le trafic est calme. Un petit pool prudent avec une file d’attente est généralement plus sûr que de multiplier les connexions jusqu’à ce que la base les refuse.
Utilisez des délais côté serveur comme garde-fous : statement_timeout limite les requêtes longues, lock_timeout limite l’attente de verrous et idle_in_transaction_session_timeout supprime les sessions qui gardent une transaction ouverte sans rien faire. Définissez des valeurs pour chaque rôle au lieu de faire confiance à chaque client généré pour s’en souvenir. Vérifiez-les avec SHOW sous le rôle réel et à travers le pool réel.
Les vérifications de santé doivent être peu coûteuses. SELECT 1 confirme un aller-retour, mais ne confirme pas que l’application peut atteindre une table approuvée ni que son chemin de recherche est correct. Une vérification de disponibilité peut interroger une petite vue stable avec le rôle d’exécution. Gardez les migrations hors du démarrage de l’application : des instances simultanées qui tentent de modifier le schéma créent précisément le couplage que cette conception cherche à supprimer.
Les colonnes inventées doivent échouer avant qu’une requête ne s’exécute
Les LLM inventent des identifiants plausibles. Si une instruction parle du nom d’affichage d’un client, le code généré peut chercher customers.display_name alors que la base stocke given_name et family_name. La base rejettera cette requête, ce qui vaut mieux que lire silencieusement le mauvais champ, mais une erreur de production reste une mauvaise stratégie de validation de schéma.
Générez un artefact de schéma typé à partir de l’instantané de catalogue approuvé et faites-en l’unique source de construction des requêtes. Une table ou une colonne absente de cet artefact doit provoquer une erreur de génération. Ne laissez pas le modèle corriger l’erreur en ajoutant une migration, sauf si la tâche entre explicitement dans la voie de migration. Un identifiant absent peut indiquer une découverte obsolète, une faute d’orthographe, le mauvais environnement ou un besoin produit réel. Chacun exige une réponse différente.
Les contrôles statiques doivent analyser le SQL et résoudre chaque relation et colonne par rapport à l’instantané. Préparez ensuite les requêtes dans une base jetable ou une transaction qui ne peut pas écrire. L’analyseur PostgreSQL détecte les colonnes inconnues, les références ambiguës, les erreurs de type d’opérateur et de nombreux mauvais casts sans exiger des données métier valides. Exécutez les tests d’intégration avec le rôle d’exécution afin que les permissions et les politiques de lignes participent.
Le rapport d’échec doit fournir assez de détails pour permettre une décision humaine. Incluez l’emplacement dans le SQL, l’identifiant non résolu, les identifiants valides voisins, l’empreinte de l’instantané et l’identité de la base cible. Les suggestions sont utiles, mais le remplacement approximatif automatique est dangereux. Remplacer billing_address_id par shipping_address_id parce que les noms se ressemblent peut produire un SQL valide au sens métier faux.
Pour les filtres et tris dynamiques, associez les noms de l’API publique à un ensemble fermé d’expressions SQL qualifiées. N’insérez jamais dans le SQL un identifiant fourni par un modèle, même à travers un paramètre de valeur. Les paramètres protègent les valeurs, pas les noms de tables ou de colonnes. Si les utilisateurs peuvent choisir un champ de tri, traduisez created en une expression connue comme app.orders.created_at et refusez tout jeton inconnu.
La dérive de schéma doit arrêter une livraison, pas déclencher une réconciliation créative. Régénérez l’instantané, montrez le diff et répétez les tests. Ce délai peut sembler tatillon, mais il coûte moins cher que déployer du code dont la compréhension de la base n’existe que dans la transcription d’une conversation.
Le SQL destructeur exige une politique de refus et des preuves
Un générateur doit classifier le SQL avant que quiconque puisse l’exécuter. Bloquez DROP, TRUNCATE, les DELETE ou UPDATE étendus sans prédicat examiné, les changements de propriété, les élévations de privilèges, les changements d’extensions et les commandes visant des schémas non approuvés. Traitez ALTER TABLE comme nécessitant une revue, pas comme sûr automatiquement. Un changement de type de colonne ou une nouvelle contrainte non nulle peut parcourir ou réécrire les données et conserver des verrous importants.
La recherche de texte seule est faible, car le SQL comporte des commentaires, des identifiants entre guillemets, des fonctions et de nombreuses façons d’exprimer des effets de bord. Analysez les instructions avec un analyseur qui connaît PostgreSQL, inspectez leurs arbres syntaxiques et comptez aussi sur le rôle de base pour refuser les actions interdites. Le classificateur améliore la revue ; les privilèges imposent la limite. Aucun ne doit porter seul toute la charge.
Utilisez une base de préproduction restaurée à partir d’un instantané récent et correctement protégé lorsqu’une migration dépend de formes de tables ou de distributions de données réelles. Appliquez-y le dossier de migration exact, relevez la durée et les observations de verrouillage, lancez les tests de l’application avec les identifiants d’exécution, puis supprimez l’environnement. Ne modifiez pas discrètement le SQL entre la préproduction et la production. Toute modification crée un nouvel artefact qui requiert une nouvelle empreinte et une nouvelle approbation.
Les journaux doivent relier une proposition à une exécution sans enregistrer de secrets ni de lignes sensibles. Enregistrez qui a approuvé l’artefact de migration immuable, son condensat, l’identité cible, l’état de début et de fin ainsi que les détails d’erreur PostgreSQL. Conservez le diff généré et les résultats préalables. Une conversation avec un agent fournit du contexte utile, mais n’est pas une trace d’audit, car les utilisateurs peuvent bifurquer, réessayer et reformuler les instructions.
Les instantanés et les contrôles de retour arrière réduisent le temps de récupération, mais ne rendent pas le SQL destructeur acceptable. Un instantané peut restaurer une base entière à un point antérieur quand le besoin réel concerne une seule colonne supprimée, et la restauration peut écarter des écritures légitimes effectuées après l’instantané. Testez la récupération séparément et documentez qui peut la déclencher.
Lorsque j’utilise Koder.ai pour une application qui touche une base établie, je garde le travail en mode planification jusqu’à avoir examiné le code exporté et la limite de base proposée. Les instantanés et le retour arrière sont des contrôles de récupération, pas une autorisation de sauter cette revue. La même règle s’applique à tout générateur : la commodité du produit doit rester derrière les contrôles de la base.
Les changements de schéma doivent tolérer des versions mixtes de l’application
Une migration n’est sûre que lorsque l’ancienne application et la nouvelle peuvent toutes deux fonctionner pendant la fenêtre de livraison. En production, le passage d’une version à l’autre est rarement instantané. Des requêtes peuvent atteindre d’anciennes instances tandis que de nouvelles démarrent, des tâches en file peuvent transporter d’anciens formats et un retour arrière peut remettre le code d’hier face au schéma d’aujourd’hui. Un générateur qui ne valide que le code final avec le schéma final ignore ce chevauchement.
Préférez d’abord les changements additifs. Ajoutez une colonne nullable, une nouvelle table ou un index sans supprimer l’ancien chemin. Déployez du code qui peut lire les deux représentations et écrit dans la nouvelle lorsque cela convient. Complétez les lignes existantes avec une tâche examinée séparément, surveillez les erreurs et le retard, puis faites du nouveau champ la référence. Supprimez l’ancienne colonne ou contrainte dans une livraison ultérieure après avoir établi qu’aucun code en cours n’y recourt.
Cette séquence prend plus de temps que de générer une instruction ALTER TABLE, mais elle isole les échecs. Si le nouveau code se comporte mal avant la suppression, l’ancien chemin existe toujours. Si une complétion prend du retard, elle peut s’arrêter sans bloquer la livraison de l’application. Si le déploiement revient en arrière, l’ancienne application reconnaît encore la base. Une livraison supplémentaire coûte moins cher que découvrir pendant un retour arrière que le binaire précédent interroge une colonne déjà supprimée par la migration.
Les renommages demandent une attention particulière, car PostgreSQL change le nom immédiatement. Un générateur peut proposer de renommer customer_ref en customer_id parce que le nouveau nom est plus clair. Les anciennes instances échoueront dès la validation de la migration. Ajoutez customer_id, gardez les deux champs synchronisés dans le code de l’application ou avec un déclencheur étroitement examiné, migrez les lecteurs, puis supprimez customer_ref seulement après la disparition des anciens écrivains. Cette duplication temporaire est une dette visible avec une condition de suppression. Un renommage immédiat crée un couplage de livraison invisible.
Les valeurs par défaut et les contraintes non nulles peuvent aussi cacher du travail. Avant d’approuver SET NOT NULL, comptez les valeurs nulles existantes et prouvez que chaque écrivain actif fournit une valeur. Pour les tables grandes ou très utilisées, examinez comment la version de PostgreSQL valide la contrainte et quels verrous elle prend. Un générateur doit signaler ces préconditions plutôt que les déduire d’un schéma sans trafic représentatif.
Les complétions de données ne doivent pas se faire dans une transaction de schéma sans limite. Mettez à jour les lignes par lots mesurés au moyen d’un worker approuvé, enregistrez la progression avec un curseur stable et rendez les nouvelles tentatives idempotentes. Une nouvelle tentative est idempotente si l’appliquer deux fois produit l’état voulu, pas seulement si PostgreSQL accepte la seconde requête. Pour les valeurs dérivées, enregistrez la version de dérivation si un code ultérieur peut les calculer autrement.
Le dossier de livraison doit nommer quatre points de compatibilité :
- La plus ancienne version de l’application autorisée à fonctionner avant la migration.
- L’état du schéma accepté par les anciennes et les nouvelles versions.
- Le signal qui autorise la livraison de nettoyage destructif.
- La voie de récupération si le nouveau code revient en arrière après une modification des données.
Les requêtes générées doivent éviter SELECT * pendant ces transitions. L’ajout d’une colonne peut modifier le coût de parcours, le décodage des résultats, l’association par position et l’exposition des données, même si l’ancien SQL reste valide. Énumérez explicitement les colonnes qualifiées et générez les décodeurs depuis le même instantané de schéma. La revue du code révèle alors exactement quelles données franchissent la limite de la base.
Les outils de migration préparés enregistrent souvent une version appliquée dans une table, mais un numéro de version seul ne prouve pas la compatibilité. Enregistrez le condensat de l’artefact SQL exact, car deux fichiers ayant le même nom convivial peuvent contenir des commandes différentes. L’exécuteur doit refuser une version déjà enregistrée avec un condensat différent. Il doit aussi refuser une migration ultérieure lorsqu’un prédécesseur nécessaire manque.
Ne laissez pas chaque instance de l’application exécuter les migrations au démarrage. Même lorsqu’un outil de migration utilise un verrou consultatif, le démarrage dépend alors d’un identifiant privilégié et de la fin du travail de schéma avant l’expiration des vérifications de santé. Exécutez les migrations dans une seule tâche de livraison, attendez son résultat enregistré et démarrez les instances d’exécution avec une identité qui ne peut pas modifier le schéma. Si le système de livraison ne peut pas séparer ces phases, corrigez-le avant d’accorder à l’application des pouvoirs de propriétaire.
Testez cette chronologie, pas seulement l’arrivée : ancien code sur ancien schéma, ancien code sur schéma étendu, nouveau code sur schéma étendu, puis code revenu en arrière après de nouvelles écritures. Le nettoyage reçoit son propre test plus tard. Cette matrice détecte les changements syntaxiquement valides mais impossibles à inverser en pratique.
Prouvez la limite avec des tests négatifs
Une conception de sécurité reste incomplète tant que les actions interdites n’échouent pas pendant les tests. Connectez-vous comme découverte et tentez une insertion, une création de table et un SET TRANSACTION READ WRITE. Connectez-vous comme exécution et tentez l’accès à une table sans droit, une lecture inter-locataires couverte par la sécurité des lignes et un changement de schéma. Le résultat attendu est une erreur de permission PostgreSQL, pas une promesse dans le journal d’un agent.
Lancez aussi des tests positifs. La découverte doit encore lire chaque entrée de catalogue autorisée. L’exécution doit effectuer chaque action utilisateur approuvée à travers le pool. L’exécution des migrations ne doit fonctionner que par le parcours d’approbation. Une limite qui bloque le travail normal du produit incitera quelqu’un à la remplacer par un identifiant de propriétaire pendant un incident.
Conservez un petit contrat d’accès à côté du code source de l’application. Il doit nommer la base, les schémas autorisés, le périmètre de découverte, les opérations d’exécution, le mode du pool, la politique de délais, les approbateurs de migration, la méthode d’empreinte de schéma et les instructions interdites. Comparez les droits réels à ce contrat dans des vérifications continues. La dérive des droits PostgreSQL est une dérive de configuration, même si personne n’a modifié le code de l’application.
Vérifiez de nouveau après des changements de rôle, de nouvelles tables, des bases restaurées, des mises à niveau du pool et des changements d’hébergement. Les privilèges par défaut comptent pour les futurs objets : accorder SELECT ON ALL TABLES couvre les tables actuelles, pas celles créées plus tard. Décidez si les nouveaux objets doivent rester invisibles jusqu’à leur revue ou être inclus par des privilèges par défaut configurés avec précision. Je préfère les rendre invisibles par défaut, car un droit explicite oblige à intégrer la nouvelle table à la discussion sur les accès.
Incluez la révocation dans le plan de test. Désactivez l’identifiant de découverte et confirmez que le trafic d’exécution continue. Désactivez l’exécution et confirmez que l’outil de migration ne remplace pas silencieusement son identité par une identité plus puissante. Faites ensuite tourner chaque secret pendant que les connexions sont actives et observez si le pool retire les anciennes sessions dans le délai prévu. Un changement de mot de passe ne termine pas les sessions déjà authentifiées : les procédures de rotation ont besoin d’un recyclage explicite du pool ou d’une politique de terminaison des sessions PostgreSQL.
Examinez les messages d’erreur afin d’éviter toute divulgation accidentelle pendant ces tests. Les erreurs PostgreSQL peuvent inclure des noms de relations, des fragments de SQL, des noms de contraintes et des valeurs fournies. Envoyez les erreurs détaillées vers des journaux serveur restreints, renvoyez une erreur publique stable aux clients et ne transmettez jamais l’intégralité d’un flux d’erreurs de production à une conversation avec un agent. Le générateur a besoin de l’emplacement de l’instruction et d’une réponse de base assainie pour corriger le code, pas des valeurs des clients.
Un dernier test détecte un nombre surprenant d’intégrations peu sûres : retirez complètement l’identifiant de migration et lancez la suite de tests de l’application. Si le démarrage normal, les vérifications de santé, les prévisualisations ou le traitement des requêtes échouent, la propriété du schéma a fui dans le chemin d’exécution. Corrigez ce couplage avant de connecter le générateur à la production. Un générateur d’applications IA peut fonctionner avec une base qu’il ne possède pas, mais PostgreSQL doit pouvoir dire non lorsque le code généré oublie cet arrangement.
FAQ
Un générateur d’applications IA peut-il utiliser ma base PostgreSQL existante ?
Oui, à condition que l’outil se connecte avec des rôles dédiés et ne découvre que les schémas approuvés. Séparez la découverte, les requêtes d’exécution et les migrations dans des parcours d’autorisations distincts afin que la connexion de l’outil ne lui donne pas la propriété du schéma.
Un utilisateur PostgreSQL en lecture seule garantit-il qu’aucune donnée ne peut changer ?
Un rôle qui n’a que SELECT et ne possède aucun objet constitue le contrôle principal. default_transaction_read_only ajoute une protection, mais ne doit pas compenser des droits trop larges ou une appartenance héritée.
Dois-je donner au générateur le mot de passe du propriétaire de ma base ?
Non. Un identifiant de propriétaire supprime la limite et permet au SQL généré de modifier les droits, les tables et les données. Créez des identifiants distincts pour la découverte, l’exécution et la tâche de migration contrôlée.
Comment un générateur d’applications peut-il apprendre mon schéma en toute sécurité ?
Autorisez-le à interroger les vues approuvées de information_schema et pg_catalog au moyen d’un rôle limité, puis enregistrez un instantané avec empreinte. Évitez les échantillons de lignes, sauf si une vue masquée a été préparée à cet effet.
Que se passe-t-il lorsque l’IA invente une colonne PostgreSQL ?
La génération doit échouer par rapport à un instantané de schéma typé avant le déploiement. Signalez le nom inconnu et les noms valides proches, mais laissez une personne décider si la correction relève du code, d’une nouvelle découverte ou d’une migration approuvée.
L’application peut-elle se connecter directement depuis un navigateur ou une application mobile ?
Il ne doit pas se connecter directement à PostgreSQL, car ces clients ne peuvent pas garder un mot de passe de base de données secret. Placez l’accès à la base dans un processus serveur et laissez le navigateur ou l’application mobile appeler son API.
Ai-je besoin d’un pool de connexions pour les applications générées ?
En général, oui, mais configurez-le avec soin. Limitez le nombre total de sessions, choisissez le mode session ou transaction, réinitialisez l’état modifiable et testez le code généré avec le même pool qu’en production.
Les migrations PostgreSQL peuvent-elles être annulées sans risque ?
Certains changements de catalogue s’inversent proprement dans une transaction, mais pas les pertes de données ni les effets externes. Examinez séparément le SQL d’application et de retour arrière, et considérez les instantanés comme des outils de récupération, pas comme la preuve qu’un changement est sûr.
Comment empêcher le générateur de modifier des tables non approuvées ?
Utilisez des listes de schémas autorisés, des noms qualifiés, des droits limités, une politique SQL analysée et des tests négatifs de permissions. Le rôle PostgreSQL doit refuser l’opération même si le modèle ou le vérificateur de politique se trompe.
À quelle fréquence le générateur doit-il redécouvrir le schéma ?
Redécouvrez le schéma chaque fois que l’empreinte enregistrée diffère, ainsi qu’après des migrations, des restaurations ou des changements d’environnement. Ne l’actualisez pas silencieusement pendant une livraison : montrez le diff et relancez la validation avec le nouvel instantané.