powered by TechFeed
表示モード
Deep Dive

AIエージェントが本番DBを消す事故は「エージェントの失敗」ではない — Prisma 8が設計レベルで破壊的操作を封じるアプローチ

7月30日、Prismaが「Don't Let Your AI Agent Delete Your Production Database」と題した記事を公開した。この記事では、AIエージェントによる本番データベースの破壊的操作を、警告ではなく設計レベルで防ぐPrisma 8のアプローチについて詳しく解説している。

7月30日、Prismaが「Don't Let Your AI Agent Delete Your Production Database」と題した記事を公開した。この記事では、AIエージェントによる本番データベースの破壊的操作を、警告ではなく設計レベルで防ぐPrisma 8のアプローチについて詳しく解説している。


事故の構造:問題はエージェントではなくツールにある

ここ最近、AIコーディングエージェントが本番データベースを破壊する事故が相次いでいる。コードフリーズ中に本番DBを丸ごと消去スキーマ警告への対応として87テーブルをDROPRDSインスタンスをスナップショットごと削除——いずれも洒落にならない被害だ。

Prismaの見立てでは、これらはエージェントの問題ではなくツールの問題だ。従来のデータベースツールは「何をしているか理解した上で使え、データを失っても自己責任」という設計思想で作られてきた。エージェントはその落とし穴に、人間より素早く踏み込むだけである。

特に問題になるのが、**--force--accept-data-lossといった強制フラグ**だ。非インタラクティブ実行時に警告でブロックされると、ツール自身のエラーメッセージがその回避方法を教えてしまう:

Use --force to run this command without user interaction.
Use the --accept-data-loss flag to ignore the data loss warnings

エージェントの目標はゼロ終了コードを得ることなので、エラーメッセージに書いてある通りに動く。87テーブルが消えた事故もこの構造で起きた。.envが本番を向いており、ツールはそれを知りも確認もしなかった。


Prisma 8が採ったアプローチ:危険な操作をそもそも存在させない

Prisma 8では、スキーマをアプリケーションとデータベース間のコントラクト(契約)として扱う。データベースを変更するには、コントラクトを変更してPrismaにマイグレーションを生成・実行させる。この設計の結果として:

  • prisma migrate reset(DB全削除コマンド)が存在しない。表示されないプロンプトにyと答えることはできないし、提供されていない--forceフラグを使うこともできない。
  • db updateコマンドは、データを破壊する変更が生じる場合、非インタラクティブ実行時に構造化エラーを返して停止する。-yフラグで受け入れられるのは、その実行計画に列挙された具体的な操作のみであり、「何が消えても構わない」という白紙委任ではない。
# 非インタラクティブ時のエラー例
meta.destructiveOperations[] に破壊的操作が列挙されて返される

シャドウDBという「別の地雷」も除去

旧来のPrismaは、マイグレーション計画にシャドウデータベース(移行履歴を再生するための使い捨てDB)を必要としていた。このシャドウDBは実行開始時に無条件でワイプされる仕様で、接続文字列を誤ったフィールドに貼り付けると本番DBが静かに消える。ドキュメントには「urlshadowDatabaseUrlに同じ値を使わないこと」と警告があるだけだった。

これは仮定の話ではない。2026年7月末、あるエージェントセッション開始から10分で、開発者の本番Supabaseインスタンスの全テーブルが空になった

Prisma 8はシャドウDBを必要としない。マイグレーションは2つのコントラクトバージョンの差分比較によってオフラインで計算されるため、データベースへの接続すら不要だ。


マイグレーション自体の安全設計

Prisma 8のマイグレーションは、各操作にprecheckpostcheckを持つ構造になっている:

{
  "id": "column.user.phone",
  "label": "Add column \"phone\" to \"user\"",
  "operationClass": "additive",
  "precheck": [
    {
      "description": "ensure column \"phone\" is missing",
      "sql": "SELECT NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE …)"
    }
  ],
  "execute": [
    {
      "description": "add column \"phone\"",
      "sql": "ALTER TABLE \"user\" ADD COLUMN \"phone\" text"
    }
  ],
  "postcheck": [
    {
      "description": "verify column \"phone\" exists",
      "sql": "SELECT EXISTS (SELECT 1 FROM information_schema.columns WHERE …)"
    }
  ]
}

precheckは操作前にDBが期待通りの状態かを確認し、postcheckが失敗すればマイグレーションはDBを変更せずに中止する。また各操作はadditivewideningdatadestructiveのいずれかに分類され、CIポリシーやエージェントがプログラムから参照できる。

さらに各DBにはマーカー(どのコントラクトバージョンを満たしているかの記録)が埋め込まれ、.envの向き先が違う、接続文字列が誤っている、マイグレーションが途中で止まったといった状況を検出して実行を拒否する。


ランタイムガードとエージェントスキル

スキーマ変更以外のリスクには、ミドルウェアで対応する:

middleware: [
  lints({
    severities: {
      deleteWithoutWhere: 'error',
      updateWithoutWhere: 'error',
      readOnlyMutation: 'error',
    },
  }),
  budgets({ maxRows: 10_000, maxLatencyMs: 1_000 }),
],

WHEREなしのDELETEは実行前にエラーになる。接続をread-onlyに制限することもできる。

またprisma initを実行すると、Claude Codeなら.claude/skills/、CursorやほかのAIなら.agents/skills/にエージェント向けスキルが自動インストールされる。エラーメッセージも「prisma migrate resetを使え」ではなく、問題を解決する具体的な手順を返す設計に変わっている:

fix: Plan the missing migration, then run it:
  1. prisma migration plan --from <hash> --to <hash> --name <slug>
  2. prisma migrate --to <hash>

現在の状況と既存ユーザーへの影響

Prisma 8のリリース候補は数週間以内に公開予定。現時点ではprisma-nextパッケージとして提供されており、試すことができる(一部のPrisma 7機能は未実装):

pnpx prisma-next@latest init

なお、このパッケージはRCリリース前の開発版であり、本番環境への適用は推奨されない。評価・検証目的での利用にとどめるべきだ。

Prisma 7からの移行については、コントラクトベースのスキーマ管理やシャドウDB廃止といった設計変更を伴うため、既存プロジェクトでの移行コストは小さくない可能性がある。元記事では具体的な移行パスや後方互換性の詳細には踏み込んでいないが、RCリリース時に公開される公式マイグレーションガイドを参照することが推奨される。

Prisma Postgres向けには、Prisma Cloud API経由でマイグレーションをリモート実行するPrisma Migration Runnerも近く提供予定だ。これが実現すると、エージェントもCIも本番DBへの管理者権限を持つ接続文字列を保持せずに済む構成となり、認証情報の漏洩リスクも含めた多層的な安全設計が整う。シャドウDB廃止・コントラクト設計・ランタイムガード・Migration Runnerを組み合わせることで、Prisma 8はAIエージェント時代のDB操作安全基盤としての一貫した設計思想を持つ。

詳細はDon't Let Your AI Agent Delete Your Production Databaseを参照していただきたい。