# 機能設計書 2-アクセスゲート（Gate）

## 概要

本ドキュメントは、Laravel Frameworkのアクセスゲート機能（Gate）について、その設計思想、処理フロー、および実装詳細を記述したものである。リソースへのアクセス制御を提供し、ポリシーベースの認可ロジックをサポートする機能設計を定義する。

### 本機能の処理概要

アクセスゲート機能は、アプリケーション内のリソースに対するきめ細かいアクセス制御を実現する認可システムである。アビリティ（能力）の定義、ポリシークラスとの連携、before/afterコールバックによる柔軟な認可判定を提供する。

**業務上の目的・背景**：認証（誰であるか）と認可（何ができるか）は別の概念である。本機能は認可の責務を担い、「このユーザーはこのリソースに対してこの操作を行う権限があるか」を判定する。ロールベース、リソースベース、ポリシーベースなど様々な認可パターンをサポートし、複雑なビジネスロジックに基づくアクセス制御を実現する。

**機能の利用シーン**：
- 記事の編集権限チェック（作成者のみ編集可能）
- 管理者権限の確認
- リソースCRUD操作の認可
- APIエンドポイントのアクセス制御
- ブレードテンプレートでの条件分岐（@can/@cannot）

**主要な処理内容**：
1. アビリティの定義と管理
2. ポリシークラスの解決と実行
3. before/afterコールバックによる認可フック
4. ユーザー別のゲートインスタンス生成
5. GateEvaluatedイベントの発火
6. 認可レスポンスの生成

**関連システム・外部連携**：
- Auth Manager（認証ユーザーの取得）
- DIコンテナ（ポリシークラスの解決）
- Event Dispatcher（認可イベント通知）
- Bladeテンプレートエンジン（@can/@cannotディレクティブ）

**権限による制御**：本機能自体が権限制御の中核であり、認可判定の結果に基づいてアクセス可否を決定する。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | 403 Forbidden | 主画面 | アクセス禁止エラー発生時の認可チェック失敗表示 |

## 機能種別

認可処理 / アクセス制御 / ポリシー管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ability | string\|UnitEnum | Yes | 認可対象のアビリティ名 | - |
| arguments | array\|mixed | No | 認可判定に渡す引数（リソース等） | - |
| user | Authenticatable | No | 認可対象ユーザー（省略時は現在のユーザー） | - |

### 入力データソース

- コントローラメソッド（authorize()呼び出し）
- ミドルウェア（can:ability）
- Bladeテンプレート（@can/@cannot）
- フォームリクエスト（authorize()メソッド）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| allowed | bool | 認可成功/失敗 |
| response | Response | 認可レスポンス（メッセージ、コード含む） |

### 出力先

- HTTPレスポンス（403 Forbiddenまたは続行）
- Event Dispatcher（GateEvaluatedイベント）

## 処理フロー

### 処理シーケンス

```
1. アビリティ解決
   └─ abilities配列またはポリシークラスからコールバックを解決
2. beforeコールバック実行
   └─ 登録済みbeforeコールバックを順次実行（非null返却で早期終了）
3. 認可判定
   └─ アビリティコールバックまたはポリシーメソッドを実行
4. afterコールバック実行
   └─ 登録済みafterコールバックを順次実行
5. イベント発火
   └─ GateEvaluatedイベントをディスパッチ
6. レスポンス生成
   └─ Response::allow()またはResponse::deny()を返却
```

### フローチャート

```mermaid
flowchart TD
    A[認可リクエスト] --> B[raw()メソッド呼び出し]
    B --> C[ユーザー解決]
    C --> D{beforeコールバック}
    D -->|非null| E[結果をそのまま返却]
    D -->|null| F{ポリシー存在?}
    F -->|Yes| G[ポリシーbefore実行]
    G --> H{before結果}
    H -->|非null| I[結果をそのまま返却]
    H -->|null| J[ポリシーメソッド実行]
    F -->|No| K{abilities定義?}
    K -->|Yes| L[アビリティコールバック実行]
    K -->|No| M[空コールバック実行]
    J --> N[afterコールバック実行]
    L --> N
    M --> N
    I --> N
    E --> N
    N --> O[GateEvaluatedイベント発火]
    O --> P{結果判定}
    P -->|true| Q[Response::allow()]
    P -->|false| R[defaultDenialResponse or Response::deny()]
    P -->|Response| S[そのまま返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | beforeコールバック優先 | beforeコールバックが非nullを返した場合、以降の判定をスキップ | before()登録時 |
| BR-02 | ポリシー優先解決 | 引数にモデルが含まれる場合、ポリシーを優先的に解決 | inspect()呼び出し時 |
| BR-03 | ゲスト許可判定 | ユーザーがnullの場合、コールバック/メソッドのシグネチャで許可判定 | canBeCalledWithUser() |
| BR-04 | ポリシー自動発見 | モデルクラス名からポリシークラス名を推測 | getPolicyFor() |
| BR-05 | アビリティメソッド変換 | ハイフン区切りをキャメルケースに変換 | formatAbilityToMethod() |

### 計算ロジック

- ポリシー名推測: `{ModelName}` → `{Namespace}\Policies\{ModelName}Policy`

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

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

本機能は直接的なデータベース操作を行わない。ポリシー内でのデータベースアクセスは各ポリシーの責務である。

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | Gate自体はDBアクセスなし |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | AuthorizationException | authorize()で認可失敗 | 403レスポンス返却 |
| - | InvalidArgumentException | define()に不正なコールバック | callable/配列/文字列を指定 |

### リトライ仕様

認可処理にリトライ機能はない。

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

本機能はトランザクションを使用しない。

## パフォーマンス要件

- ポリシーインスタンスはコンテナでキャッシュされる
- 同一リクエスト内での重複判定はキャッシュを推奨

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

- ゲストユーザー（null）の場合、明示的に許可されていないとアクセス拒否
- ポリシーのbeforeメソッドで管理者を一括許可可能
- AuthorizationExceptionには詳細な拒否理由を含めない（情報漏洩防止）

## 備考

- ポリシーは`#[UsePolicy]`アトリビュートでも指定可能
- guessPolicyNamesUsing()でポリシー名推測ロジックをカスタマイズ可能
- defaultDenialResponse()でデフォルトの拒否レスポンスを設定可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GateContract.php | `src/Illuminate/Contracts/Auth/Access/Gate.php` | Gateインターフェースの定義 |
| 1-2 | Response.php | `src/Illuminate/Auth/Access/Response.php` | 認可レスポンスの構造 |
| 1-3 | AuthorizationException.php | `src/Illuminate/Auth/Access/AuthorizationException.php` | 認可失敗例外 |

**読解のコツ**: Gateの基本操作（allows, denies, check, authorize）を先に理解すること。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AuthServiceProvider.php | `src/Illuminate/Auth/AuthServiceProvider.php` | Gateサービスの登録 |

**主要処理フロー**:
1. **57-61行目**: registerAccessGate()でGateをシングルトン登録
2. **59-60行目**: userResolverとしてAuthManagerから取得

#### Step 3: Gateクラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Gate.php | `src/Illuminate/Auth/Access/Gate.php` | 認可ロジックの中心クラス |

**主要処理フロー**:
- **99-115行目**: コンストラクタでabilities、policies、コールバック初期化
- **203-222行目**: define()でアビリティを定義
- **291-297行目**: policy()でポリシーを登録
- **305-310行目**: before()でbeforeコールバック登録
- **356-361行目**: check()で認可判定（複数アビリティ対応）
- **396-399行目**: authorize()で認可判定（失敗時例外）
- **408-423行目**: inspect()でResponseオブジェクト取得
- **434-459行目**: raw()で実際の認可判定ロジック実行
- **549-554行目**: callAuthCallback()でコールバック実行
- **627-651行目**: resolveAuthCallback()でコールバック解決
- **659-690行目**: getPolicyFor()でポリシー取得
- **774-799行目**: resolvePolicyCallback()でポリシーコールバック生成
- **865-876行目**: forUser()で特定ユーザー用Gate生成

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

```
Gate Facade / $user->can()
    │
    ├─ Gate::allows($ability, $arguments)
    │      └─ check($ability, $arguments)
    │             └─ inspect($ability, $arguments)
    │                    └─ raw($ability, $arguments)
    │                           │
    │                           ├─ callBeforeCallbacks()
    │                           │      └─ $before($user, $ability, $arguments)
    │                           │
    │                           ├─ callAuthCallback()
    │                           │      ├─ resolveAuthCallback()
    │                           │      │      ├─ getPolicyFor($arguments[0])
    │                           │      │      │      ├─ policies[$class]
    │                           │      │      │      ├─ getPolicyFromAttribute()
    │                           │      │      │      └─ guessPolicyName()
    │                           │      │      └─ resolvePolicyCallback()
    │                           │      │             ├─ callPolicyBefore()
    │                           │      │             └─ callPolicyMethod()
    │                           │      └─ abilities[$ability]
    │                           │
    │                           └─ callAfterCallbacks()
    │                                  └─ $after($user, $ability, $result, $arguments)
    │
    └─ Gate::authorize($ability, $arguments)
           └─ inspect().authorize()
                  └─ AuthorizationException [on deny]
```

### データフロー図

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

ability名 ────────────▶ Gate::raw() ──────────────────▶ bool/Response
arguments                  │
                          │
                    resolveUser()
                          │
                          ▼
                    beforeCallbacks
                          │
                          ▼
                    Policy or Ability
                          │
                          ├── Policy::before()
                          ├── Policy::$method()
                          └── abilities[$ability]()
                          │
                          ▼
                    afterCallbacks
                          │
                          ▼
                    GateEvaluated Event ────────────▶ Event Dispatcher
                          │
                          ▼
                    Response::allow/deny() ─────────▶ HTTPレスポンス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Gate.php | `src/Illuminate/Auth/Access/Gate.php` | ソース | 認可ロジックの中心クラス |
| Response.php | `src/Illuminate/Auth/Access/Response.php` | ソース | 認可レスポンス |
| AuthorizationException.php | `src/Illuminate/Auth/Access/AuthorizationException.php` | ソース | 認可失敗例外 |
| HandlesAuthorization.php | `src/Illuminate/Auth/Access/HandlesAuthorization.php` | ソース | allow/denyヘルパートレイト |
| GateEvaluated.php | `src/Illuminate/Auth/Access/Events/GateEvaluated.php` | ソース | 認可評価イベント |
| UsePolicy.php | `src/Illuminate/Database/Eloquent/Attributes/UsePolicy.php` | ソース | ポリシー指定アトリビュート |
| Authorize.php | `src/Illuminate/Auth/Middleware/Authorize.php` | ソース | 認可ミドルウェア |
