# 機能設計書 81-ロール管理

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおけるロール管理機能の設計について記述する。RBAC（Role-Based Access Control）モジュールの中核機能として、ユーザーロールの作成・取得・更新・削除を行う。

### 本機能の処理概要

**業務上の目的・背景**：ECサイトの運営において、管理者、オペレーター、閲覧者など異なる権限レベルを持つユーザーが存在する。ロール管理機能は、これらのユーザーグループごとに適切なアクセス権限を付与し、セキュリティを確保しながら効率的な業務運営を実現するために必要不可欠である。不正アクセスの防止、業務分担の明確化、コンプライアンス対応などの課題を解決する。

**機能の利用シーン**：新規管理者アカウントの作成時にロールを割り当てる場面、組織変更に伴うロール構成の見直し、新機能追加時の権限設計、セキュリティ監査時のロール一覧確認などで利用される。

**主要な処理内容**：
1. ロールの作成（createRbacRoles）：名前、説明、メタデータを指定してロールを新規作成
2. ロールの一覧取得（listRbacRoles）：フィルタ条件を指定してロールを検索・取得
3. ロールの詳細取得（retrieveRbacRole）：IDを指定して特定のロールを取得
4. ロールの更新（updateRbacRoles）：ロール名、説明等の情報を更新
5. ロールの削除（deleteRbacRoles）：不要なロールをソフトデリート
6. ロール階層の管理（createRbacRoleParents）：親子関係によるロール継承の設定

**関連システム・外部連携**：ユーザーモジュール（ユーザーへのロール割り当て）、ポリシー管理機能（ロールへのポリシー紐付け）と連携する。

**権限による制御**：ロール管理機能自体がRBACの対象であり、`rbac_role:create`、`rbac_role:read`、`rbac_role:update`、`rbac_role:delete`などのポリシーによってアクセス制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （画面未実装）| - | 本機能はAPI経由で利用 |

## 機能種別

CRUD操作 / 階層構造管理

## 入力仕様

### 入力パラメータ

#### ロール作成（createRbacRoles）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | string | Yes | ロール名 | 一意制約、空文字不可 |
| description | string | No | ロールの説明 | - |
| metadata | object | No | カスタムメタデータ | JSON形式 |

#### ロール一覧取得（listRbacRoles）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | string/string[] | No | ロールID | - |
| name | string/string[] | No | ロール名 | - |
| q | string | No | 検索クエリ | - |

#### ロール階層設定（createRbacRoleParents）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| role_id | string | Yes | 子ロールID | 存在確認 |
| parent_id | string | Yes | 親ロールID | 存在確認、循環参照チェック |

### 入力データソース

API経由でのJSON形式リクエストボディ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | ロールID（プレフィックス: role_） |
| name | string | ロール名 |
| description | string/null | ロールの説明 |
| metadata | object/null | カスタムメタデータ |
| policies | RbacPolicyDTO[] | 紐づくポリシー一覧（リレーション指定時） |
| parents | RbacRoleParentDTO[] | 親ロール関係（リレーション指定時） |
| created_at | Date | 作成日時 |
| updated_at | Date | 更新日時 |
| deleted_at | Date/null | 削除日時（ソフトデリート） |

### 出力先

APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ APIルーターがリクエストをRbacModuleServiceに転送

2. バリデーション
   └─ 入力パラメータの検証、一意制約チェック

3. ビジネスロジック実行
   └─ MedusaServiceの基底メソッド呼び出し
   └─ 階層設定時は循環参照チェック実行

4. データベース操作
   └─ トランザクション内でCRUD操作実行

5. レスポンス生成
   └─ DTOへの変換、関連データの取得
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{操作種別}
    B -->|Create| C[名前一意チェック]
    B -->|List/Retrieve| D[フィルタ条件適用]
    B -->|Update| E[存在確認]
    B -->|Delete| F[ソフトデリート]
    B -->|Parent設定| G[循環参照チェック]

    C -->|OK| H[ロール作成]
    C -->|NG| I[エラー返却]
    D --> J[ポリシー取得]
    J --> K[レスポンス返却]
    E --> L[ロール更新]
    F --> K
    G -->|OK| M[親子関係作成]
    G -->|NG| I

    H --> K
    L --> K
    M --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-81-1 | ロール名一意制約 | 同一名のロールは作成不可 | ロール作成・更新時 |
| BR-81-2 | 循環参照禁止 | ロール階層で循環は許可しない | 親ロール設定時 |
| BR-81-3 | 自己参照禁止 | ロールは自分自身を親に設定不可 | 親ロール設定時 |
| BR-81-4 | ソフトデリート | 削除はソフトデリートで実行 | ロール削除時 |
| BR-81-5 | ポリシー継承 | 親ロールのポリシーは子ロールに継承される | ポリシー取得時 |

### 計算ロジック

ポリシー継承の計算は、RbacRepositoryの再帰CTEクエリ（WITH RECURSIVE）を使用して階層を辿り、すべての継承ポリシーを取得する。

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| createRbacRoles | rbac_role | INSERT | ロールレコード作成 |
| listRbacRoles | rbac_role, rbac_role_policy, rbac_policy | SELECT | ロール一覧取得 |
| retrieveRbacRole | rbac_role | SELECT | 単一ロール取得 |
| updateRbacRoles | rbac_role | UPDATE | ロール情報更新 |
| deleteRbacRoles | rbac_role | UPDATE | deleted_at設定 |
| createRbacRoleParents | rbac_role_parent | INSERT | 親子関係作成 |

### テーブル別操作詳細

#### rbac_role

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | role_プレフィックス + UUID | 自動生成 |
| INSERT | name | リクエスト値 | 必須 |
| INSERT | description | リクエスト値 | 任意 |
| INSERT | metadata | リクエスト値（JSON） | 任意 |
| UPDATE | deleted_at | 現在日時 | ソフトデリート時 |

#### rbac_role_parent

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | role_id | 子ロールID | 必須 |
| INSERT | parent_id | 親ロールID | 必須 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| DUPLICATE_ERROR | 重複エラー | 同一名のロールが存在 | 別名を使用 |
| NOT_FOUND | 検索エラー | 指定IDのロールが存在しない | 正しいIDを指定 |
| INVALID_DATA | 検証エラー | 循環参照が発生 | 階層構造を見直し |
| INVALID_DATA | 検証エラー | 自己参照が発生 | 異なるロールを親に指定 |

### リトライ仕様

データベースデッドロック発生時は、トランザクションマネージャーにより自動リトライされる。

## トランザクション仕様

- 各操作は`@InjectManager()`または`@InjectTransactionManager()`デコレータによりトランザクション管理される
- 複数レコードの一括操作時は同一トランザクション内で処理
- 循環参照チェックは親子関係作成前にトランザクション内で実行

## パフォーマンス要件

- ロール一覧取得：1000件以下で1秒以内
- ポリシー継承取得：階層深度10以下で500ms以内
- 名前インデックス使用による検索の高速化

## セキュリティ考慮事項

- ロール管理操作にはRBACポリシーによる認可が必要
- スーパー管理者ロール（*:*ポリシー保持）の変更には特別な注意が必要
- ソフトデリートによりデータ復旧可能性を確保
- 循環参照チェックによる権限エスカレーション防止

## 備考

- アプリケーション起動時に`syncRegisteredPolicies`が実行され、コードで定義されたポリシーがDBと同期される
- ロール継承は再帰CTEを使用し、無限ループを`path`配列で防止

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、ロール管理で使用されるエンティティモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rbac-role.ts | `packages/modules/rbac/src/models/rbac-role.ts` | ロールエンティティの定義、name一意制約、policies/parentsリレーション |
| 1-2 | rbac-policy.ts | `packages/modules/rbac/src/models/rbac-policy.ts` | ポリシーエンティティの定義、key/resource/operationフィールド |
| 1-3 | rbac-role-policy.ts | `packages/modules/rbac/src/models/rbac-role-policy.ts` | ロールとポリシーの中間テーブル、複合一意制約 |
| 1-4 | rbac-role-parent.ts | `packages/modules/rbac/src/models/rbac-role-parent.ts` | 親子関係を表す中間テーブル |

**読解のコツ**: MedusaのDMLモデル定義では、`model.define()`でエンティティを定義し、`model.hasMany()`/`model.belongsTo()`でリレーションを設定する。`.indexes()`でインデックス定義、`.searchable()`で検索対象フィールドを指定する。

#### Step 2: エントリーポイントを理解する

RbacModuleServiceがロール管理の主要サービスである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | サービスクラスの構造、依存性注入、MedusaService継承 |

**主要処理フロー**:
1. **41-48行目**: MedusaServiceを継承し、RbacRole, RbacPolicy, RbacRoleParent, RbacRolePolicyエンティティを登録
2. **61-73行目**: コンストラクタで依存サービス（rbacRepository, rbacRolePolicyService等）を注入
3. **75-79行目**: `__hooks`でアプリケーション起動時のポリシー同期を設定

#### Step 3: ポリシー同期処理を理解する

アプリケーション起動時に実行されるポリシー同期ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | syncRegisteredPoliciesメソッド |

**主要処理フロー**:
- **85-169行目**: `syncRegisteredPolicies`メソッド
  - **89-97行目**: `Policy`オブジェクトから登録済みポリシーを抽出
  - **102-106行目**: 既存ポリシーをDB（ソフトデリート含む）から取得
  - **114-145行目**: 新規作成・更新・復元対象を分類
  - **147-154行目**: 不要ポリシーのソフトデリート対象を特定
  - **161-168行目**: `promiseAll`で並列にDB操作を実行

#### Step 4: ロール一覧取得とポリシー継承を理解する

ロール取得時のポリシー継承ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | listRbacRoles, listAndCountRbacRolesメソッド |
| 4-2 | rbac.ts | `packages/modules/rbac/src/repositories/rbac.ts` | listPoliciesForRoles再帰CTEクエリ |

**主要処理フロー**:
- **179-209行目**: `listRbacRoles`メソッド
  - **192-194行目**: policiesリレーションが要求されているかチェック
  - **196-206行目**: 要求されている場合、リポジトリから継承ポリシーを取得
- **36-89行目**（rbac.ts）: `listPoliciesForRoles`メソッド
  - **36-69行目**: WITH RECURSIVEクエリで親ロールを辿りポリシーを取得
  - **63行目**: `inherited_from_role_id`で継承元を識別

#### Step 5: 親子関係の循環チェックを理解する

ロール階層作成時の循環参照防止ロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | createRbacRoleParents, updateRbacRoleParentsメソッド |
| 5-2 | rbac.ts | `packages/modules/rbac/src/repositories/rbac.ts` | checkForCycleメソッド |

**主要処理フロー**:
- **243-272行目**: `createRbacRoleParents`メソッド
  - **252-256行目**: 自己参照チェック（role_id === parent_id）
  - **258-268行目**: 循環参照チェックを実行、エラー時は例外送出
- **91-125行目**（rbac.ts）: `checkForCycle`メソッド
  - **102-121行目**: WITH RECURSIVEで親ロールを辿り、role_idに到達するかチェック
  - **116行目**: `path`配列で無限ループを防止

### プログラム呼び出し階層図

```
API Route
    │
    └─ RbacModuleService
           │
           ├─ MedusaService (継承)
           │      └─ 基本CRUD操作
           │
           ├─ rbacRepository_
           │      ├─ listPoliciesForRole()
           │      ├─ listPoliciesForRoles()
           │      └─ checkForCycle()
           │
           ├─ rbacRoleService
           │      └─ create() / update() / list() / softDelete()
           │
           ├─ rbacPolicyService
           │      └─ create() / upsert() / softDelete()
           │
           └─ rbacRolePolicyService
                  └─ create() / list()
```

### データフロー図

```
[入力]                    [処理]                           [出力]

ロール作成要求 ───▶ RbacModuleService.createRbacRoles() ───▶ RbacRoleDTO
                          │
                          └─▶ rbacRoleService.create()
                                     │
                                     └─▶ rbac_roleテーブル INSERT

ロール一覧要求 ───▶ RbacModuleService.listRbacRoles() ───▶ RbacRoleDTO[]
                          │
                          ├─▶ super.listRbacRoles()
                          │
                          └─▶ rbacRepository_.listPoliciesForRoles()
                                     │
                                     └─▶ 再帰CTEクエリ実行

親子関係作成 ───▶ RbacModuleService.createRbacRoleParents() ───▶ RbacRoleParentDTO
                          │
                          ├─▶ 自己参照チェック
                          │
                          ├─▶ rbacRepository_.checkForCycle()
                          │
                          └─▶ super.createRbacRoleParents()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | サービス | ロール管理の主要ビジネスロジック |
| rbac.ts | `packages/modules/rbac/src/repositories/rbac.ts` | リポジトリ | ポリシー継承・循環チェックのカスタムクエリ |
| rbac-role.ts | `packages/modules/rbac/src/models/rbac-role.ts` | モデル | ロールエンティティ定義 |
| rbac-policy.ts | `packages/modules/rbac/src/models/rbac-policy.ts` | モデル | ポリシーエンティティ定義 |
| rbac-role-policy.ts | `packages/modules/rbac/src/models/rbac-role-policy.ts` | モデル | ロール-ポリシー中間テーブル |
| rbac-role-parent.ts | `packages/modules/rbac/src/models/rbac-role-parent.ts` | モデル | ロール親子関係テーブル |
| index.ts | `packages/modules/rbac/src/index.ts` | エクスポート | モジュールエクスポート |
