Admin Control Plane
顧客操作とは別の、強い権限・監査・冪等性を持つ管理者経路を読み解きます。
台帳、振込、KYC、権限、監査、照合をMinibankの実装と結び付ける。
先に学ぶ内容 — Prerequisite: 基礎 / 銀行業務学ぶこと — LEARNING GOALS
このページで学ぶこと
- operatorとadmin_manager
- 口座・KYC・金融操作の管理経路
- 最後のmanagerと無効化競合への対策
体験09 · ADMIN(管理者の権限)
管理者は、何でも自由に操作できるか確かめよう
まずは予想をひと言。本文を読んだ後、管理者向け画面で見える範囲と制限を確認します。
- 01まず予想する — PREDICT
まずここだけ:思ったことをひと言書く
管理者なら、口座の凍結や解除など何でも自由に操作できてよいでしょうか?
正解でなくて大丈夫です。「〜だと思う」から始めてみましょう。
ヒント1を見る
管理者は1種類だけでしょうか、それとも役割によってできることが違うでしょうか?
ヒント2を見る
口座を「凍結」した後、次に何ができて何ができないと思いますか?
もっと詳しく:この問いで使う専門用語
- Control Plane(管理領域)は、顧客の通常利用とは別の、制度・状態・権限を管理する操作領域です。
- operatorとadmin_managerは、管理者の中でもできる操作の範囲が異なる役割です。
- 状態遷移は、active→frozen→closedのように、許可された順序だけで状態を変える規則です。
- 最後のmanager保護は、管理者を管理できる人が0人にならないための安全策です。
日常語で理解する — PLAIN LANGUAGE
まず、ここだけつかむ
管理画面は一般利用者より強い操作が集まるため、通常の顧客機能とは別の制御面として扱います。
管理者にも役割と有効・無効状態があり、すべての管理者へ同じ権限を渡しません。最後のadmin_managerを無効化して誰も管理できなくなる事故も防ぎます。
freeze、close、KYC判断などは、DBが現在状態をlockして遷移を確認し、成功と監査記録を同じtransactionで残す必要があります。
順番に理解する — DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
Control Plane
顧客の通常利用ではなく、制度・状態・権限を管理する操作領域です。
侵害時の影響が大きいため、顧客向けData Planeから入口と権限を分離します。
admin schema、管理RPC、/adminのUI・APIで管理操作を構成します。
最小権限
仕事に必要な操作だけを、その期間だけ許可する考え方です。
1つの管理者アカウントが侵害されたときの被害を小さくします。
operatorとadmin_managerを分け、active状態も各RPCで確認します。
状態遷移
active→frozen→closedなど、許可された順序だけで状態を変える規則です。
closed口座の再開や同じ審査の二重確定など、意味のない操作を防ぎます。
RPCが対象をlockし、現在状態から許可された操作かを判定します。
最後のmanager保護
管理者を管理できる人が0人にならないための安全策です。
最後の1人を無効化すると、正規手順では復旧できずDB owner操作が必要になります。
deactivation時にactiveなadmin_manager数をtransaction内で確認します。
発展 — ADVANCEDもっと詳しく確認する最初の学習では読まなくても問題ありません。仕組みをもっと深く理解したい場合に開いてください。
役割と操作
| 役割 | 主な操作 |
|---|---|
| operator | 入金、出金、手数料、逆仕訳、口座freeze/unfreeze/close、KYC review |
| admin_manager | operatorの操作に加え、管理者作成・role変更・enable/disable |
状態遷移
- 口座freeze: active → frozen
- 口座unfreeze: frozen → active
- 口座close: activeまたはfrozen → closed。ただしledger残高0が必要
- KYC approve/reject: pendingからのみ
- 管理者は削除せずdisabledとして履歴を残す
- activeなadmin_managerを最後の1人から0人にする操作を拒否
振込監視:資金移動前の状態も見る
顧客履歴はcompletedしたjournalを中心に表示しますが、運用者はOTP待ち、処理中、失敗、期限切れも把握する必要があります。`/admin/transfers` はadmin_list_transfer_requests()を使い、振込依頼の全lifecycleを読みます。
| 監視項目 | 内容 |
|---|---|
| Status | pending_otp / processing / completed / failed / expired / cancelled |
| OTP | consumed challengeの有無から認証済みを表示 |
| 振込情報 | 依頼者、送金先口座、銀行・支店・種目・名義、金額 |
| 失敗 | private transfer_requestsのfailure_reasonをactive adminへ表示 |
| 組戻し | completed transferのjournalに対応するreversal有無 |
| 検索 | status、口座番号、request ID、依頼者ID、cursor pagination |
実際のMinibankでは
管理操作はauthenticatedへ公開されたSECURITY DEFINER wrapperが `auth.uid()` を基にactive operatorを確認します。idempotency keyとfingerprint、結果を `admin.operation_requests` に保存します。20260823100001では呼出者自身のoperator行をロックして再検査し、待機中の無効化・降格に対するTOCTOUを抑えています。
Actor Separationにより、customer profileを持つauth userのadmin作成と、active adminによるcustomer作成をDBで拒否します。画面redirectだけではなく、2つのwrite入口とintegrity checkで兼務を防ぎます。
体験学習の続き · LEARNING LOOP
ここまで読めましたか?続けて確認してみましょう
管理者の権限と状態遷移の考え方を読んだところで、実際の管理画面を確認し、自分の言葉で説明してみます。
- 02実際に観察する — OBSERVE
同じ仕組みを、動く画面から観察する
この仕組みは管理者向けの画面で確認できます。管理者ログインがない場合は、この教材内の図・説明・Source Trail(教材の参照元)で代替学習し、次へ進めます。
管理者ログインがない場合:教材の参照元で確認する ↓ - 03証拠を確認する — EVIDENCE
何を見たか、1つずつ確かめる
Evidence(判断の根拠となる記録)を確認したらチェックします。各項目の「何を見るか」を手がかりにしてください。
画面を開けない項目は、Source Trail(教材の参照元)と教材の説明で確認できます。失敗を実際に起こす必要はありません。
- 04コードの処理経路を追う — CODE TRAIL
コードを書く必要はありません
ここでは「説明されている仕組みが、実際のMini Bankのどこに実装されているか」を確認します。まずは日本語の役割説明を読み、入力した依頼がどこへ渡るかをつかみましょう。コードの全文を読む必要はありません。
基本の順序は、画面 → API Route(依頼を受ける窓口)→ TransferService(処理をつなぐサービス)→ DB / RPC(記録の保存場所と、その処理の呼び出し)です。まず最初の2つを見て、続くサービスは「もっと詳しく」で確認します。
教材の参照元を確認する — Source Trail ↓管理者の金融操作(入出金・freeze等)を実行する窓口の定義。
supabase/migrations/20260821100004_create_admin_execute_wrappers.sqlMigration(DB定義の変更履歴)。口座の状態遷移(freeze/unfreeze/close)を定義する箇所を確認します。
supabase/migrations/20260821100006_create_account_lifecycle_functions.sql - 05自分の言葉で説明する — EXPLAIN
LEVEL 1 — やさしい説明(まずここだけ)
なぜ管理者にも、役割や対象の状態によってできる操作の違いがあるのでしょうか? 短い2文を目安に説明してください。
日常語だけで完了できます。専門用語の数や正誤を自動採点するものではありません。
ヒント1を見る
「役割」と「状態」という2つの言葉を使って書いてみましょう。
ヒント2を見る
もし管理者が1人しかいなくなったら何が困るか考えてみましょう。
もっと詳しく:LEVEL 2 — 専門用語を使った説明(任意)
Control Plane、最小権限、状態遷移、最後のmanager保護の4つを使って、管理者権限の設計を説明してみましょう。
挑戦する場合は、上の説明欄に追記できます。追加しなくても完了できます。
説明の確認ポイント — Checkpoint- 管理者にも役割と状態による操作制限があると説明できる
- 画面に到達できることと操作を実行できることが別だと説明できる
理解を確かめる — CHECK YOUR UNDERSTANDING
3問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1admin画面へ入れたら、全管理操作を許可してよいですか?
いけません。各RPCでroleとactive状態、対象状態をその都度確認します。
Q2口座freezeを二重実行したらどう扱うべきですか?
状態遷移または冪等性の規則に従い、二重の副作用や重複監査を生まないようにします。
Q3最後のadmin_manager保護に同時実行対策が必要な理由は?
2人が同時に互いを無効化すると、各処理が『もう1人いる』と古い状態を見て全員無効化する恐れがあるからです。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
教材の参照元 — SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
- 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/20260821100001_create_admin_schema_and_operators.sqladmin operatorモデル - 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/20260821100004_create_admin_execute_wrappers.sql金融操作wrapper - 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/20260821100006_create_account_lifecycle_functions.sql口座状態遷移 - 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/20260823100001_fix_admin_toctou_lock_own_operator_row.sqlcaller row lockと再認可 - 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/20260823160001_enforce_actor_separation.sqlcustomerとactive adminのactor分離 - 過去の実装 — HISTORICAL IMPLEMENTATION
supabase/migrations/20260823180002_create_admin_transfer_requests_read_api.sqladmin_list_transfer_requests()active admin限定の振込監視 - 現在の実装 — CURRENT IMPLEMENTATION
src/app/admin/(protected)/transfers/page.tsx振込lifecycle監視UI - 現在の実装 — CURRENT IMPLEMENTATION
scripts/regression/suites/adminQuorum.mjs管理者ライフサイクル回帰