--- name: verify-mechanism description: > 「効いているはず」の機構が本当に効いているかを対照実験で確かめる。 分離・権限・フィルタ・認可・マスク・キャッシュ・レート制限・索引・発火条件など、 何かを「制限する」「守る」「速くする」仕組みを実装または設定した直後に必ず使う。 「RLS を入れた」「権限を絞った」「マスクした」「テストが通った」「設定した」 「ちゃんと効いてる?」「本当に動いてる?」といった場面で起動する。 肯定側のテストだけでは機構の証明にならないため、機構を外した対照を作って 期待どおり失敗することを確かめ、差が出なければ効いていないと判定する。 ユーザーが「確かめて」と言わなくても、防御的な機構を書いた直後なら検討する。 allowed-tools: Read, Grep, Glob, Bash, Write, Edit --- # 効いていることを確かめる 「設定した」と「効いている」は別物になる。 両者を分けるのは実測だけで、定義を読んでも成功メッセージを見ても区別できない。 ## なぜ肯定側のテストでは足りないか 守る仕組みを検証するとき、素直に書くと肯定側だけを見る。 これは通ってしまう。機構が無くても通る。 | 機構 | 肯定側のテスト | なぜ証明にならないか | |---|---|---| | テナント分離 | 自テナントの行が取れる | 分離が無くても取れる | | 発火条件 | 発火すべきでない入力で発火しない | 何も発火しなくても通る | | マスク処理 | 伏せ字の値が出力に含まれる | 元の値も一緒に出ていても通る | | 権限の制限 | 許可した操作ができる | 何も制限していなくてもできる | | キャッシュ | 2 回目も正しい値が返る | キャッシュを引いていなくても返る | 共通するのは、**機構が存在しない世界でも同じ結果になる**ことになる。 差が出ない検証は、何も検証していない。 ## 手順 ### 1 何を約束しているかを書き出す コード上のコメント、設定ファイル、ドキュメント、コミットメッセージが 何を保証すると述べているかを、1 文で書き出す。 「WHERE 句を間違えても他テナントに届かない」 「API キーがログに出ない」 「2 ページ目に溢れない」 曖昧なままだと、次のステップで何を壊せばよいかが決まらない。 ### 2 その約束が崩れる条件を洗い出す 多くの機構には、設計上のバイパス経路がある。 知らずに使うと「設定したのに効かない」が起きる。 代表的なものは [references/bypass-conditions.md](references/bypass-conditions.md) にまとめてある。 対象の機構が載っていれば先に読む。載っていなければ公式ドキュメントで 「いつ無効になるか」を探す。有効化の手順より先にこちらを読む。 ### 3 対照を作る 機構が効かない状態を意図的に作り、**期待どおり失敗することを確かめる**。 - 分離なら、別テナントのデータを混ぜて他方から見えるかを見る - マスクなら、実際の秘密を入れて出力に平文が混ざらないかを見る - 発火条件なら、発火すべき入力を投げて実際に発火するかを見る - 制限なら、制限を超える入力を投げて拒否されるかを見る ここで作るのは「壊れた状態」であって、テストが落ちるのが正しい。 落ちなければ機構は効いていない。 ### 4 両方を測って差を見る 機構ありと機構なしで、同じ入力に対する結果を並べる。 差が出なければ、その機構は結果に影響していない。 設定が入っていても、有効化されていないか、バイパスされているか、 そもそも別の何かが仕事をしている。 ### 5 集計値ではなく内訳を見る 合格率やスコアは、失敗の形を隠す。 発火率の測定で「4/8 通過」という数字が出たことがある。 内訳を見ると、通過したのは全部「発火すべきでない」側で、 **発火すべき側は 1 件も通っていなかった**。何も発火していなかった。 集計値だけを見ていれば「半分は当たっている」と読める。 内訳を見れば「機構が一度も動いていない」と分かる。 ### 6 形式固有の指標を測る 目で見て正しくても、その形式の要件を満たしていないことがある。 見えている範囲しか目視は検証しない。 [references/format-metrics.md](references/format-metrics.md) に形式ごとの指標を挙げてある。 ### 7 テストで固定する 確かめた事実は、次に触る人が壊せる。特に次の 2 つを固定する。 **機構が効いていること** 対照側が失敗することをテストにする。 **設定漏れが安全側に倒れること** 設定を外した状態で「何も見えない」 「拒否される」になるかを確かめる。「全部見える」に倒れる設計は、 運用中の設定ミスがそのまま事故になる。 ## 判定 次のいずれかに当てはまれば、機構は効いていない。 - 機構あり/なしで結果に差が出ない - 対照(壊れた状態)でテストが落ちない - 集計値は良いのに、内訳の片側が全滅している - 「設定した」ことは確認できるが、「その設定が結果を変えた」証拠がない ## 実例 今日この手順で見つかった 4 件を挙げる。すべて「設定済み」に見えていた。 **Row Level Security が一度も効いていなかった** `ENABLE ROW LEVEL SECURITY` とポリシーは入っていた。 だが接続ユーザーが superuser で、PostgreSQL は superuser に対して RLS をバイパスする。 `FORCE ROW LEVEL SECURITY` を足しても superuser には効かない。 分離を担っていたのは `WHERE tenant_id = %s` だけだった。 対照(別テナントの行を混ぜて読む)で 2 件返ったことで判明した。 **発火率の測定が一度も発火していなかった** スコア 4/8 は「発火すべきでない」8 件中 4 件が自動的に正解になっただけだった。 内訳を見るまで、それらしい数字に見えていた。 **PDF が 2 ページに割れていた** 画面キャプチャでは正しく見えた。A4 の紙面境界が画像に写らないため、 3 回見逃した。ページ数を数えて初めて分かった。 **スキルがインストールされたが読み込まれていなかった** `✓ Installed` と表示された。ディレクトリ階層が 1 段深く、 探索対象から外れていた。エラーも警告も出なかった。 再起動後に一覧へ名前が出るかを見るまで気づけなかった。