Postgres、PostGraphile、RLSおよびSQL
概要
このスタックのデータ層メカニズムです。多層防御(RLSを最終壁とする)および唯一の正規データパスを実装します。スタック固有の内容であり、PostGraphile/Postgresを使用しないプロジェクトには適用されません。
データパス
ブラウザ → アプリサーバー → PostGraphile → PostgreSQL。 唯一の正規パスです。
- ブラウザはGraphQL/DBと直接通信しません。アプリはアプリケーションデータのためにDBに直接問い合わせしません。
- アプリはセッションコンテキストをヘッダとしてのみ(ユーザーID、組織ヒント)渡します。アプリ内に認可ロジックはありません。コンテキストは下流で検証され、信頼されません。
- 単一パス = 認証コンテキスト、検証、およびRLSを強制する単一の場所です。サイドチャネルは強制を回避する穴です。
セキュリティルール
- RLSは最終適用層です。 アプリ層のチェックはUXであり、データベースが壁です。上位層のバグがあっても、他のテナントの行が漏洩することはありません。
- ロールは実際のセッション状態をモデル化します — 未ログイン、組織なしログイン、組織ありログイン、接続専用ロール、マイグレーション専用ロール。ロールには意味があります。
- 特権接続ロールはアプリケーションクエリを実行しません。 アプリクエリは制約されたRLS対象ロールの下で実行されます。
SECURITY DEFINER関数は定義内でsearch_pathをインライン設定します — 毎回、例外なく。- 欠損は
NULLであり、空文字列ではありません。 空文字列センチネルは禁止されています。欠損時は値を省略します。 - GraphQLはDoS面です — 制限をかけます。 クエリ深さ制限およびコスト/複雑性分析を強制し、予算超過クエリを拒否します。ページネーションサイズに上限を設けます。アプリロールにDBの**
statement_timeout**を設定します。意図的に必要としない限り、プロダクションでイントロスペクションを無効化します。
SQLスタイル
- 1ファイル1オブジェクト — 各テーブル、関数、ポリシー、GRANTはそれぞれ独自のファイルに。
schema/object_type/nameで構成 — ディレクトリはデータベースの構成を反映します。- インクルード順序は依存順序です。 インクルードマニフェストが目次です。
- インラインで文書化します。
COMMENT ONはオブジェクトと同じファイルにあります — 何をそしてなぜ。 - 説明的なエイリアス(テーブル名の単数形、単一文字ではない)。Postgresの慣用に従います(
current_*ゲッター)。 - 型およびユーザー向けロールはデータであり、ハードコードされた制約ではありません — キー/ラベル/説明を持つルックアップテーブル、FKで検証、スキーマ変更なしで拡張可能。
クイックリファレンス
| ルール | チェック内容 |
|---|---|
新しいSECURITY DEFINER関数 | search_pathがインライン設定されているか? |
| テナントデータを持つ新しいテーブル | RLSポリシー + 拒否テスト(graphql-contract-testingを参照)? |
| 欠損値 | NULLであり、''ではないか? |
| 新しいGraphQL面 | 深さ/コスト制限およびページネーション上限があるか? |
| 新しいオブジェクト | 独自ファイル、依存順インクルード、インラインCOMMENT ONがあるか? |
完全な根拠: 憲法第XIII、XIV、XVIII条、engineering-constitution/references/engineering-constitution.mdにバンドル。マイグレーション: zero-downtime-migrations。コントラクトテスト: graphql-contract-testing。