メインコンテンツへスキップ

AIエージェント開発・運用の事故録 #10

Deploy SUCCESSは
本番確認ではない

provenance・Production SHA・認証済み経路・browser evidence

公開日:2026年8月25日 著者:飯田 友広(Tomohiro Iida)

この記事の結論

  • Deploy SUCCESSは操作の完走であり、本番が期待どおり動いている証拠ではありません。

  • main SHA、deploy input SHA、deployment artifact SHA、Production SHAを別々に確認します。

  • 判定に「その変更では値が変わらないもの」を使いません。汎用のuptimeチェックや公開トップの200では、認証済み経路の障害を検出できません。

  • 公開経路と認証済み経路、schemaの実状態、browser evidence、検証用identityの後始末、rollback可能性を、それぞれ別の確認として持ちます。

デプロイworkflowが緑になった瞬間、報告は「本番反映しました」になります。

その緑が示しているのは、デプロイ操作が最後まで走ったことだけです。本番でどのコードが動いているか、DBの状態が合っているか、ログイン中の顧客に何が見えているかは、まだ何も確認していません。

結論は単純です。

Deploy SUCCESSとProduction verificationを、別の工程として分けます。 反映は反映で完了させ、そのうえで、SHAの一致、schemaの状態、公開経路と認証済み経路、browser evidence、後始末、戻せるかどうかを、それぞれ別々に確認します。

Incident Card

INCIDENT:
Production deploymentが完了した後、ログイン中の顧客だけが全画面で500になっていた

SYMPTOM:
cookieが無い、または空なら200。非空なら500。公開ページは200のままで、異常が見えなかった

FALSE_ASSUMPTION:
デプロイが成功し、公開ページが200なら、本番は健全である

ROOT_CAUSE:
mainへ未マージのコードが手元から本番へ出て、そのコードが要求するDBの列が本番に存在しなかった

IMMEDIATE_FIX:
過去にProductionとして配信されていたdeploymentへrollbackし、認証済み経路の復帰を実測した

SYSTEM_FIX:
Git連携の自動デプロイを全branchで無効化し、本番反映を確認文字列つきの単一workflowへ限定し、source commitの記録と後段の本番検証を分離した

REMAINING_RISK:
検証中に本番が動く、classification登録済みの所見が実害を隠す、rollback先が枯れる

緑のDeployのあとで、顧客画面だけが落ちていた

2026-08-16、本番の顧客ポータルがログイン中の顧客に対して500を返し続けました。観測できた挙動は次のとおりです。

  • セッションcookieが無い場合は200
  • cookieの値が空文字の場合も200
  • cookieの値が非空なら、値の正しさに関係なく500
  • 公開ページは200

つまり、未ログインの利用者からは正常に見えていました。 異常が出るのは、セッションを引くSELECTが走る経路だけでした。ランタイムログの実エラーはSQLSTATEの42703、undefined_columnです。コードが参照している列が、本番のDBに存在しませんでした。

原因を追ううちに、二つの事実が出てきました。一つは、問題のProduction deploymentが、deployment metadataにcommit SHAを持っていなかったことです。Git連携ではなく、手元の作業ディレクトリから直接出されていました。もう一つは、その列を追加するmigrationがmainへ未マージのbranch側にあり、本番DBへ適用されていなかったことです。

デプロイ操作自体は成功しています。緑でした。

誤った前提は、判定材料の選び方にあった

「Deployが成功したから本番は新しい」という前提が一つ目です。デプロイの成否は、コマンドが最後まで走ったかどうかを示します。何が配信されているかは、別に確認する必要があります。

二つ目は判定材料の選び方です。その変更では値が変わらないものを、判定に使ってはいけません。

  • 公開トップページのHTTP 200は、認証済み経路の障害では変わりません
  • 汎用のuptimeチェックは、特定のルートだけが落ちても緑のままです
  • ビルドの成否は、DBの状態を何も知りません
  • デプロイのタイムスタンプは、何が配信されたかを言いません

値が変わらないものを見続けると、偽陰性が生まれます。逆に、その変更と無関係に動く値を見ると、偽陽性が生まれます。判定には、その変更でしか変わらない値を選びます。

根本原因

事故の構造は二つ重なっていました。

  1. mergeとproduction rolloutが結合していた、あるいは、手元から本番へ出せる権限が残っていた
  2. deployment artifactにsource commitの記録が無く、何が配信されているかを後から言えなかった

そのうえで、検証側にも欠落がありました。schemaとcodeの要求が突き合わされておらず、確認が公開経路だけで、認証済み経路の実測が無かったことです。

その場の対処

復旧は、過去にProductionとして配信されていたdeploymentへのrollbackで行いました。rollback後に、でたらめな値のcookieでも認証済み経路が200へ戻ることを実測しています。

このとき復旧が速かった理由は、手元からrollbackを叩けたことでした。同じ権限が、事故の原因でもありました。

仕組みへ変換する

Deploy SUCCESSの後に、次を別々に確認します。

仕組みへ変換する
確認対象見るもの分かること
SHAの一致current main、deploy input、deployment artifact、Production alias何が配信されているか
DBの状態実schemaを読み取り専用で照会codeの要求と一致するか
公開経路主要ルートのHTTPとレンダリング結果未ログインの体験
認証済み経路ログイン後の顧客画面顧客だけに出る障害
browser evidence複数viewportのスクリーンショットとconsole、network error画面まで行かないと分からない壊れ方
後始末検証用identityの削除本番データを汚していないか
戻せるかrollback先の存在と素性障害時に復旧できるか

判定ロジックは擬似コードで固定します。

DEPLOY_RESULT = SUCCESS
PRODUCTION_VERIFIED = UNKNOWN

if PRODUCTION_SHA != DEPLOY_INPUT_SHA:
    PRODUCTION_VERIFIED = FAIL

if SCHEMA_STATE != CODE_REQUIREMENT:
    PRODUCTION_VERIFIED = FAIL

if AUTHENTICATED_ROUTE not OBSERVED:
    PRODUCTION_VERIFIED = UNKNOWN

if SIGNAL_USED_FOR_JUDGEMENT does not change with THIS_CHANGE:
    SIGNAL = INVALID

このリポジトリには、対応する実装が置いてあります。

  • vercel.jsonのGit deploy policyは、***mainのすべてをfalseにしています。Git pushによる自動デプロイは、mainを含む全branchで無効です。 本番反映の唯一の経路は、確認文字列を要求する手動workflowです。
  • 静的検査がこのポリシーを固定し、branch側で例外を足すことも、maintrueへ戻すことも拒否します。2026-08-16には、agent branchが自分自身をallowlistへ追加し、2時間でPreviewが11本発生しました。Vercelはpushされたcommitのvercel.jsonを読むため、検査は差分の時点で落とします。
  • 本番デプロイのコマンドは--metaでsource commitを記録します。記録できたかどうかはデプロイ直後に実測し、記録が落ちていればjobを落とします。ただし、deployment自体は既に出ています。 これは反映の失敗ではなく、復旧経路の欠落の通知です。
  • 反映jobとpost-deploy QA jobは分かれています。反映jobはstep summaryへDEPLOYEDのboundaryを記録し、後続の失敗がこのデプロイを取り消さないことを明示します。赤いworkflowを「未反映」と誤認してblind rerunしないためです。
  • post-deploy QAは、QAの前とQAの後の2回、Production aliasが指すSHAを解決します。QA中に本番が動いた場合に、観測を取り違えないためです。
  • 本番schemaは読み取り専用の別workflowが実schemaを直接読みます。migration workflowのログは「適用したと記録されている」ことしか言いません。42703のようなエラーは実schemaの話なので、実schemaを見ます。
  • 認証済み顧客画面はbrowserで巡回し、複数viewportのスクリーンショットとconsole、network errorを証拠として残します。そのうえで、証拠が「在る」ことと、required項目が揃っていることを別に数え直します。 required viewportごとの構造化row、exact SHA、public HTTP、artifactの実体を照合します。
  • 本番smokeが使う検証用identityは、リポジトリのコードで固定されています。workflow入力から識別子を受け取りません。cleanupが本番DBの権限を持つため、呼び出し側が識別子を指定できるとaccount mutatorになるためです。
  • rollbackで戻せるのは、source commitがmainの履歴にあり、かつ過去にProductionとして配信されたdeploymentだけです。未マージのPreviewへ戻せるなら、それは復旧ではなくbypassです。入力されたdeploymentは信用せず、metadataを取り直して検証します。

再利用できる本番検証チェックリスト

Deploy SUCCESSの後に、上から順に確認します。

  1. current main SHAは何か
  2. deploy input SHAはそのmain SHAと一致するか
  3. deployment artifactにsource commitが記録されているか
  4. Production aliasが指すSHAはdeploy input SHAと一致するか
  5. 検証の前後でProduction SHAが動いていないか
  6. 実schemaを読み、codeが要求する状態と一致するか
  7. 未適用のmigrationが残っていないか
  8. 公開経路を実測したか
  9. 認証済み経路を実測したか
  10. browser evidenceを複数viewportで取り、console、network errorを確認したか
  11. 判定に使った値は、その変更で実際に変わる値か
  12. 検証用identityを片付けたか
  13. 戻せるdeploymentが存在し、その素性を確認したか

Evidence

Evidence
内容分類根拠
2026-08-16、認証済み経路だけが500になり、公開ページは200だったOBSERVEDリポジトリの governance/incidents/INC-2026-08-16-003.yaml
ランタイムの実エラーはSQLSTATE 42703のundefined_columnだったOBSERVEDリポジトリの governance/incidents/INC-2026-08-16-003.yaml
問題のProduction deploymentはcommit SHAのmetadataを持っていなかったOBSERVEDリポジトリの governance/incidents/INC-2026-08-16-003.yaml
Git連携の自動デプロイはmainを含む全branchで無効IMPLEMENTEDリポジトリの vercel.json
本番反映は確認文字列を要求する手動workflowに限定されているIMPLEMENTEDリポジトリの .github/workflows/deploy-signal-production.yml
deploy policyの差分を静的検査が拒否する。2026-08-16にagent branchが自己allowlist化し2時間でPreviewが11本出たIMPLEMENTEDリポジトリの scripts/check-vercel-deploy-policy.mjs
source commitの記録は静的検査とデプロイ直後の実測の両方で確認するIMPLEMENTEDリポジトリの scripts/deploy-policy/check-deploy-provenance.mjs
post-deploy QAはQAの前後でProduction aliasのSHAを解決するIMPLEMENTEDリポジトリの .github/workflows/deploy-signal-production.yml
実schemaは読み取り専用workflowが直接読むIMPLEMENTEDリポジトリの .github/workflows/verify-production-schema.yml
認証済み顧客画面のbrowser巡回とevidence契約の数え直しIMPLEMENTEDリポジトリの .github/workflows/signal-production-ui-audit.ymlscripts/signal-audit/assert-signal-service-evidence.mjs
検証用identityはコードで固定され、workflow入力から受け取らないIMPLEMENTEDリポジトリの scripts/signal-audit/production-goal-smoke-identity.ts
rollback先はmain履歴かつ過去のProduction配信に限定されるIMPLEMENTEDリポジトリの .github/workflows/production-rollback.yml
判定に使う値の選び方が偽陰性・偽陽性を決めるINFERRED上記の観測と実装からの推論
本番検証の所要時間短縮と自動判定の拡大PROPOSED現時点では人間が最終判断を持つ

適用限界

ここに書いた手順は、Netsujoの運用目安であり、普遍的な正解ではありません。

  • 確認する経路の数と深さは、サービスの構成と顧客への影響範囲によって変わります。
  • 認証済み経路の実測には、本番へ入れる検証用identityと、その後始末の設計が必要です。設計せずに真似ると、本番データを汚します。
  • Git連携の自動デプロイを全branchで無効化する構成は、リリース頻度と手動運用の負荷を引き受ける前提で成り立ちます。
  • この分離によって障害の平均検知時間がどれだけ短くなったかは未計測です。

残るリスク

  • 検証中に本番が動く可能性は残ります。前後2回のSHA解決は、動いたことを検出はしますが、防ぎません。
  • 既知の所見をclassificationへ登録する運用は、実害のある壊れ方を「登録済み」として通す危険を持ちます。分類は測定ではありません。
  • 読み取り専用の接続文字列は、名前ではなく権限で確かめる必要があります。名前は権限ではありません。
  • rollback先は時間とともに枯れます。戻せるdeploymentが残っているかは、事故の前に確認する対象です。
  • 本番検証を通っても、そのSHAが以後も配信され続ける保証はありません。

まとめ

Deploy SUCCESSは、操作が完走したという報告です。Production verificationは、いま何が動いているかという観測です。

main SHA / deploy input SHA / artifact SHA / Production SHA
+
schema・migrationの実状態
+
公開経路と認証済み経路
+
browser evidenceとconsole・network error
+
検証用identityの後始末
+
rollbackできる状態

この6つを別々に持つと、緑の報告と本番の実態が離れたときに、離れたことが分かります。

よくある質問

デプロイworkflowが緑なら、本番反映は完了ですか

反映操作は完了しています。本番が期待どおりに動いているかは別です。Production aliasが指すSHA、DBの状態、公開経路と認証済み経路を、それぞれ観測してから完了と呼びます。

公開ページが200なら、本番は健全だと判断してよいですか

判断できません。認証済み経路だけが落ちる壊れ方があります。2026-08-16の事故では、cookieが非空のときだけ500になり、公開ページは200のままでした。

uptimeチェックがあれば十分ですか

不足します。汎用のuptimeチェックは、その変更で値が変わりません。判定には、その変更でしか変わらない値を選びます。SHAの一致、対象ルートの応答、schemaの実状態がその例です。

post-deployのQAが失敗したら、デプロイをやり直すべきですか

まず、反映がすでに済んでいることを確認します。反映jobと後段のQA jobは別です。赤いworkflowを「未反映」と読み替えてblind rerunすると、同じ配信を重ねます。

本番へ検証用のアカウントを作ってよいですか

後始末まで含めて設計できる場合に限ります。識別子はリポジトリのコードで固定し、workflow入力から受け取りません。削除処理が本番DBの権限を持つため、呼び出し側が識別子を指定できると、任意のアカウントを操作できる経路になります。

この記事の著者

飯田 友広

飯田 友広

代表取締役

Netsujo株式会社 代表取締役。京都発のWeb3・AI実装スタートアップを2023年6月に創業。Webサイトを営業基盤として捉え、経営・営業・検索・生成AI・コンバージョン・計測を横断して課題と改善優先順位を整理する「Netsujo SIGNAL」を設計・運営。京都ビッグデータ活用プラットフォーム参画(小規模企業会員・ベンチャー)、同プラットフォーム発のワーキンググループ「Chain Up KYOTO」参画(2026-03-10)、IVS2026サイドイベント「なぜ京都でWeb3.0ビジネスなのか」を京都府庁旧議場で開催(2026-07-02・Netsujoとして主催、企画・登壇・運営/京都府デジタル政策推進課は共催)。京都美術工芸大学での講義・龍谷大学でのセミナー実績、ITコミュニティ「みやこでIT」(connpassメンバー614名・イベント167件・2019年2月から運営)運営。NPO法人NEMTUS理事、BAR KRYPTO運営。ソーシャル企業認証「S認証」認証企業(2026年2月認証・2026年4月公表)。技術領域はWeb3/ブロックチェーン/DID/NFT/生成AI/コミュニティ運営。

プロフィールを見る

この記事が向いている方

  • AIエージェントを開発へ組み込み、本番反映の報告と実態が合わなくなっている事業責任者・開発責任者

  • デプロイworkflowの緑を本番確認として扱っているチーム

  • 公開ページの死活監視だけで本番の健全性を判断しているITエンジニア

— 壁打ち相談

読者のよくある相談

記事を読んだ後に「自分の状況だとどう判断すべきか」を整理するための壁打ち相談を受け付けています。下記のような相談例が当てはまる方は、お気軽にご連絡ください。

Q. デプロイが成功したのに、顧客からだけ不具合の連絡が来る

認証済み経路を実測します。公開経路が200でも、セッションを引く経路だけが落ちる壊れ方があります。

Q. 本番でどのコードが動いているか、後から言えない

deployment artifactへsource commitを記録し、記録できたことをデプロイ直後に実測します。

Q. 監視は緑なのに、障害に気づけなかった

判定に使っている値が、その変更で実際に変わる値かを確認します。変わらない値では検出できません。

上記いずれかが該当する場合、初回30分の壁打ち相談で論点整理に対応します。記事に書ききれない個別事情を踏まえた判断材料が必要な段階こそ、壁打ちが活きやすいフェーズです。

AI導入・開発運用設計のご相談

本番の状態を、報告ではなく観測で持つ

デプロイ経路の限定、source commitの記録、schemaの実確認、認証済み経路の巡回、rollback可能性までを設計します。

AI導入について相談する