# 機能設計書 83-ロールポリシー紐付け

## 概要

本ドキュメントは、Medusaコマースプラットフォームにおけるロールポリシー紐付け機能の設計について記述する。RBAC（Role-Based Access Control）モジュールの構成要素として、ロールとポリシーの関連付け管理を行う。

### 本機能の処理概要

**業務上の目的・背景**：ECサイト運営において、「管理者ロール」に「商品編集」「注文管理」などの複数ポリシーを紐付けることで、ロールベースのアクセス制御を実現する。個別のユーザーごとに権限を設定するのではなく、ロール単位で権限を管理することで、権限管理の効率化、一貫性の確保、監査対応の容易化を実現する。

**機能の利用シーン**：新規ロール作成時のポリシー割り当て、ロールの権限拡張・縮小時のポリシー追加・削除、組織変更に伴うロール権限の見直しなどで利用される。

**主要な処理内容**：
1. ロールポリシー紐付けの作成（createRbacRolePolicies）：ロールIDとポリシーIDを指定して関連を作成
2. ロールポリシー紐付けの一覧取得（listRbacRolePolicies）：特定ロールまたはポリシーの紐付け一覧を取得
3. ロールポリシー紐付けの削除（deleteRbacRolePolicies）：不要な紐付けをソフトデリート
4. ロールに対するポリシー一覧取得（listPoliciesForRole）：ロールIDを指定して継承ポリシー含むポリシー一覧を取得

**関連システム・外部連携**：ロール管理機能（ロール情報）、ポリシー管理機能（ポリシー情報）と連携する。

**権限による制御**：ロールポリシー紐付け操作にはRBACポリシーによる認可が必要。

## 関連画面

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

## 機能種別

CRUD操作 / 関連管理

## 入力仕様

### 入力パラメータ

#### ロールポリシー紐付け作成（createRbacRolePolicies）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| role_id | string | Yes | ロールID | 存在確認 |
| policy_id | string | Yes | ポリシーID | 存在確認 |
| metadata | object | No | カスタムメタデータ | JSON形式 |

#### ロールポリシー紐付け一覧取得（listRbacRolePolicies）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| role_id | string/string[] | No | ロールID | - |
| policy_id | string/string[] | No | ポリシーID | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | 紐付けID（プレフィックス: rlpl_） |
| role_id | string | ロールID |
| policy_id | string | ポリシーID |
| role | RbacRoleDTO | ロール情報（リレーション指定時） |
| policy | RbacPolicyDTO | ポリシー情報（リレーション指定時） |
| metadata | object/null | カスタムメタデータ |
| created_at | Date | 作成日時 |
| updated_at | Date | 更新日時 |
| deleted_at | Date/null | 削除日時（ソフトデリート） |

### 出力先

APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

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

2. バリデーション
   └─ role_id/policy_idの存在確認
   └─ 重複チェック（同一role_id + policy_idの組み合わせ）

3. 紐付け作成
   └─ rbac_role_policyテーブルにレコード挿入

4. レスポンス生成
   └─ 作成された紐付け情報を返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{操作種別}
    B -->|Create| C[存在確認]
    B -->|List| D[フィルタ条件適用]
    B -->|Delete| E[ソフトデリート]

    C -->|ロール存在| F[ポリシー存在確認]
    C -->|ロール不存在| G[エラー返却]
    F -->|ポリシー存在| H[重複チェック]
    F -->|ポリシー不存在| G
    H -->|重複なし| I[紐付け作成]
    H -->|重複あり| G

    D --> J[紐付け一覧取得]
    E --> K[deleted_at設定]

    I --> L[レスポンス返却]
    J --> L
    K --> L
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-83-1 | 複合一意制約 | 同一role_id + policy_idの組み合わせは作成不可 | 紐付け作成時 |
| BR-83-2 | 外部キー制約 | 存在するロールとポリシーのみ紐付け可能 | 紐付け作成時 |
| BR-83-3 | ソフトデリート | 削除はソフトデリートで実行 | 紐付け削除時 |
| BR-83-4 | ポリシー継承 | 親ロールのポリシーは子ロールに自動継承 | ポリシー取得時 |

### 計算ロジック

ポリシー継承は、ロール階層を再帰的に辿り、すべての親ロールに紐づくポリシーを集約する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| createRbacRolePolicies | rbac_role_policy | INSERT | 紐付けレコード作成 |
| listRbacRolePolicies | rbac_role_policy | SELECT | 紐付け一覧取得 |
| deleteRbacRolePolicies | rbac_role_policy | UPDATE | deleted_at設定 |
| listPoliciesForRole | rbac_role_policy, rbac_policy, rbac_role_parent | SELECT | 継承含むポリシー取得 |

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

#### rbac_role_policy

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | rlpl_プレフィックス + UUID | 自動生成 |
| INSERT | role_id | ロールID | 外部キー |
| INSERT | policy_id | ポリシーID | 外部キー |
| INSERT | metadata | カスタムデータ（JSON） | 任意 |
| UPDATE | deleted_at | 現在日時 | ソフトデリート時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| NOT_FOUND | 検索エラー | 指定ロールが存在しない | 正しいロールIDを指定 |
| NOT_FOUND | 検索エラー | 指定ポリシーが存在しない | 正しいポリシーIDを指定 |
| DUPLICATE_ERROR | 重複エラー | 同一紐付けが存在 | 既存の紐付けを使用 |

### リトライ仕様

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

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

- 各操作はMedusaServiceの基底メソッドによりトランザクション管理される
- 複数紐付けの一括作成は同一トランザクション内で処理

## パフォーマンス要件

- 紐付け一覧取得：1000件以下で500ms以内
- ポリシー継承取得：階層深度10以下で500ms以内
- role_id/policy_idインデックスによる検索高速化

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

- 紐付け操作にはRBACポリシーによる認可が必要
- 権限エスカレーション防止のため、自身の権限を超えるポリシー割り当ては制限されるべき
- ソフトデリートによりデータ復旧可能性を確保

## 備考

- ロールへのポリシー一覧取得時は、親ロールからの継承ポリシーも含まれる
- 継承ポリシーには`inherited_from_role_id`で継承元が識別される

---

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

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

### 推奨読解順序

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

ロールポリシー紐付けの中間テーブル構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | rbac-role-policy.ts | `packages/modules/rbac/src/models/rbac-role-policy.ts` | role/policyリレーション、複合一意制約 |

**読解のコツ**: `model.belongsTo()`でロールとポリシーへの参照を定義。`indexes`配列で複合一意制約（role_id + policy_id）を設定している。

#### Step 2: ポリシー取得ロジックを理解する

ロールに紐づくポリシー（継承含む）の取得処理。

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

**主要処理フロー**:
- **171-177行目**（rbac-module-service.ts）: `listPoliciesForRole`メソッドがリポジトリに委譲
- **12-21行目**（rbac.ts）: `listPoliciesForRole`が単一ロール用のラッパー
- **23-89行目**（rbac.ts）: `listPoliciesForRoles`が複数ロール対応の本体
  - **36-51行目**: WITH RECURSIVEで親ロールを辿る
  - **52-68行目**: 辿った全ロールのポリシーをJOINで取得
  - **63行目**: `inherited_from_role_id`で継承元を識別

#### Step 3: CRUD操作を理解する

MedusaServiceが提供する基底CRUD操作。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | MedusaService継承 |

**主要処理フロー**:
- **42-47行目**: `MedusaService({ ... RbacRolePolicy })`でRbacRolePolicyエンティティを登録
- これにより`createRbacRolePolicies`、`listRbacRolePolicies`、`deleteRbacRolePolicies`が自動生成

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

```
API Route
    │
    └─ RbacModuleService
           │
           ├─ MedusaService (継承)
           │      └─ createRbacRolePolicies()
           │      └─ listRbacRolePolicies()
           │      └─ deleteRbacRolePolicies()
           │
           ├─ listPoliciesForRole()
           │      └─ rbacRepository_.listPoliciesForRole()
           │
           └─ rbacRolePolicyService
                  └─ create() / list() / softDelete()
```

### データフロー図

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

紐付け作成要求 ───▶ MedusaService.createRbacRolePolicies() ───▶ RbacRolePolicyDTO
                          │
                          └─▶ rbacRolePolicyService.create()
                                     │
                                     └─▶ rbac_role_policyテーブル INSERT

ポリシー取得要求 ───▶ RbacModuleService.listPoliciesForRole() ───▶ PolicyDTO[]
        │                      │
        │                      └─▶ rbacRepository_.listPoliciesForRole()
        │                                 │
        │                                 └─▶ WITH RECURSIVE クエリ
        │
        └─ role_id
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rbac-module-service.ts | `packages/modules/rbac/src/services/rbac-module-service.ts` | サービス | 紐付け管理、ポリシー取得 |
| rbac.ts | `packages/modules/rbac/src/repositories/rbac.ts` | リポジトリ | 継承ポリシー取得クエリ |
| rbac-role-policy.ts | `packages/modules/rbac/src/models/rbac-role-policy.ts` | モデル | 紐付けエンティティ定義 |
| rbac-role.ts | `packages/modules/rbac/src/models/rbac-role.ts` | モデル | ロールエンティティ（policiesリレーション） |
| rbac-policy.ts | `packages/modules/rbac/src/models/rbac-policy.ts` | モデル | ポリシーエンティティ |
