データベースと認可境界Database
松葉は社外の取引先もログインして使うため、「他社・他取引先のファイルが見えてしまう」事態は絶対に避けなければなりません。多くのシステムはアプリのコードだけでアクセス制御をしますが、それだとコードに 1 か所抜けがあった瞬間に漏えいします。松葉は最後の砦として、データベース自身が「あなたが見てよい行か」を判定する仕組み(行レベルセキュリティ、RLS)を入れ、DB へ触る入口も 3 つの経路に限定しました。
DB へ触る入口は 3 つだけThree routes & RLS
データベースへ触る方法を、用途別の 3 つの経路に限定しました。それぞれが、データベース側で別々の「立場(ロール)」を名乗ります。立場ごとに「見える行・触れる行」が RLS で決まるため、アプリのどこに抜けがあっても、立場に許されない行は返ってきません。
立場(ロール)の名乗り方: 各経路は、データベースとの 1 回のやり取りの中で「自分は今どの立場か」を宣言します。認証ユーザなら authenticated、共有リンク受取なら anon、システム処理なら service_role です。RLS は宣言された立場をもとに、行ごとに見えるかどうかを判定します。service_role だけは定期処理・連携のため RLS を越える権限を持つので、その経路は限られた場所からしか使えないようにしています。
authenticated の立場で「あなたはその行を見られない」と判定し、データを返しません。
呼び方の注意: 松葉のこの仕組みは「マルチテナント」とは呼ばず、「Box 認可境界」と呼んでいます。会社単位ではなく、共有の単位である Box ごとに「見える・見えない」の境界を引いているためです。資料の中でも「Box 境界」「Box 越境(境界を越えてしまうこと)」という言い方で統一しています。
「見てよいか」を判定する部品Helpers & roles
RLS が行ごとに判定するとき、その根拠になる小さな判定関数を 8 種類用意しました。ログイン時に発行される証明書(トークン)の中身を読み取り、「この人は誰か」「どの Box でどの権限か」を返します。
| 判定関数 | 何を判定するか |
|---|---|
current_user_id | 今アクセスしているのは誰か(ユーザ ID) |
current_user_box_ids | その人が参加している Box の一覧 |
current_user_role_for_box | ある Box でのその人の権限(4 ロールのどれか) |
is_system_admin | システム管理者かどうか |
is_internal_user | 社内ユーザかどうか(社外と区別) |
current_share_link_id | 共有リンク経由のとき、どのリンクか |
can_view_box_via_visibility | Box の公開設定上、その Box 自体を閲覧できるか |
can_read_box_contents_via_visibility | Box の公開設定上、中のファイル・フォルダを閲覧できるか |
Box の中での権限は 4 段階です。下にいくほどできることが増えます。これは認証システム(Better Auth)の仕組みを使い、Box を 1 つのテーブルで一元管理しています。
| 権限(ロール) | できること |
|---|---|
viewer(閲覧者) | ファイルの閲覧・ダウンロード |
uploader(投稿者) | 閲覧に加えて、ファイルのアップロード |
editor(編集者) | 投稿に加えて、ファイル・フォルダの編集・削除 |
owner(管理者) | 編集に加えて、Box のメンバー管理・設定変更 |
社内と社外で入口が違います: 社内ユーザは会社の Google アカウントでログイン(@example.com 限定)。社外の取引先は招待制で、メールアドレス + パスワードに加えてワンタイムコード(OTP)による二段階認証を必須にしています。どちらの立場でも、上の RLS と 4 ロールによる制御は同じように効きます。
追記専用の監査記録Append-only audit
「誰が・いつ・何をしたか」の記録(監査ログ)は、後から書き換えたり消したりできては意味がありません。松葉の監査ログは、追記(新しい記録の追加)だけを許可し、更新・削除をデータベースの権限レベルで拒否しています。
三重の守り: ①更新・削除のポリシーを作らないことで RLS が拒否し、さらに②権限(GRANT)レベルでも更新・削除を取り消して二重に防ぎます。③記録は月ごとに自動分割し、古い月の分はストレージ(GCS)へ退避して、長期にわたり安全・低コストに保管します。記録は専用の書き込み関数を介さず、各処理が通常の追記として残すシンプルな方式です。
正直な注記: ここで説明した RLS・追記専用ルールは、データベースに対して人手で慎重に適用する運用にしています(自動適用はしません)。また現時点では、これらの「守りの仕組み」が先に組まれた段階で、実際にデータを読み書きする業務処理は今後の開発で載せていきます。土台としての守りを先に固めておくことが狙いです。