# 通知設計書 1-認証失敗通知

## 概要

本ドキュメントは、Decap CMSにおけるログイン時の認証失敗通知（トースト通知）の設計仕様を定義する。ユーザーが認証情報を入力してログインを試みた際に認証が失敗した場合、画面右上にエラートースト通知を表示してユーザーに失敗を伝える仕組みの詳細を記載する。

### 本通知の処理概要

本通知は、Decap CMSのログイン画面においてユーザーが認証操作を行い、バックエンドサービスでの認証処理が失敗した場合に発火するエラートースト通知である。Redux アクション `loginUser` 内のPromise catchブロックで `addNotification` が呼び出され、react-toastify を通じて画面上にエラーメッセージが表示される。

**業務上の目的・背景**：CMSへのアクセスを試みるユーザーに対して、認証が失敗した事実とその理由を即座にフィードバックすることで、正しい認証情報の再入力やパスワードリセットなどの次のアクションを促す。認証失敗の原因（不正なパスワード、アカウントロック等）をユーザーに伝えることで、サポートへの不要な問い合わせを削減する効果も期待される。

**通知の送信タイミング**：ユーザーがログイン画面で認証情報（credentials）を送信し、`backend.authenticate(credentials)` の呼び出しがPromise rejectされた時点で即座に通知が発行される。

**通知の受信者**：認証操作を行った当該ユーザー本人。ブラウザ画面上のトースト通知として表示されるため、操作中のユーザーのみが受信者となる。

**通知内容の概要**：i18nキー `ui.toast.onFailToAuth` に基づくメッセージが表示される。英語ロケールでは `%{details}` としてバックエンドから返されたエラーメッセージがそのまま表示される。

**期待されるアクション**：ユーザーは表示されたエラーメッセージを確認し、認証情報の再確認・再入力、パスワードリセット、または管理者への問い合わせを行うことが期待される。

## 通知種別

アプリ内通知（トースト通知）

react-toastify ライブラリを使用したブラウザ内トースト通知。画面右上（`top-right`）に `colored` テーマで表示される。

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Redux dispatch → react-toastify） |
| 優先度 | 高（認証エラーはユーザー操作の継続に直結） |
| リトライ | なし（UIトースト通知のため再送不要） |

### 送信先決定ロジック

認証操作を実行したユーザーのブラウザセッションに対して直接表示する。送信先の決定ロジックは不要で、Redux storeの `notifications` ステートに追加されたエントリが `Notifications` コンポーネントによってレンダリングされる。

## 通知テンプレート

### メール通知の場合

該当なし（本通知はアプリ内トースト通知のみ）

### 本文テンプレート

```
%{details}
```

i18nキー `ui.toast.onFailToAuth` のテンプレートは `%{details}` のみであり、バックエンドから返されたエラーオブジェクトの `message` プロパティがそのまま表示される。

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| details | 認証エラーの詳細メッセージ | `error.message`（backend.authenticate の reject 値） | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | ログインフォーム送信 | `backend.authenticate(credentials)` が reject された場合 | ユーザーがログインボタンを押下し、バックエンド認証が失敗した時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 認証成功時 | `backend.authenticate` が resolve した場合は通知を発行しない |
| 自動認証チェック（authenticateUser） | キャッシュトークンの検証失敗時は `authError` のみ発行し、トースト通知は表示しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ユーザーがログインフォーム送信] --> B[loginUser アクション発火]
    B --> C[dispatch authenticating]
    C --> D[backend.authenticate 呼び出し]
    D -->|成功| E[dispatch authenticate - ログイン完了]
    D -->|失敗| F[catch ブロック実行]
    F --> G[console.error でエラーログ出力]
    G --> H[dispatch addNotification - エラートースト表示]
    H --> I[dispatch authError - 認証失敗状態更新]
    I --> J[Notifications コンポーネントがトースト描画]
    J --> K[8秒後に自動消去]
    E --> L[終了]
    K --> L
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（本通知はクライアントサイドのRedux storeのみを使用し、データベースへのアクセスは行わない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 認証失敗 | バックエンドが認証を拒否 | エラートースト通知を表示し、`authError` アクションでRedux stateを更新 |
| ネットワークエラー | バックエンドへの接続が失敗 | 同上（Promiseの reject がキャッチされ同じフローで処理） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし（ユーザーが手動で再ログインを試行する想定） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（UI通知のため制限なし） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（ユーザーがログイン操作を行ったタイミングで即座に表示）

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

- エラーメッセージ（`error.message`）がそのまま画面に表示されるため、バックエンド側でセンシティブな情報（内部システム情報、スタックトレース等）を含めないよう注意が必要
- 認証失敗の詳細情報がクライアント側のコンソール（`console.error`）にも出力される

## 備考

- `authenticateUser` 関数（キャッシュトークンの自動検証）での失敗時にはトースト通知は表示されず、`authError` と `logoutUser` のみが実行される（`auth.ts` 72-75行目）
- `logoutUser` 実行時は `clearNotifications` が呼ばれ、既存の全通知がクリアされる（`auth.ts` 116行目）

---

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

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

### 推奨読解順序

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

通知システムで使用されるデータ構造（NotificationPayload、Notification型）を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notifications.ts (actions) | `packages/decap-cms-core/src/actions/notifications.ts` | `NotificationPayload` インターフェース（8-12行目）で通知データの構造を理解する。`message`, `dismissAfter`, `type` の3つのフィールドが基本構造。 |
| 1-2 | notifications.ts (reducers) | `packages/decap-cms-core/src/reducers/notifications.ts` | `Notification` 型（17-22行目）でRedux storeに保持される通知オブジェクトの形状を理解する。`id`（UUID）が追加される点に注目。 |

**読解のコツ**: `NotificationMessage` インターフェースの `key` フィールドがi18nロケールキーに対応し、`details` が動的パラメータとしてテンプレートに埋め込まれる。

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

認証フローの起点となる `loginUser` 関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | auth.ts | `packages/decap-cms-core/src/actions/auth.ts` | `loginUser` 関数（79-108行目）がログイン処理のエントリーポイント。Redux ThunkActionとして定義されている。 |

**主要処理フロー**:
1. **84行目**: `dispatch(authenticating())` - 認証開始状態をReduxに通知
2. **85-86行目**: `backend.authenticate(credentials)` - バックエンドへ認証リクエスト
3. **93-106行目**: `.catch` ブロック - 認証失敗時のエラー処理
4. **96-104行目**: `dispatch(addNotification({...}))` - エラートースト通知の発行
5. **105行目**: `dispatch(authError(error))` - 認証失敗状態の更新

#### Step 3: 通知アクション層を理解する

`addNotification` アクションの内部処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | notifications.ts (actions) | `packages/decap-cms-core/src/actions/notifications.ts` | `addNotification` 関数（18-19行目）が `NOTIFICATION_SEND` アクションを発行する。payloadとして `NotificationPayload` がそのまま渡される。 |

**主要処理フロー**:
- **18-19行目**: `NOTIFICATION_SEND` タイプのReduxアクションオブジェクトを生成

#### Step 4: リデューサー層を理解する

Reduxリデューサーが通知をstoreに追加する処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | notifications.ts (reducers) | `packages/decap-cms-core/src/reducers/notifications.ts` | `NOTIFICATION_SEND` ケース（40-47行目）で通知オブジェクトに `uuid()` で一意IDが付与され、`notifications` 配列に追加される。 |

#### Step 5: UIレンダリング層を理解する

Redux storeの通知がブラウザ上にどう表示されるかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | Notifications.tsx | `packages/decap-cms-core/src/components/UI/Notifications.tsx` | `useEffect`（30-52行目）で新規通知を検知し、`toast()` でreact-toastifyのトーストを生成。i18nキーを `t()` 関数で翻訳して表示（37行目）。`dismissAfter` 経過後に `dismissNotification` を呼び出す。 |

#### Step 6: i18nメッセージテンプレートを理解する

表示されるメッセージの内容を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | index.js (en) | `packages/decap-cms-locales/src/en/index.js` | 282行目: `onFailToAuth: '%{details}'` - `details` 変数がそのまま表示されるテンプレート |

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

```
loginUser (actions/auth.ts:79)
    |
    +-- dispatch(authenticating()) (auth.ts:84)
    |
    +-- backend.authenticate(credentials) (auth.ts:85-86)
    |       |
    |       +-- [成功時] dispatch(authenticate(user)) (auth.ts:91)
    |       |
    |       +-- [失敗時] .catch ブロック (auth.ts:93)
    |               |
    |               +-- console.error(error) (auth.ts:94)
    |               |
    |               +-- dispatch(addNotification({...})) (auth.ts:95-104)
    |               |       |
    |               |       +-- [Redux] NOTIFICATION_SEND アクション
    |               |       |       |
    |               |       |       +-- notifications reducer (reducers/notifications.ts:40-47)
    |               |       |               |
    |               |       |               +-- uuid() でID生成、notifications配列に追加
    |               |       |
    |               |       +-- [React] Notifications コンポーネント再描画
    |               |               |
    |               |               +-- toast() でトースト通知表示 (Notifications.tsx:34-42)
    |               |               |
    |               |               +-- 8000ms後 dismissNotification (Notifications.tsx:48-51)
    |               |
    |               +-- dispatch(authError(error)) (auth.ts:105)
```

### データフロー図

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

credentials        -->  backend.authenticate()     -->  [成功] User データ
(ユーザーID/PW)         (バックエンド認証)                [失敗] Error オブジェクト
                                                              |
                                                              v
Error.message      -->  addNotification()          -->  Redux store
                        (i18nキー: ui.toast.                 (notifications配列)
                         onFailToAuth)                        |
                                                              v
notifications      -->  Notifications コンポーネント -->  react-toastify
(Redux state)           (t() でi18n変換)                 トースト UI表示
                                                         (画面右上, 8秒で消去)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| auth.ts | `packages/decap-cms-core/src/actions/auth.ts` | ソース | 認証アクション。`loginUser` が認証失敗時にトースト通知を発行するエントリーポイント |
| notifications.ts (actions) | `packages/decap-cms-core/src/actions/notifications.ts` | ソース | 通知アクション作成関数。`addNotification` を定義 |
| notifications.ts (reducers) | `packages/decap-cms-core/src/reducers/notifications.ts` | ソース | 通知リデューサー。Redux storeの `notifications` 状態を管理 |
| Notifications.tsx | `packages/decap-cms-core/src/components/UI/Notifications.tsx` | ソース | 通知UIコンポーネント。react-toastifyを使用してトーストを画面描画 |
| index.js (en) | `packages/decap-cms-locales/src/en/index.js` | i18nリソース | 英語ロケール。`ui.toast.onFailToAuth` のメッセージテンプレートを定義 |
| index.js (ja) | `packages/decap-cms-locales/src/ja/index.js` | i18nリソース | 日本語ロケール。`ui.toast.onFailToAuth` の日本語メッセージテンプレートを定義 |
