# 画面設計書 3-403 Forbidden

## 概要

本ドキュメントは、Laravel フレームワークにおける HTTP 403 Forbidden エラー画面の設計書です。認可（Authorization）に失敗した場合、つまりユーザーが特定のリソースへのアクセス権限を持っていない場合に表示されるエラー画面について記載しています。

### 本画面の処理概要

HTTP 403 Forbidden エラー画面は、認証済みのユーザーが、アクセス権限のないリソースにアクセスしようとした場合に表示される画面です。この画面は、ユーザーに対してアクセスが禁止されていることを明確に伝え、適切な対応を促す役割を果たします。

**業務上の目的・背景**：Web アプリケーションにおいて、ロールベースのアクセス制御（RBAC）やポリシーベースのアクセス制御を実装する際、権限のないユーザーからのアクセスを拒否し、その理由を明確に伝えるために本画面が必要です。管理者専用ページへの一般ユーザーのアクセス、他のユーザーのプライベートリソースへのアクセス試行など、認可チェックに失敗した場合に表示されます。セキュリティ上、権限のないユーザーにはコンテンツを表示せず、代わりにこのエラー画面を表示することで、アプリケーションのセキュリティと整合性を維持します。

**画面へのアクセス方法**：この画面は直接アクセスするものではなく、以下のような状況で自動的に表示されます。
1. Gate（認可ゲート）チェックに失敗した場合
2. Policy（ポリシー）による認可チェックに失敗した場合
3. AuthorizationException がスローされた場合
4. ミドルウェアでの権限チェックに失敗した場合

**主要な操作・処理内容**：
1. エラーコード「403」とメッセージ「Forbidden」を画面中央に表示
2. 例外オブジェクトにカスタムメッセージが含まれている場合は、そのメッセージを表示
3. ダークモード対応のスタイリングにより、ユーザーの表示設定に応じた適切な配色で表示
4. レスポンシブデザインにより、デスクトップ・モバイル両方のデバイスで適切に表示

**画面遷移**：
- 遷移元：アクセス権限のない任意の画面へのアクセス試行
- 遷移先：なし（エラー表示のみ。ただし、アプリケーション側でカスタマイズして適切な遷移先リンクを追加可能）

**権限による表示制御**：この画面は認可チェックに失敗したユーザーにのみ表示されます。適切な権限を持つユーザーには、リクエストしたリソースが正常に表示されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | アクセスゲート（Gate） | 主機能 | アクセス禁止エラー発生時の認可チェック失敗表示 |
| 36 | ビューファクトリ | 補助機能 | Blade テンプレートのレンダリング処理 |

## 画面種別

エラー表示画面

## URL/ルーティング

この画面は特定の URL を持ちません。HTTP レスポンスステータスコード 403 が返される際に、例外ハンドラ（`Illuminate\Foundation\Exceptions\Handler`）により自動的にレンダリングされます。

## 入出力項目

### 入力項目

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| なし | - | - | この画面は入力項目を持ちません |

### 出力項目（テンプレート変数）

| 項目名 | 型 | 説明 |
|--------|------|------|
| $exception | HttpExceptionInterface | 発生した例外オブジェクト |
| $errors | ViewErrorBag | バリデーションエラーバッグ（空） |

## 表示項目

| 項目 | 表示内容 | スタイル |
|------|----------|----------|
| エラーコード | 403 | 大きなフォント、右ボーダー付き |
| エラーメッセージ | Forbidden（または例外のカスタムメッセージ） | 大文字、トラッキング広め |

## イベント仕様

### 1-画面表示

本画面は静的なエラー表示のみを行い、ユーザーインタラクションのイベントは定義されていません。ブラウザの「戻る」ボタンまたは直接 URL 入力により他の画面へ遷移します。

## データベース更新仕様

本画面はデータベースへの読み書きを行いません。

## メッセージ仕様

| メッセージ種別 | メッセージコード | メッセージ内容 | 表示条件 |
|--------------|----------------|--------------|----------|
| エラー | - | Forbidden | 例外にカスタムメッセージがない場合 |
| エラー | - | （例外のカスタムメッセージ） | 例外にカスタムメッセージがある場合 |

**多言語対応**：メッセージは `__($exception->getMessage() ?: 'Forbidden')` ヘルパー関数を使用しており、言語ファイルにより翻訳可能です。

**カスタムメッセージ機能**：他のエラー画面と異なり、403 画面は `$exception->getMessage()` を使用してカスタムメッセージを表示できます。これにより、「この操作を行う権限がありません」などの具体的なメッセージを表示できます。

## 例外処理

本画面自体が例外処理の結果として表示されるため、画面内での例外処理は定義されていません。テンプレートのレンダリングに失敗した場合は、Symfony の HtmlErrorRenderer によるフォールバック表示が行われます。

## 備考

- この画面は `minimal.blade.php` レイアウトを継承しています
- **他のエラー画面との違い**：403 画面は例外オブジェクトのメッセージを動的に取得して表示します（`$exception->getMessage() ?: 'Forbidden'`）
- カスタマイズする場合は、`resources/views/errors/403.blade.php` にファイルを配置することで上書き可能です
- ダークモード対応のスタイリングが含まれています（`prefers-color-scheme: dark` メディアクエリ使用）

---

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

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

### 推奨読解順序

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

例外処理の流れで渡されるデータ構造を理解することが重要です。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | HttpException.php | `vendor/symfony/http-kernel/Exception/HttpException.php` | ステータスコード、ヘッダー、メッセージを保持する例外クラスの構造 |
| 1-2 | AccessDeniedHttpException.php | `vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php` | 403 専用の例外クラス |
| 1-3 | AuthorizationException.php | `src/Illuminate/Auth/Access/AuthorizationException.php` | Laravel の認可例外クラス |

**読解のコツ**: 403 エラーは AuthorizationException から AccessDeniedHttpException に変換されて処理されます。この変換は Handler クラスで行われます。

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

例外発生からビュー表示までの流れを理解します。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Handler.php | `src/Illuminate/Foundation/Exceptions/Handler.php` | 例外ハンドラのメインクラス |

**主要処理フロー**:
1. **行 920-938**: `renderHttpException()` メソッドで HTTP 例外のレンダリングを実行
2. **行 922**: `registerErrorViewPaths()` でエラービューのパスを登録
3. **行 924-930**: `getHttpExceptionView()` で適切なビューを取得し、`response()->view()` でレンダリング
4. **行 958-968**: `getHttpExceptionView()` でステータスコードに基づくビュー名を決定

#### Step 3: ビューパス登録を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | RegisterErrorViewPaths.php | `src/Illuminate/Foundation/Exceptions/RegisterErrorViewPaths.php` | エラービューの名前空間登録処理 |

**主要処理フロー**:
- **行 15-22**: `__invoke()` メソッドで `errors` 名前空間にビューパスを登録

#### Step 4: テンプレート継承を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | 403.blade.php | `src/Illuminate/Foundation/Exceptions/views/403.blade.php` | 403 エラー専用テンプレート |
| 4-2 | minimal.blade.php | `src/Illuminate/Foundation/Exceptions/views/minimal.blade.php` | 共通レイアウトテンプレート |

**主要処理フロー**:
- **403.blade.php 行 1**: `@extends('errors::minimal')` で共通レイアウトを継承
- **403.blade.php 行 3-5**: `@section` でタイトル、コード、メッセージを定義
- **403.blade.php 行 5**: `$exception->getMessage() ?: 'Forbidden'` で動的メッセージ取得
- **minimal.blade.php 行 24, 28**: `@yield('code')` と `@yield('message')` で子テンプレートの内容を表示

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

```
AuthorizationException 発生
    │
    ├─ Handler::render()
    │      │
    │      └─ Handler::prepareResponse()
    │             │
    │             └─ Handler::renderHttpException()
    │                    │
    │                    ├─ Handler::registerErrorViewPaths()
    │                    │      └─ RegisterErrorViewPaths::__invoke()
    │                    │
    │                    └─ Handler::getHttpExceptionView()
    │                           └─ view()->exists('errors::403')
    │
    └─ response()->view('errors::403', [...])
           └─ 403.blade.php
                  │
                  ├─ $exception->getMessage()
                  │
                  └─ minimal.blade.php（継承）
```

### データフロー図

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

AuthorizationException ─▶ Handler                   ───▶ HTTP Response
        │                     │                              (status: 403)
        │                     ├─ exceptionMap で変換
        │                     │      └─ AccessDeniedHttpException
        ▼                     │
カスタムメッセージ        ├─ registerErrorViewPaths()
(getMessage())                │
        │                     ├─ getHttpExceptionView()
        │                     │      └─ 'errors::403' 決定
        ▼                     │
 403.blade.php ◀─────── response()->view()
        │
        ├─ $exception->getMessage() ?: 'Forbidden'
        │
        └─ minimal.blade.php
             └─ HTML 構造 + CSS
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 403.blade.php | `src/Illuminate/Foundation/Exceptions/views/403.blade.php` | テンプレート | 403 エラー専用のコンテンツ定義（カスタムメッセージ対応） |
| minimal.blade.php | `src/Illuminate/Foundation/Exceptions/views/minimal.blade.php` | テンプレート | エラー画面の共通レイアウト |
| Handler.php | `src/Illuminate/Foundation/Exceptions/Handler.php` | ソース | 例外ハンドリングとビュー選択のロジック |
| RegisterErrorViewPaths.php | `src/Illuminate/Foundation/Exceptions/RegisterErrorViewPaths.php` | ソース | エラービューパスの登録処理 |
| AuthorizationException.php | `src/Illuminate/Auth/Access/AuthorizationException.php` | ソース | 認可失敗時の例外クラス |
| Gate.php | `src/Illuminate/Auth/Access/Gate.php` | ソース | 認可ゲートの実装 |
