マルチテナントSaaSの権限を、組織・チーム・ロール・所有権のルールをわかりやすく説明。チェックリストとスケールする実例つきで、安全に運用できる設計を紹介します。

権限の問題はたいてい小さな面倒ごとから始まります。チケットが来る:「私は管理者なのに請求書が見られません」。別のチケット:「なぜ同僚が設定を編集できるの?」 人はクリックして探し、推測し、時にはアクセスの整理より速いので「オーナー」ログインを共有してしまいます。
すると応急処置が積み重なります。チームは「Admin 2」や「Manager (no delete)」のような役割を作ります。エンジニアは「もしユーザーがSalesに入っていたらエクスポートを許可する」など、その場しのぎのチェックを追加します。1か月後、どのルールが意図されたものか、どれが事故なのか誰にもわからなくなります。
顧客が増えるとさらに悪化します。1社では問題にならなかったルール(「管理者はすべてのデータを見られる」)が、何百もの組織で破綻します。ある顧客は部署間を厳密に分離したい。別の顧客は共有ワークスペースを望む。契約社員はあるプロジェクトだけ見たい。モデルが明確でないと、新しい顧客ごとに例外を作ることになります。
目標は単純です:1分で説明できる予測可能なアクセスルール。例えば:「組織がデータを所有する。チームは人をまとめる。ロールは操作を定義する。リソースは組織、時にチームに属する。共有はいくつかのデフォルトに従う。」これを明瞭に言えなければ、作るのもテストするのも変更するのも難しくなります。
守るべき約束は、ロールを減らし、所有権を明確にし、安全なデフォルトにすることです。実際の職務に結びついた小さなロールセットから始め、すべてのリソースに対して所有者を明示し、最小権限をデフォルトにします。共有は意図的に、事故ではなく許可していくべきです。
アプリが複数の顧客にサービスを提供するなら、ルールを書く前にメンタルマップを正しく持ちましょう。マルチテナントSaaSの混乱の多くは、同じ用語が製品の別の場所で異なる意味になってしまうことから生じます。
テナント境界の意味を一つに決め、それを守ってください。多くのプロダクトは「組織」をテナントとし、すべてのデータは組織内にあり、明示的な共有を作らない限り越境しない、という設計を取ります。
成長してもブレないシンプルな語彙:
「一人が複数の組織に属する」のは普通です。コンサルタントは3つの顧客組織に所属し、それぞれ別のロールを持つかもしれません。だから「ユーザー」と「メンバーシップ」は分けて考え、チェックは通常メンバーシップに依存します。
チームは「サポート」や「経理」のように現実のまとまりを反映すると有益です。チームが2つ目の権限システムになるとノイズになります。テストは簡単です:チームを一文で説明できるか、それが特定の機能ルールに依存していないかを確認してください。
例:Mariaは一度ログインし、Org AとOrg Bを切り替えます。Org AではFinanceにいて請求書を表示でき、Org BではViewerでプロジェクトを閲覧のみできます。同じユーザーでもメンバーシップが違えば権限は明確です。
マルチテナントSaaSの権限は、次の3つを分けるとわかりやすくなります:
RBAC(ロールベースのアクセス制御)は、ユーザーにロールを与え、そのロールが許可されたアクションを与える仕組みです。ロール名は状態ではなく責任を表すべきです。「Billing Admin」は明確ですが「Power User」は議論が起きがちです。
権限は動詞として扱い、一貫性を保ちます:
同じ動詞を異なる場所で使えるようにスコープを加えます。これで似たようなロールを20個作るのを避けられます。
よく使われる読みやすいスコープ例:
「Project Editor」と「Project Editor (Own)」のようなロールが増えるとしたら、それはたいていスコープの問題です。
例:CRMでは「Sales Rep」に案件の作成・編集を許可するが、スコープを「own items」に制限します。「Sales Manager」は同じ動詞を持ちながら「team-only」や「org-wide」のスコープを持たせます。そうすればロールは少なく、ルールは明確になります。
良いデフォルトは:ロールは動詞を与え、所有権(または割り当て)がどこでそれが作用するかを制限する、です。
1つの顧客では動くモデルが10だと壊れるなら、「誰が見られるか」と「誰ができるか」と「誰が所有するか」を混ぜてしまっている可能性があります。これらを分ければシステムは予測可能になります。
スケールするルール例:
例:SamはOrg AとOrg Bに所属。Org AではMemberで自分のレポートを作成・編集できるが請求は触れない。Org BではBilling Managerで支払い方法を更新し請求書をダウンロードできるが、メンバーシップにその領域が含まれていない限りプライベートプロジェクトは見られない。
こうすると成長が「つまらない」ほど楽になります。新しい組織を追加するのはメンバーシップとロールを追加するだけで、コアルールは変わりません。
チームメイトが2分で読める1ページを書いてください。コードを開かずに説明できるなら良い状態です。
部品は意図的に小さく保ちます:
スコープを使えばロールの爆発を避けられます。多くのプロダクトは3つのスコープで足ります:own、team、org。
| Role | View | Edit | Invite users | Billing | Scope note |
|---|---|---|---|---|---|
| Owner | Yes | Yes | Yes | Yes | Org-wide, can transfer ownership |
| Admin | Yes | Yes | Yes | No/Yes | Org-wide, no ownership changes |
| Member | Yes | Limited | No | No | Own + team (where assigned) |
| Viewer | Yes | No | No | No | Read-only in assigned scope |
健康診断:このページを非技術の同僚に見せて「SupportメンバーはSalesのレポートを編集できるか?」と聞いてみてください。ためらうなら、スコープかチーム定義が不明瞭です。
権限を理解しやすくするため、まず各リソースの所有者を決め、共有オプションは限定してください。
多くのリソースは組織所有にします。顧客は会社単位で考えることが多く、請求書、プロジェクト、連絡先、チケット、自動化は組織に属すると期待します。
チームは有用ですが、ワークフローのラベル(ルーティングや可視性のデフォルト)として扱い、重要なセキュリティロジックにしないでください。チームタグはフィルタ、ダッシュボード、通知、キューに使えますが、アクセスはロールとスコープから来るべきです。
ユーザー所有のリソースは例外にし、真に個人的なもの(下書き、プライベートノート、保存ビュー、APIトークン、個人設定)に限定します。ユーザーが離れたときの扱いを決めておきましょう:削除、移譲、保持のいずれか。
読みやすさを保つ小さな共有ルール:
「アクセスが必要だ」と言われたら、それが個人のプライベートかチームか組織全体かを詰めてください。それが3つのどれにも当てはまらないなら、スコープが不明瞭なサインです。
例:サポートチケットは組織所有(マネージャーが全チケットを集計できる)、Supportにチームタグ付け(適切なキューに表示)、Jordanに割り当て(責任者)。割り当ては他の許可されたロールの閲覧をブロックしてはいけません。
権限はしばしば「人が関わるイベント」で破綻します:招待、チーム移動、アクセス削除。これらのフローがモデルを予測可能に保てるかを決めます。
招待はメンバーシップ作成のリクエストと扱い、招待自体が即時アクセスを与えるものではありません。招待は、承認時に付与される組織、チーム(任意)、ロールを明示すべきです。
ルールを厳しく:
一時的なアクセスはここで扱えます。"temp user"ロールを作る代わりに、ロール付与に終了日を設定し、期限が来たら自動でアクセスを落とすとよいです。
誰かが組織を離れるとき、資源を勝手に処理しないでください。ルールが「リソースは組織所有」であれば、それを守ります。作成者は履歴として残しても組織が所有者です。
ユーザー所有のリソースがあるなら、削除前に移譲を要求する(プロジェクト、ドキュメント、APIキーなど重要なもの)。
1つのログインが複数の組織に属しても、アプリは常に「現在の組織」を持つべきです。UIで明確に示し、すべての操作をそれにスコープします。
非アクティブ化は削除より優れます。今すぐアクセスを外しつつ、過去の操作は監査できる状態を保ちます。
多くの権限モデルはルールより速く成長するため失敗します。基本(テナント境界、所有、スコープ)を守り、その他は詳細として扱ってください。
ロールの爆発は典型的な罠です。エッジケースが現れ新しいロールを作ると、数か月後に「Manager Plus」が何を意味するかわからなくなります。頻繁に必要なら第一級の権限にし、稀なら期限付きの一時付与で対応しましょう。
**権限の乖離(permission drift)**は静かに進みます。「ちょっと例外を追加」してモデルを更新し忘れると、1年後にドキュメントと実システムが一致しません。まずモデルを更新してから実装してください。
チームを偽のセキュリティ境界にすると常に混乱します。リソースが組織内でチームを越えて共有できるなら明確に伝える。できないならコードで強制し、名前で誤解させないでください。
早めに見つけるべきレッドフラッグ:
サポートが助けるために「グローバル管理者を1分だけ付与する」はテナント分離の漏洩につながります。代わりに、明示的でログ済みのアクセス(特定組織、時間枠、操作)を好みます。
各リクエストはまずアクティブな組織コンテキストを解決し(サブドメイン、ヘッダ、セッション、ルートから)、一致しないものは拒否してください。
組織コンテキストの後は一貫した順序でチェックします:メンバーシップ(この組織にいるか?)、ロール(ここで何が許可されるか?)、所有権や共有(このレコードにアクセス権があるか?)。所有権を先にチェックすると、その存在を漏らす可能性があります。
エンドツーエンドの小さなテストセットを実際のアカウントで回してください(単なるユニットテストではなく):
ロール変更、メンバー削除、エクスポート、削除、設定更新など、権限を変える・データを動かす操作には基本的な監査イベントを追加してください。完璧である必要はありませんが、「誰が何をいつしたか」に答えられる必要があります。
デフォルトを見直すこと。新規組織や新規メンバーは成功に最低限必要なアクセスから始めるべきです。サポートや営業向けの内部FAQも役立ちます(例:「チームリードは他チームを見られるか?」「削除後のアクセスはどうなる?」など)。
まずは小さな実例で始めてください:1社(1組織)に2つのチーム、SalesとOps。全員一度サインインして自分の属する組織を選ぶ。Salesは顧客情報と見積が必要、Opsは請求と内部設定が必要。
チームはグルーピングとワークフローに留め、主な権限のスイッチにしないでください。デフォルトやルーティングには使えますが、唯一のゲートにしない。
Admin、Member、Viewerなど少数のロールを選び、機能追加後も安定させます。ロールは「この組織で何ができるか」を答え、スコープは「どこでそれができるか」を答えます。
1つの所有ルールを追加:各リソースは組織と所有者(多くは作成者)を持つ。編集はAdminであれば可、または所有者でかつロールが「edit own」を含む場合に可。閲覧はそのリソースタイプに対してロールが「view」を含めば可。
例:Sales Memberが見積を作成。別のSales Memberは閲覧はできるが、チーム共有や再割り当てが無ければ編集はできない。Ops Viewerはルールが許せばSalesリソースを見られる。
200の顧客組織をオンボードしても、同じロールと所有ルールを再利用します。変更するのはメンバーシップだけでモデルはそのまま。
サポートの要望「Xにアクセス付与できますか?」はチェックリストになります:組織とリソースを確認、ユーザーのその組織でのロールを確認、所有権と共有を確認、ロール変更か共有を行う。ワンオフの例外は避け、監査ノートを残してください。
1ページのモデルを契約として扱ってください。すべてのAPI呼び出しとUI画面で強制できるルールだけを実装しなければ、権限は「場合による」に堕ちます。
小さく始める:少数のロール、明確なスコープ、単純な所有権。新しい要求が来たら(「Editor-Managerを追加できますか?」)、まず所有権やスコープで解決できないか検討してください。新しいロールは稀にするべきです。
新しいリソースを追加するたびに基本を一貫させる:
org_id を保存する(チーム適用なら team_id も)エッジケースを磨く前に実際のフロー(招待、組織切替、管理画面、アクセス喪失中の挙動)をテストしてください。
チャットベースのアプリビルダーで作る場合、権限モデルを平易な言葉で先に書き、製品仕様と並べて置くと便利です。Koder.ai (koder.ai) の Planning Mode やスナップショット、ロールバックは、これらのシナリオを試してルールがウェブ、バックエンド、モバイルで一貫することを確認する実践的な方法です。