Postgres, PostGraphile, RLS et SQL
Aperçu
Mécanisme de la couche de données pour cette stack. Implémente la défense en profondeur (RLS comme dernier rempart) et le chemin de données unique légal. Spécifique à la stack — ne s'applique pas aux projets sans PostGraphile/Postgres.
Le Chemin de Données
Navigateur → Serveur d'application → PostGraphile → PostgreSQL. Exactement un chemin légal.
- Le navigateur ne communique jamais directement avec GraphQL/la base de données ; le serveur d'application n'interroge jamais la base de données directement pour les données applicatives.
- Le serveur d'application transmet le contexte de session uniquement comme en-têtes (id utilisateur, indication d'organisation) — aucune logique d'autorisation dans l'application ; le contexte est validé en aval, non considéré comme fiable.
- Un seul chemin = un seul endroit où imposer le contexte d'authentification, la validation et le RLS. Les canaux secondaires sont les trous qui contournent cette imposition.
Règles de Sécurité
- Le RLS est la couche d'imposition finale. Les vérifications au niveau applicatif sont de l'UX ; la base de données est le mur. Même un bogue dans les couches supérieures ne peut pas fuiter des lignes d'un autre locataire.
- Les rôles modélisent des états de session réels — non-connecté, connecté-sans-organisation, connecté-avec-organisation, un rôle de connexion uniquement, un rôle de migration uniquement. Les rôles ont une signification.
- Le rôle de connexion privilégié n'exécute jamais de requêtes applicatives. Les requêtes applicatives sont exécutées sous un rôle contraint, soumis au RLS.
- Les fonctions
SECURITY DEFINERdéfinissentsearch_pathdirectement dans leur définition — à chaque fois, sans exception. - L'absence est
NULL, jamais une chaîne vide. Les sentinelles à chaîne vide sont interdites ; omettre la valeur en cas d'absence. - GraphQL est une surface de déni de service — limitez-la. Imposez des limites de profondeur de requête et une analyse de coût/complexité ; rejetez les requêtes hors budget. Limitez la taille de la pagination. Définissez un
statement_timeoutpour les rôles applicatifs. Désactivez l'introspection en production sauf si délibérément nécessaire.
Style SQL
- Un objet par fichier — chaque table, fonction, politique, ensemble de privilèges dans son propre fichier.
- Organisé par
schéma/type_objet/nom— le répertoire reflète l'organisation de la base de données. - L'ordre d'inclusion suit l'ordre des dépendances ; le manifeste d'inclusion est la table des matières.
- Documentez en ligne.
COMMENT ONvit dans le même fichier que l'objet — quoi et pourquoi. - Alias descriptifs (singulier du nom de la table, pas de lettres uniques) ; suivez les idiomes Postgres (
current_*getters). - Les types et les rôles destinés à l'utilisateur sont des données, pas des contraintes codées en dur — tables de référence avec clé/libellé/description, validées par clé étrangère, extensibles sans changement de schéma.
Référence Rapide
| Règle | Vérification |
|---|---|
Nouvelle fonction SECURITY DEFINER | search_path défini en ligne ? |
| Nouvelle table avec données de locataire | Politique RLS + tests de refus (voir graphql-contract-testing) ? |
| Valeur absente | NULL, pas '' ? |
| Nouvelle surface GraphQL | Limite de profondeur/coût et limite de pagination ? |
| Nouvel objet | Fichier propre, inclusion triée par dépendance, COMMENT ON en ligne ? |
Raisonnement complet : Articles XIII, XIV, XVIII de la constitution, groupés dans engineering-constitution/references/engineering-constitution.md. Migrations : zero-downtime-migrations. Tests de contrat : graphql-contract-testing.