ハンズオン

組織、チーム、テナント分離

個人ワークスペース、ロール、招待、席数上限、テナント分離、共有クレジット、組織課金を設定します。

starter のコミット 7d452a6 に同期しています。

すべてのアカウントに組織がある

サインアップ時に個人組織と owner メンバーシップを作成します。ユーザー所有リソースという別経路はなく、ファイル、タスク、注文、契約、クレジット、API キー、予約は org_uuid を使います。

Better Auth がメンバーシップと招待を提供し、Sushi がテナント範囲、権限、席数制限、共有残高、同時実行ガードを追加します。

ロール

階層は owneradminmember です。

操作MemberAdminOwner
データ閲覧、ファイル作成/削除、クレジット消費
招待、削除、ロール変更
組織更新
課金管理、組織削除

getOrgContext(request, optionalSlug) で利用者・組織・ロールを解決し、can(ctx, action, resource) で認可します。リクエスト body の org_uuid は信用しません。

テナント分離と席数

テナント表のクエリは model 内で scopedToOrg(column, ctx.orgUuid) を使います。アーキテクチャテストが範囲のない読み書きを検出します。

招待は 72 時間で期限切れになり、招待先メールに紐づき、有効な間は席を予約します。

プラン総席数
Free1
Plus5
Max20

送信時と承認時の両方で、同じ組織単位の PostgreSQL advisory lock の下で確認します。管理画面から監査付きの一時・無期限例外も設定できます。

不変条件

  • 最後の owner は削除できません。
  • 唯一の組織から退出できません。
  • 自分より上のロールを付与できません。
  • ダウングレードは既存メンバーやデータを削除せず、新規追加だけを止めます。
  • クレジットと Stripe Customer は組織に属します。

UI は /{locale}/account/team、API は /api/account/team/* です。組織切替、slug ルート、カスタムロール、Stripe の席数課金はまだ含まれません。

組織、チーム、テナント分離 · Sushi SaaS