銀行エンジニアリング 33:復元と検証(manifest・照合・二者確認・訂正)
バックアップから戻しただけでは、正しく戻ったとは言えません。何を確かめれば再開してよいのか、失われた取引をどう扱うのか、復元後に見つかった誤りをどう直すのかを追います。
v8以降に実装した台帳・記帳エンジンなどを実際に動かし、正常時と異常時の両方から銀行システムの構造を学ぶ。
Prerequisite: BANKING SYSTEMLEARNING GOALS
このページで学ぶこと
- バックアップ時点の記録(manifest)と復元後の検証
- 同じ冪等キーでの再送が二重にならない理由
- 復元で戻ってしまう同意の失効と、その対処
PLAIN LANGUAGE
まず、ここだけつかむ
復元したデータが正しいことは、バックアップ時点の記録(manifest)との一致と、これまでの版の照合の両方で確かめます。
バックアップのあとの取引は失われます。顧客のアプリが元の冪等キーで再送すると、ちょうど1回に収束します。
復元で戻ってしまう同意の失効は、再開時にアクセストークンをすべて失効させて塞ぎます。
DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
manifest
バックアップ時点のデータの指紋です。
復元後に、バックアップ時点と同じかを数値で確かめるためです。
recovery.manifests。件数・最終仕訳・ハッシュ・営業日に加え、グループの勘定残高や、同意・融資・定期預金の状態、さらに書込停止中は変わらない状態の行ごとのハッシュ(digest の方式 3。融資(契約・返済予定・申込・分類と審査のイベント・命令・商品の版)、預金の価格(手数料と利息の実行・その訂正・商品の版)、法人(支払依頼・支払予定・メンバー・組織・設定依頼)、group(事業体・事業体の役割)、Open Banking(クライアント・同意・振込依頼・通知先の登録)、顧客の振込依頼、risk の設定(パラメータ・シナリオ・測定)、twin の設定(モデル・シナリオ)、銀行間送金(支払・決済バッチ)、管理責任者の復旧の記録と方針、締め処理の実行、KYC の状態)。運用者の権限は入れない。digest は方式の版と一緒に外へ控える。
検証
復元後に、帳簿が矛盾していないかを確かめることです。
戻したデータで営業を再開してよいかを判断するためです。
recovery.verify。核の 9 項目(元帳・Posting・補助元帳・融資・預金価格・Open Banking・Treasury・V19_GROUP・V19_ADAPTER)、運用者の権限(EXTERNAL_OPERATORS)、manifest との比較。manifest 以外の全項目(運用者の権限を含む)が OK で、manifest の比較も OK になった検証があることが提出の条件。
外に控えた運用者の一覧
障害の前に、運用者の user_id・role・status を、データベースの外へ控えたものです。
運用者の権限は書込停止中に『無効化』で変わるので digest に入れられません。外の一覧と比べて、権限が増えていないことだけを確かめるためです。
復元の宣言の external_operators(任意。1〜500 件の配列)。検証の EXTERNAL_OPERATORS は、一覧を渡せば増える向きだけ NG で、一覧にない人は NG にしない(人数は unlisted_active に出る)。渡さなければ検査は走らず、『検査せず』(declared:false)と出る。NG は、無効化することで解消する(降格は書込停止中は RY001 で止まる。管理責任者の無効化は、その人を除いて有効な管理責任者が 2 人以上残るときだけ)。
調整の仕訳
誤りを消さずに、差額を新しい仕訳で直すことです。
元の記録を残したまま、あとから説明できるようにするためです。
pricing.adjust_run。仮受金は専用の取消し。
Level 1 基礎:戻したデータが正しいことを、どう確かめるか
バックアップの直前に、その時点のデータの『指紋』を記録しておきます(manifest)。復元したあとに同じ指紋を取り、一致すれば、復元がバックアップ時点と同じだと分かります。ただし、復元先の中で新しく取った指紋は、復元先が古くても必ず一致してしまいます。だから指紋の digest は、障害の前にデータベースの外へ控えておき、復元を始めるときに入力します。それとは別に、帳簿そのものが矛盾していないかも確かめます。
| 検証の項目 | 確かめること |
|---|---|
| 元帳と残高(v7) | 仕訳の借方と貸方の合計、口座の残高と元帳の再計算 |
| Posting(v8) | 事象と仕訳の対応 |
| 補助元帳(v10) | 総勘定元帳と、預金・定期預金・為替・仮受金・融資の明細 |
| 融資(v14)・預金価格(v15)・Treasury(v13) | 各業務の契約と仕訳の照合 |
| Open Banking(v16) | イベントの連番、依頼と振込の対応、無効な同意で生きているトークン |
| グループ(v19・V19_GROUP) | entity・グループ内の移動と、グループの仕訳・勘定残高の照合 |
| 基準の銀行の読取り口(v19・V19_ADAPTER) | グループの照合とは別に、基準の銀行の読取り口(adapter)が元帳と食い違っていないか |
| manifest | 件数・最終仕訳・試算表と残高のハッシュ・営業日に加え、グループの勘定残高と移動の状態、同意・融資・定期預金の状態のハッシュ、さらに書込停止中は変わらない状態の行ごとのハッシュ(融資(契約・返済予定・申込・分類と審査のイベント・命令・商品の版)、預金の価格(手数料と利息の実行・その訂正・商品の版)、法人(支払依頼・支払予定・メンバー・組織・設定依頼)、group(事業体・事業体の役割)、Open Banking(クライアント・同意・振込依頼・通知先の登録)、顧客の振込依頼、risk の設定(パラメータ・シナリオ・測定)、twin の設定(モデル・シナリオ)、銀行間送金(支払・決済バッチ)、管理責任者の復旧の記録と方針、締め処理の実行、KYC の状態。更新日時は除く)が、バックアップ時点と一致するか(digest の方式 3)。復元を経た場合は、外に控えた digest・版との一致も含む |
| 運用者の権限(外に控えた一覧) | 復元を宣言した周期では必ず出る行。運用者の一覧を渡していれば、一覧にある人の権限が一覧より増えていないか(増えていれば NG。減る向きと、一覧にない人は NG にしない。一覧にない有効な運用者の人数 unlisted_active は情報だけ)。一覧を渡していなければ検査せず(declared:false。OK 扱いだが、権限は調べていない) |
Level 2 銀行業務:失われた取引と再送
バックアップのあとに確定し、顧客に『成功』と答えた取引は、復元したデータにはありません。顧客のアプリは、結果が不明なときと同じように、元の冪等キーで再送します。再送は、失われた取引なら1回だけ実行され、すでにある取引なら元の結果を返して二重になりません。
演習では、失われた取引の数と時間幅(RPO)を測り、すべての再送のあとに、主系(正解として残しておいた古い側)と口座の残高が一致することを確かめます。
Level 3 システム:MiniBankでの実装
- recovery.take_manifest がバックアップ時点の記録を取り、recovery.verify が上の検証を束ねて実行する。結果は追記専用の記録に残り、提出できるのは、照合を始めたあとの最新の検証で manifest 以外の全項目(運用者の権限の行を含む)が OK で、かつその間に、外に控えた digest と一致する manifest の比較が OK になった検証があるときだけ(バックアップ後に再送した取引で manifest との差が出るのは正常)
- digest 版 3 は、書込停止中は変わらない状態の行ごとのハッシュを含む(融資(契約・返済予定・申込・分類と審査のイベント・命令・商品の版)、預金の価格(手数料と利息の実行・その訂正・商品の版)、法人(支払依頼・支払予定・メンバー・組織・設定依頼)、group(事業体・事業体の役割)、Open Banking(クライアント・同意・振込依頼・通知先の登録)、顧客の振込依頼、risk の設定(パラメータ・シナリオ・測定)、twin の設定(モデル・シナリオ)、銀行間送金(支払・決済バッチ)、管理責任者の復旧の記録と方針、締め処理の実行、KYC の状態。実装の recovery.snapshot の state_hashes_v3 に対応)。書込停止中に変わらないので、再開を詰まらせない。運用者の権限は含めない(書込停止中の『無効化』で変わってしまうため)ので、外に控えた運用者の一覧との一方向の検査(EXTERNAL_OPERATORS)で守る。NG は『復元後に権限が増えている人がいる』という意味で、書込停止中にできるのは『無効化』だけで、役割を下げる変更(降格)は RY001 で止まる。管理責任者の無効化は、その人を除いて有効な管理責任者が 2 人以上残る場合だけで、満たさなければ RY003 で止まる
- manifest の比較は、差を数値で報告する(仕訳が何件欠けたか、最終仕訳が何か、ハッシュがどう違うか)。manifest を指定しない検証は NOT RUN で、提出の条件にならない
- 復元を経て再開すると、発行済みの Open Banking のアクセストークンをすべて失効させる。バックアップのあとに顧客が取り消した同意が、復元で ACTIVE に戻ることがあるため。トークンは15分で更新もないので、外部のアプリは顧客の新しい同意をもう一度得る必要がある
- 復元でイベントの連番も巻き戻る。外部のアプリが覚えている連番が別のイベントを指さないよう、event_id の食い違いで検知して、events API で取り直す
- 復元後に誤りが見つかったときは、仮受金は専用の訂正(受入の取消し/振替の取消し)、利息・手数料は調整の仕訳(正なら追加、負なら回収)で直す。汎用の取消しは PF002 で拒否される
- 顧客がすでに使ったお金を戻す訂正は、Posting Engine が残高不足で断る(PE010)。資金を負にしない
異常時:復元後の検証が NG
| 段階 | 内容 |
|---|---|
| 症状 | 検証の manifest の項目だけが NG。ほかは OK |
| 読み方 | 復元がバックアップ時点と一致していない。差は数値で出る(件数の差、最終仕訳、ハッシュ) |
| よくある原因 | 復元先へ、復元後に書込みが入った(fence の前)。違う(古い)バックアップから戻した。外に控えた digest と食い違うので、検証は NG になる |
| 対応 | 再開しない。復元先で書込みが入った経路を止め、正しいバックアップから戻し直す。差の意味を説明できるまで提出しない。外に控えた値を入力し間違えたときは、abort_restore で書込停止に戻して宣言からやり直す |
異常時:運用者の権限(EXTERNAL_OPERATORS)が NG
| 段階 | 内容 |
|---|---|
| 症状 | 検証の『運用者の権限』の行だけが NG。manifest を含むほかの項目は OK のまま、レビューへ提出できない(RY004) |
| 読み方 | 復元後に、外に控えた一覧より権限が増えている人がいる(一覧では無効の人が有効、運用者のはずの人が管理責任者)。NG の詳細の escalations(権限が増えている人の一覧)に user_id が出る。一覧にない人は NG にならない。unlisted_active は一覧にない有効な運用者の人数(情報だけ) |
| 対応 | 書込停止中にできるのは『無効化』(有効から無効への変更)だけで、役割を下げる変更(降格)は RY001 で止まる。管理画面『管理者管理』で無効化して、もう一度検証してから提出する。無効化の対象が管理責任者のときは、その人を除いて有効な管理責任者が 2 人以上残らないと RY003 で止まる。その場合は『復元をやり直す』(abort_restore)で外に控えた一覧を訂正し、宣言し直す |
| 注意 | 『検査せず』(declared:false)は OK ではない。復元の宣言で一覧を渡さなかったので、権限を調べていない。外に控えた一覧があるなら、宣言をやり直す(abort_restore で書込停止に戻して、最初から) |
Level 4 アーキテクチャ:復旧の設計は冪等性の設計
復元で取引が失われても、クライアントが同じキーで再送できれば結果は1回に収束します。復旧は『元に戻す』作業ではなく、『失われた分を、同じ意図で、もう一度、ちょうど1回だけ』実行する作業です。冪等キーが表ごとに固定されていることが、その土台です。
どこを確認すればよいか
- 管理画面『復旧・DR』:検証の結果(項目ごとの OK/NG)、manifest、演習の記録、訂正のフォーム
- scripts/dr/drill.mjs の出力:RTO・RPO・失われた取引の数・条件
CHECK YOUR UNDERSTANDING
6問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1運用者の権限は、なぜ digest に入れないのですか?
書込停止中でも『無効化』だけはできるため、digest に入れると正当な無効化で再開が詰まるからです。代わりに、外に控えた一覧と比べ、権限が増えている向きだけを NG にします。
Q2復元の宣言で運用者の一覧を渡さなかったら、運用者の権限は調べられますか?
調べられません。検証には『検査せず』(declared:false)と出ます。OK に見えても、権限は調べていません。AML など digest に入らない状態も、DB は見つけないので、人が確認します。
Q3運用者の権限が NG のとき、manifest などほかの項目が OK なら提出できますか?
できません(RY004)。無効化して、もう一度検証します(降格は書込停止中は RY001 で止まります)。管理責任者の無効化は、その人を除いて有効な管理責任者が 2 人以上残る場合だけできます(そうでなければ RY003。その場合は復元をやり直して一覧を訂正します)。
Q4manifest を指定しない検証で提出できますか?
できません。manifest の項目は NOT RUN で、全項目 OK になりません(RY004)。
Q5失われた取引を同じキーで再送すると二重になりますか?
なりません。失われたものは1回だけ実行され、あるものは元の結果を返します。
Q6復元のあとに再開すると、Open Banking のトークンは?
すべて失効します。外部のアプリは顧客の新しい同意が必要です。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
Implementation Status: IMPLEMENTED IN MINIBANK(この教材が扱うコードの範囲)
- RELATED LESSON/docs/be-dr-writer-fencing書込停止と再開
- RELATED LESSON/docs/be-openbanking-events-webhooksイベントの連番と pull による取り直し
- RELATED LESSON/docs/be-gl-subledger補助元帳の照合
- CURRENT IMPLEMENTATION
supabase/migrations/20260930190000_v20_digest_v3_review.sqlrecovery.snapshotバックアップ時点の記録(件数・最終仕訳・試算表と残高のハッシュ・営業日など。v19で entity・仕訳・グループ内移動の件数を追加し、Freeze Hardening で、グループの勘定残高・移動の状態・同意・融資・定期預金の状態ハッシュを追加。digest 版 3 で、書込停止中は変わらない状態の行ごとのハッシュ(主なもの: 融資・価格・法人・group・Open Banking・振込依頼・risk/twin の設定・銀行間送金・KYC)を追加し、再監査で、並べ替えのいらない方式(行ごとの md5 の合計と件数)に変え、group の事業体・Open Banking の同意と通知先・管理責任者の復旧・締め処理の実行も加えた。運用者の権限は入れない) - CURRENT IMPLEMENTATION
supabase/migrations/20260930190000_v20_digest_v3_review.sqlrecovery.verifyこれまでの版の照合を束ね、manifest と突き合わせる検証(v19でグループの照合を追加、Freeze Hardening で基準銀行の adapter の独立検査と、digest の方式の版の突合を追加。digest 版 3 で、外に控えた運用者の一覧と比べ、権限が増えている向きだけを NG とする EXTERNAL_OPERATORS を追加。再監査で、復元を宣言した周期では必ずこの行を出し、一覧が未申告なら declared:false の「検査せず」とし、申告ありなら一覧にない有効な運用者の人数 unlisted_active も出す) - CURRENT IMPLEMENTATION
supabase/migrations/20260930130000_v17_reliability.sqlgl.reverse_suspense_receipt / gl.reverse_suspense_clear仮受金の受入・振替の専用の訂正(汎用の取消しは PF002) - CURRENT IMPLEMENTATION
supabase/migrations/20260930130000_v17_reliability.sqlpricing.adjust_run利息・手数料の実行の誤りを、調整の仕訳で直す - CURRENT IMPLEMENTATION
scripts/banking/v17-recovery.test.mjs状態機械・書込停止・書込世代・manifest と検証・トークン失効・訂正・演習記録のDBテスト