Claude Code自動承認ガードレール実装ハンドブック¶
実装検証に特化した昼版です。朝の記事: 朝の記事
この記事は朝の記事のフォローアップです
ゴール¶
- 自動承認ガードレールをCI前段で検証できる
- 許可/拒否リストの差分を即時追跡し監査できる
- ログと指標で自動承認の価値を定量評価できる
アーキテクチャ / フロー概要¶
Shift+Tab運用を軸に、①設定検証→②ログ収集→③監視の3層で統制する。CI冒頭でsettings.jsonを検証し、ログはS3互換ストレージへ置き、可視化は既存ダッシュボードを流用する。
実装ステップ¶
ステップ1: 設定ファイルをCIで検証する¶
許可/拒否リストが空のまま自動承認を走らせないよう、CI開始時に設定を検査する。permissions.denyが空ならジョブを止めるこのガードで、人為ミスを即ブロックできる。
#!/usr/bin/env bash
set -euo pipefail
CONFIG=${1:-$HOME/.claude/settings.json}
DENY_COUNT=$(jq '.permissions.deny | length' "$CONFIG")
if [[ "$DENY_COUNT" -eq 0 ]]; then
echo "deny list is empty; aborting auto-approval run" >&2
exit 42
fi
ステップ2: 拒否リスト差分を標準化する¶
拒否ルールの改変は事故を招くため、PR差分を定型化する。settings.jsonはコメント不可なのでmetadataに意図を残し、jqで整形して差分を一定にする。
{
"permissions": {
"metadata": {"owner": "platform-team","review_ticket": "SEC-4312","last_validated_at": "2025-10-30T03:00:00Z"},
"allow": ["Edit","MultiEdit","Bash(npm run lint)"],
"deny": [
"Bash(rm -rf *)",
"Bash(curl http://*)",
"Bash(python -c \"import os; os.system('rm -rf /')\")"
]
}
}
ステップ3: 自動承認の成果を可視化する¶
ログとメトリクスを分けて収集する。ログはauto-approval/YYYY/MM/DD/run-<timestamp>.jsonでS3互換ストレージへ、メトリクスはPushgatewayで処理時間やdenyヒットを追跡する。下記はログからdenyヒット数を抜き出し可視化基盤へ送る軽量スクリプト例。
#!/usr/bin/env python3
import json, sys
with open(sys.argv[1]) as f:
events = json.load(f)["events"]
hits = [e for e in events if e["action"] == "deny"]
print(f"deny_hits {len(hits)}")
ベンチマーク / 比較¶
| 条件 | 結果 | 所感 |
|---|---|---|
| 手動レビューのみ | 平均12分/タスク、誤検知0件 | 安全だが待機時間が長い |
| CIガード+自動承認 | 平均4分/タスク、denyヒット0.6件/日 | 時短しつつリスクが見える |
| CIガード+メトリクス | 平均4.5分/タスク、denyヒット0.2件/日 | 収集値で設定精度が向上 |
失敗パターンと回避策¶
| 症状 | 原因 | 回避 |
|---|---|---|
| jqが存在せずCIが停止 | ランナーに前提パッケージがない | 依存を追加し冒頭でjq --versionをチェック |
| denyヒットの解釈が属人的 | イベント形式が揺れている | JSONスキーマを定義しCIでログをLint |
| メトリクスが連携されない | Pushgatewayが閉じている | VPCエンドポイントと再送キューで補完 |
自動化 / 拡張案 (任意)¶
- denyルールの定期テストを
cronワークフローで自動実行 - Shift+Tab切替ログをブラウザ拡張で記録し週次レビューに添付
- 自動承認開始時にSlackへポリシー抜粋を通知するミドルウェア