{
  "format": "agent-article-v0",
  "article_id": "EA-282",
  "canonical_url": "/tools/ea-282-row-column-level-security-ai-analytics",
  "page_type": "reference",
  "claim_ids": [],
  "evidence_ids": [
    "EVD-EA-282-URL-B637184D645F",
    "EVD-EA-282-URL-FD37AFDDBD22",
    "EVD-EA-282-URL-C5F2C6C39C63",
    "EVD-EA-282-URL-61002B66107F",
    "EVD-EA-282-URL-FB87768384BB",
    "EA-282-CURRENT-APPROVAL",
    "EA-282-CURRENT-BODY-READBACK"
  ],
  "unknown_ids": [
    "EA-282-UNKNOWN-01"
  ],
  "operational_object_ids": [],
  "provider": [],
  "models": [],
  "plans": [],
  "surfaces": [],
  "regions": [],
  "current_status": "CURRENT",
  "observation_status": "SPEC_ONLY",
  "freshness": "CURRENT",
  "last_verified": "2026-10-20",
  "supersedes": [],
  "superseded_by": [],
  "provenance": [
    "MANUAL-EA282-DRAIN-20261020-C1",
    "SRC-EA-282-URL-B637184D645F",
    "SRC-EA-282-URL-FD37AFDDBD22",
    "SRC-EA-282-URL-C5F2C6C39C63",
    "SRC-EA-282-URL-61002B66107F",
    "SRC-EA-282-URL-FB87768384BB",
    "BODY-SHA256:b27577b39b57836f206cec52a694532706e142244989ce6b6905a8da8ce3bb1f"
  ],
  "article_sources": [
    {
      "id": "EVD-EA-282-URL-B637184D645F",
      "evidence_class": "RESEARCH",
      "title": "[S1] PostgreSQL 18 Row Security Policies:",
      "href": "https://www.postgresql.org/docs/18/ddl-rowsecurity.html",
      "supports": [],
      "limit": "元の監査済み資料に記載された参照先です。URLの復元は、資料の最新性や全主張の支持を新たに検証したことを意味しません。",
      "origin_class": "SOURCE_PACKET_REFERENCE",
      "source_or_experiment_ids": [
        "SRC-EA-282-URL-B637184D645F"
      ],
      "supporting_locators": [
        "出典・provenance",
        "S1",
        "- [S1] PostgreSQL 18 Row Security Policies: https://www.postgresql.org/docs/18/ddl-rowsecurity.html"
      ],
      "scope": "出典・provenance",
      "provenance_status": "SOURCE_PACKET_REFERENCE_PROJECTED"
    },
    {
      "id": "EVD-EA-282-URL-FD37AFDDBD22",
      "evidence_class": "RESEARCH",
      "title": "[S2] PostgreSQL 18 Privileges:",
      "href": "https://www.postgresql.org/docs/18/ddl-priv.html",
      "supports": [],
      "limit": "元の監査済み資料に記載された参照先です。URLの復元は、資料の最新性や全主張の支持を新たに検証したことを意味しません。",
      "origin_class": "SOURCE_PACKET_REFERENCE",
      "source_or_experiment_ids": [
        "SRC-EA-282-URL-FD37AFDDBD22"
      ],
      "supporting_locators": [
        "出典・provenance",
        "S2",
        "- [S2] PostgreSQL 18 Privileges: https://www.postgresql.org/docs/18/ddl-priv.html"
      ],
      "scope": "出典・provenance",
      "provenance_status": "SOURCE_PACKET_REFERENCE_PROJECTED"
    },
    {
      "id": "EVD-EA-282-URL-C5F2C6C39C63",
      "evidence_class": "RESEARCH",
      "title": "[S3] pgvector README, Filtering／Multitenancy／Iterative Index Scans:",
      "href": "https://github.com/pgvector/pgvector",
      "supports": [],
      "limit": "元の監査済み資料に記載された参照先です。URLの復元は、資料の最新性や全主張の支持を新たに検証したことを意味しません。",
      "origin_class": "SOURCE_PACKET_REFERENCE",
      "source_or_experiment_ids": [
        "SRC-EA-282-URL-C5F2C6C39C63"
      ],
      "supporting_locators": [
        "出典・provenance",
        "S3",
        "- [S3] pgvector README, Filtering／Multitenancy／Iterative Index Scans: https://github.com/pgvector/pgvector"
      ],
      "scope": "出典・provenance",
      "provenance_status": "SOURCE_PACKET_REFERENCE_PROJECTED"
    },
    {
      "id": "EVD-EA-282-URL-61002B66107F",
      "evidence_class": "RESEARCH",
      "title": "[S4] pgvector Issue #719:",
      "href": "https://github.com/pgvector/pgvector/issues/719",
      "supports": [],
      "limit": "元の監査済み資料に記載された参照先です。URLの復元は、資料の最新性や全主張の支持を新たに検証したことを意味しません。",
      "origin_class": "SOURCE_PACKET_REFERENCE",
      "source_or_experiment_ids": [
        "SRC-EA-282-URL-61002B66107F"
      ],
      "supporting_locators": [
        "出典・provenance",
        "S4",
        "- [S4] pgvector Issue #719: https://github.com/pgvector/pgvector/issues/719"
      ],
      "scope": "出典・provenance",
      "provenance_status": "SOURCE_PACKET_REFERENCE_PROJECTED"
    },
    {
      "id": "EVD-EA-282-URL-FB87768384BB",
      "evidence_class": "RESEARCH",
      "title": "歴史的所在記録:",
      "href": "https://docs.google.com/document/d/1Vd0BP7G2UyPDRQs_-8dPvTgQ78Tk6kcVGuMJjqNdr84/edit",
      "supports": [],
      "limit": "元の監査済み資料に記載された参照先です。URLの復元は、資料の最新性や全主張の支持を新たに検証したことを意味しません。",
      "origin_class": "SOURCE_PACKET_REFERENCE",
      "source_or_experiment_ids": [
        "SRC-EA-282-URL-FB87768384BB"
      ],
      "supporting_locators": [
        "出典・provenance",
        "- 歴史的所在記録: https://docs.google.com/document/d/1Vd0BP7G2UyPDRQs_-8dPvTgQ78Tk6kcVGuMJjqNdr84/edit"
      ],
      "scope": "出典・provenance",
      "provenance_status": "SOURCE_PACKET_REFERENCE_PROJECTED"
    },
    {
      "id": "EA-282-CURRENT-APPROVAL",
      "evidence_class": "RESEARCH",
      "title": "現行本文の監査・revision対応",
      "supports": [
        "現行台帳のAUDIT_PASSと候補・revision・本文ハッシュの対応を確認しています。"
      ],
      "limit": "監査状態と来歴の記録です。外部根拠の最新性や本文の全主張を追加保証しません。",
      "origin_class": "AUDITED_CANONICAL_RESEARCH_PACKET",
      "source_or_experiment_ids": [
        "MANUAL-EA282-DRAIN-20261020-C1"
      ],
      "supporting_locators": [
        "1KqhJtiSb2S84rWmeYVwKcT_76dBwZ_B0ZZuAWQqH0rQ/EA_REVISION_LEDGER#ea_id=EA-282&revision_id=EA-282-RESEARCH-20261020-R1&candidate_id=MANUAL-EA282-DRAIN-20261020-C1",
        "EA-282-RESEARCH-20261020-R1"
      ],
      "provenance_status": "CURRENT_CANONICAL_APPROVAL_READBACK"
    },
    {
      "id": "EA-282-CURRENT-BODY-READBACK",
      "evidence_class": "IMPL",
      "title": "現行本文の収録照合",
      "supports": [
        "公開生成入力の本文SHA-256が、監査済み候補に結び付いたハッシュと一致しています。"
      ],
      "limit": "本文の同一性の検査です。外部システムの挙動や全主張の真偽を実証したものではありません。",
      "checked_at": "2026-10-21",
      "origin_class": "IMPLEMENTATION_READBACK",
      "source_or_experiment_ids": [
        "BODY-SHA256:b27577b39b57836f206cec52a694532706e142244989ce6b6905a8da8ce3bb1f"
      ],
      "supporting_locators": [
        "content/staging/EA-282.md",
        "b27577b39b57836f206cec52a694532706e142244989ce6b6905a8da8ce3bb1f",
        "EA-282-RESEARCH-20261020-R1"
      ],
      "provenance_status": "CURRENT_APPROVED_BODY_HASH_MATCH"
    }
  ],
  "research_sections": [
    {
      "heading": "要点と前提",
      "text": "自然言語で分析するAIは、質問をSQLや検索条件へ変換してデータを取り出す。行単位のセキュリティ（RLS）は閲覧・変更できるレコードを制限し、列単位の権限は取り出せる属性を制限する。どちらも、AIが生成した説明文やWHERE条件を信用して実現するものではない。実際にデータを実行・取得する主体の権限と、データ基盤が強制する条件で成立させる。\n\nたとえば営業分析では、担当顧客の売上行は見せても、全顧客の売上や個人の口座番号は見せないという要件がある。利用者が「全社集計」と入力したとき、AIがそれらしいSQLを作れることと、利用者にその分析権限があることは別である。プロンプトで機密列を使わないよう依頼しても、広いDB権限が残っていれば確実な境界にはならない。"
    },
    {
      "heading": "三つの主体を対応させる",
      "text": "認証された利用者、AIアプリのサービスID、DBに接続するロールは同一とは限らない。全利用者が一つの管理者接続を共有すると、DBは利用者ごとの違いを認識できず、アプリが後から行を隠す設計へ依存する。取得後の削除では、ログ、モデル入力、エラー内容へすでに情報が入った可能性がある。\n\n本稿では、利用者の所属・権限をサーバーで確定し、それに対応した実行主体または信頼できる認可コンテキストをデータ層へ伝える構成を提案する。接続プールを使う場合、前の利用者のロールやセッション変数が次の要求へ残らないよう、設定・解除・トランザクション境界を確認する。利用者や生成SQLが任意に変更できる属性を、そのまま唯一の認可根拠にしない。"
    },
    {
      "heading": "RLSと列権限は別に設計する",
      "text": "PostgreSQL 18の資料では、RLSを有効化して適用ポリシーがない場合は通常アクセスを拒否する。一方、superuserやBYPASSRLS、通常のテーブル所有者には適用上の例外があり、所有者への強制にはFORCE ROW LEVEL SECURITYが関わる。[S1] 「RLSを設定した」という記録だけでは足りず、アプリの実ロールでその制御が働くかを調べる。\n\n列権限はRLSと独立する。PostgreSQLのGRANT体系では、SELECTなどを表全体または特定列に付与できる。[S2] たとえば担当顧客の行だけを許可しても、その行の機密列まで自動的に隠れるわけではない。表全体への権限、所属ロールからの継承、ビューや関数を経由する経路も合わせて確認する。\n\n| 設計点 | 制御の例 | AI分析での確認 |\n|---|---|---|\n| 行の範囲 | 担当者・部門・テナントに応じたポリシー | WHERE句を省略・改変しても越境しない |\n| 列の範囲 | 許可列だけのSELECT権限、用途別の公開面 | SELECT *、別名、計算式、関数で抜けない |\n| 操作の範囲 | 読み取り主体、許可されたクエリ経路 | 生成SQLが書込み・管理操作を起こさない |\n| 結果の範囲 | 件数・時間・出力サイズ・集計の制約 | 大量抽出や繰返し質問による再構成を検討 |\n| 下流への伝播 | 認可済み結果だけをモデル・出力へ渡す | キャッシュ、CSV、トレースでも同じ範囲を守る |\n\nこれは制御の組合せの提案であり、SQLを機械的に禁止語チェックすれば実現できるという意味ではない。SQL方言に対応した構文解析、許可されたデータ面、DB権限、実行時間の制限を重ね、解析器だけに全責任を負わせない。"
    },
    {
      "heading": "別の実体へコピーした後の権限",
      "text": "DBの行や列を埋め込み索引、分析用のマテリアライズドデータ、会話要約へコピーすると、元のDBの制御がコピー先にも自動で付くとは限らない。RAGのチャンクに元行の所有者と認可情報を保持し、検索時に現在の利用者で判定する。列の組合せから機密情報を再構成できる場合、単純な列名の禁止では対応できない。\n\n回答の根拠としてモデルへ渡した時点で、データは別の処理面へ移る。最終文面をマスクするだけでは、モデル入力や保存トレースでの露出を防げない。必要な行・列を取得段階で絞り、回答キャッシュやダウンロードも同じ権限範囲へ結び付ける。権限失効後に過去の回答を再表示できるかも、会話サービス側で別に判断する。"
    },
    {
      "heading": "検索品質の低下を権限解除で直さない",
      "text": "ベクトル検索で認可フィルタを付けると結果件数が減ることがある。pgvectorの作者管理資料は、近似索引の走査後にフィルタが適用されるため、条件付き検索で必要件数に届かない場合と、対応版の反復走査やパーティション等の選択肢を説明する。[S3] これは「権限制御が壊れた」「禁止行を返している」という証拠ではなく、許可範囲内の検索品質・性能の課題として扱う。\n\nIssue #719にも、条件付き近似検索で結果が得られないという実利用者の報告と、資料に沿った調整を案内する保守者の応答がある。[S4] 設定変更の効果はデータ分布やクエリに依存する。対策として、許可範囲内の厳密検索との比較、対象区画の分割、走査予算の調整を検討する。応答が空だから認可フィルタを外して再検索するという処理は、品質改善と引き換えに情報境界を破る。"
    },
    {
      "heading": "具体的な失敗と復旧",
      "text": "導入時のテストを所有者ロールで行うと、本番の制限ロールと違う結果になる。逆にアプリが所有者で接続していることに気付かず、正常系だけを見てRLS適用済みと判断する場合もある。実ロール、ロール継承、実行したポリシー、認可コンテキストを記録し、許可と拒否を対で検証する。\n\nエクスポート処理だけ別の広い資格情報を使うと、画面の分析結果は正しくても、ダウンロードしたCSVに全件が入る。表示、集計、CSV、非同期レポートを同じ認可入口へ通す。誤配信が起きた場合は、キャッシュと配布物を失効させ、対象範囲をログから特定し、資格情報・権限を修正して再試験する。SQLテンプレートだけの修正で閉じない。\n\n集計値も無条件に安全ではない。小さな集団の合計や、条件を少しずつ変えた差分から個別値を推測できる場合がある。匿名化・統計的開示制御はRLS・列権限とは別の課題であり、必要な業務では集計単位や繰返し照会の扱いを設計する。「個票を出していない」という説明だけで秘匿を保証しない。"
    },
    {
      "heading": "受入れ・反証・適用境界",
      "text": "模擬データで、利用者A/B、管理者、ジョブ主体を分け、行の越境、機密列、権限継承、セッション再利用、直接ID指定、出力キャッシュ、エクスポートを試す。ポリシー変更や権限失効を挟んだ並行処理も調べる。DBポリシーの名称や構文だけの照合では、実効権限を確認できない。\n\nPostgreSQLの仕様を、クラウド分析基盤やBI製品へそのまま当てはめない。ポリシーの適用主体、所有者・管理者の例外、ビュー・関数・外部表の扱いは製品別に確認する。DBが正しく拒否しても、すでにモデルや会話へ渡した内容を取り戻すことはできないため、取得前の認可が必要である。"
    },
    {
      "heading": "OPEN_UNKNOWN",
      "text": "- 対象DB・版・ロール・ビュー・関数・プール方式・権限同期・集計開示条件は未取得。\n- RLS・列権限、生成SQL、セッション漏れ、失効、キャッシュ、CSV、検索再現率の実試験はNOT_RUN。\n- 先行Luna完成本文は確認できず、旧記録は所在確認のprovenanceとして残す。"
    },
    {
      "heading": "SAFE_WORDING",
      "text": "「実行主体とデータ基盤のポリシーで取得可能な行・列を制限し、AI入力と下流出力にも同じ権限を保つ」。一方、「プロンプトに権限を書けば十分」「RLSがあれば列も匿名化される」「結果0件ならフィルタを外す」「DB設定済みなので出力全体も安全」とはしない。"
    },
    {
      "heading": "出典・provenance",
      "text": "2026-10-20に一次資料を確認。工程表と失敗例は本稿の設計提案。DBの例はPostgreSQL 18資料の範囲であり、実環境の導入を示さない。\n\n- [S1] PostgreSQL 18 Row Security Policies: https://www.postgresql.org/docs/18/ddl-rowsecurity.html （通常適用と権限上の例外）\n- [S2] PostgreSQL 18 Privileges: https://www.postgresql.org/docs/18/ddl-priv.html （表・列単位の権限）\n- [S3] pgvector README, Filtering／Multitenancy／Iterative Index Scans: https://github.com/pgvector/pgvector （フィルタと近似検索の境界。実使用版の確認が必要）\n- [S4] pgvector Issue #719: https://github.com/pgvector/pgvector/issues/719 （報告と保守者コメント、2025-02-20／24。全構成への性能保証ではない）\n- 歴史的所在記録: https://docs.google.com/document/d/1Vd0BP7G2UyPDRQs_-8dPvTgQ78Tk6kcVGuMJjqNdr84/edit 、tab=t.0:21984–23383、特に22491–22588。GX02検索結果をLuna成果へ誤帰属していない。"
    }
  ],
  "human_url": "/tools/ea-282-row-column-level-security-ai-analytics",
  "markdown_url": "/agent/article.md?path=%2Ftools%2Fea-282-row-column-level-security-ai-analytics",
  "json_url": "/agent/article.json?path=%2Ftools%2Fea-282-row-column-level-security-ai-analytics"
}