利用者の画面とは異なる、審査・運用・監査のための画面を見ます。
重要なコードの抜粋へ ↓このページでわかること
- 管理者に必要な操作
- 権限の分離
- 操作を追跡できる設計
管理者は何をするか
v1の管理画面では、本人確認の審査、口座の凍結と解除、取引や帳簿の確認、整合性チェックなどを扱います。顧客の画面からはできない操作をまとめた場所です。
本人確認では顧客の申請が pending になり、管理者が verified または rejected を選びます。申請者が自分で承認できないことが大切です。
管理者でも何でもできるわけではない
管理者のログイン、役割、操作権限を分けます。権限のある人だけが状態変更を行い、誰が実行したかを監査ログに残します。
口座の凍結は送金などの操作を止めるための状態変更です。画面でボタンを隠すだけでなく、処理側でも凍結状態を検証します。
管理者操作ほど確認が必要
口座凍結や本人確認の承認は利用者の行動を大きく変えます。対象者、現在の状態、実行後の状態を確認し、操作を監査ログへ残します。操作直前に別の管理者が状態を変えることもあるため、画面で見た古い状態のまま決めないようにします。
v1には管理者操作と役割管理のための関数や画面があります。権限は「管理画面が開けるか」だけでなく、個々の操作ごとに考えます。
見えることと直せることを分ける
監査ログ、帳簿、整合性チェックの結果は、管理者が原因を調べる材料です。しかし閲覧権限があるからといって、過去の帳簿を書き換える権限を与えるべきではありません。訂正は反対仕訳など決められた手順で行います。
運用画面では「異常がある」と示すだけでなく、どの取引や口座を確認すべきか追えることが重要です。
本人確認の審査を例にする
顧客が申請すると pending になり、管理者が確認して verified または rejected にします。審査画面で見た状態が、承認ボタンを押すまでの間に変わるかもしれません。実行時に状態を再確認し、許されない遷移を拒否します。
誰がいつ承認したか残せなければ、後で理由を調べられません。画面、状態遷移、監査記録を一つの業務操作として考えます。
口座凍結の影響範囲
凍結を画面に赤く表示するだけでは、送金APIへ直接届いた依頼を止められません。入金・出金・送金など、口座状態を参照する処理が同じ判断をする必要があります。解除も権限のある管理者が行い、両方の操作を履歴に残します。
一方、凍結中でも取引履歴を読めるかなど、閲覧と更新は分けて設計します。何を止める状態なのかを言葉で定義しないと、画面ごとに解釈が変わります。
管理者同士の競合
二人の管理者が同じ対象を同時に操作する場合、片方が見た状態はもう古いかもしれません。承認と拒否が競合したらどうするか、口座の凍結と解除が続いたらどちらを有効にするかを処理側で決めます。
「確認画面を出した」だけで競合は防げません。確定時の状態確認やロック、明確なエラーが必要です。
操作履歴が答えるべき問い
監査画面で、対象口座に何が起きたか、どの管理者が実行したか、成功したか失敗したかを調べられると、問い合わせや障害調査に役立ちます。元の帳簿と監査ログを自由に書き換えられないことも重要です。
ただしログを多く集めればよいわけではありません。秘密情報を避けながら、業務の判断を後で再現できる粒度を選びます。
緊急操作と通常操作
口座凍結は急いで止めたい場面があり得ますが、急ぎを理由に対象確認や監査を省くと、別の口座を止めた原因を追えません。通常時と緊急時の操作をどう分けるか、誰が解除できるか、解除の理由をどこに残すかを考える必要があります。
役割を持つ人の管理も業務
管理者の役割を付与・停止できる人をどう決めるかは、口座を操作する権限と同じくらい重要です。退職や担当変更で権限を止めた後、古いセッションから操作できないことを確かめます。
管理者一覧、役割変更、無効化の操作も、実行者と結果を追えるようにします。強い権限を持つ人の管理を、単なる設定画面として扱わないことが必要です。
重要なコードを読む
v1.0.0 の実コードから、この章で押さえたい箇所だけを抜粋しました。前後の定義は省略しています。
管理者の権限をロックして確認する
SQL / PLpgSQL select role, status into v_operator_role, v_operator_status
from admin.admin_operators where user_id = v_auth_uid for update;
if v_operator_role is null then
raise exception 'not an admin operator' using errcode = 'AD002';
end if;
if v_operator_status <> 'active' then
raise exception 'admin operator is disabled' using errcode = 'AD003';
end if;まず理解する凍結操作の前に、操作する管理者自身の行をロックし、管理者であり有効な状態かを確かめます。
一歩深く待機中に管理者の権限が変更される競合を防ぎます。ロックは処理の終わりまで保持されるため、確認した権限と実行時の権限がずれません。
出典:supabase/migrations/20260823100001_fix_admin_toctou_lock_own_operator_row.sql