# 通知設計書 15-指紋認証失敗通知

## 概要

本ドキュメントは、ユーザーが生体認証（指紋認証/Face ID）によるログインに失敗した際に表示されるアプリ内エラー通知の設計を定義する。

### 本通知の処理概要

サインイン画面において、ユーザーが指紋認証アイコンをタップして生体認証を試みた際、認証に失敗した場合にエラーをリアルタイムでフィードバックするアプリ内オーバーレイ通知機能である。

**業務上の目的・背景**：生体認証は従来のパスワード入力に比べて利便性が高く、多くのユーザーに利用される認証方式である。しかし、指紋の読み取り失敗、Face IDの認識失敗、デバイスが生体認証をサポートしていない場合など、認証が失敗するケースがある。これらの場合に適切なエラーフィードバックを提供することで、ユーザーは代替手段（パスワード入力）での認証を選択できる。

**通知の送信タイミング**：生体認証API（LocalAuthentication）の認証結果がfalseまたはデバイスが生体認証をサポートしていない場合に、即座に通知が表示される。具体的には`startAuthentication`メソッド内の`didAuthenticate=false`時または`auth.isDeviceSupported()=false`時に表示される。

**通知の受信者**：生体認証を試みたユーザー本人のみ。デバイス上で即座に表示されるローカル通知。

**通知内容の概要**：赤色背景のエラー通知で、「認証に失敗しました」（StringConstants.authenticationFailed）というメッセージを表示する。

**期待されるアクション**：ユーザーは認証失敗を認識し、再度指紋認証を試みるか、メールアドレスとパスワードによる従来のログイン方式を選択する。

## 通知種別

アプリ内通知（オーバーレイ通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（認証API応答後即時表示） |
| 優先度 | 高 |
| リトライ | 無（表示は1回のみ） |

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

生体認証を試みたユーザーのデバイス画面に直接表示される。

## 通知テンプレート

### アプリ内通知の場合

| 項目 | 内容 |
|-----|------|
| 表示位置 | 画面上部オーバーレイ |
| 表示時間 | 約3秒（自動消去） |
| 背景色 | 赤色（Colors.red） |

### 本文テンプレート

```
タイトル: Failed
メッセージ: 認証に失敗しました（StringConstants.authenticationFailed）
アイコン: cancel_outlined（白色）
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| authenticationFailed | 認証失敗メッセージ | StringConstants.authenticationFailed | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | 指紋認証アイコンタップ | didAuthenticate=false | 生体認証に失敗 |
| 画面操作 | 指紋認証アイコンタップ | isDeviceSupported=false | デバイスが生体認証非対応 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 認証成功 | didAuthenticate=trueの場合 |
| 指紋認証未登録 | getFingerPrintUserが空の場合はアイコン非表示 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[指紋認証アイコンタップ] --> B[startAuthentication呼び出し]
    B --> C[auth.isDeviceSupported]
    C -->|false| D[errorNotification表示]
    C -->|true| E[auth.authenticate実行]
    E --> F{認証結果}
    F -->|didAuthenticate=false| G[errorNotification表示]
    F -->|didAuthenticate=true| H[ログイン処理へ]
    D --> I[通知自動消去]
    G --> I
    I --> J[サインイン画面に留まる]
```

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

### 参照テーブル一覧

該当なし（生体認証はデバイスローカルで処理）

### ローカルストレージ参照

| キー | 用途 | 取得条件 |
|-----|------|---------|
| fingerPrintUser | 登録済みユーザーのメールアドレス | 指紋認証でログインする際のユーザー特定 |
| fingerPrintPassword | 登録済みユーザーのパスワード | 指紋認証成功時のAPI認証に使用 |

### 更新テーブル一覧

該当なし（認証失敗時はデータ更新なし）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 認証失敗 | 指紋/顔認証に失敗 | エラー通知表示、再試行または代替認証を促す |
| デバイス非対応 | 生体認証ハードウェアなし | エラー通知表示、パスワード認証を促す |
| 認証キャンセル | ユーザーが認証をキャンセル | エラー通知は表示されない（例外処理） |
| 認証ロックアウト | 複数回失敗でロック | デバイスOS側でハンドリング |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0回（自動リトライなし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | OSレベルで制御（連続失敗でロックアウト） |
| 1日あたり上限 | OSレベルで制御 |

### 配信時間帯

制限なし（ユーザー操作に応じて即時表示）

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

- 生体認証データはデバイスのSecure Enclave/TrustZoneで管理され、アプリからはアクセス不可
- 認証失敗回数が一定を超えるとOSレベルでロックアウトされる
- local_authパッケージを使用し、Flutter標準の生体認証APIを利用
- biometricOnly: trueを設定し、デバイスPINでの代替認証を無効化

## 備考

- local_authパッケージ（LocalAuthentication）を使用して生体認証を実装
- 指紋認証は事前にappStoragePref.setFingerPrintUserでユーザー情報を登録している必要がある
- 認証成功時は保存されたメールアドレス・パスワードを使用してAPI認証を実行
- iOS/AndroidのOS標準の生体認証ダイアログが表示される
- 例外発生時はcatch節でエラーログを出力（デバッグ用）

---

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

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

### 推奨読解順序

#### Step 1: 生体認証の初期化を理解する

まず、生体認証ライブラリの初期化と使用方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | sign_in_screen.dart | `lib/screens/sign_in/view/sign_in_screen.dart` | LocalAuthenticationインスタンスの初期化（行327）を確認 |

**読解のコツ**: `final LocalAuthentication auth = LocalAuthentication();`でlocal_authパッケージのインスタンスを作成している。

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

処理の起点となる指紋認証アイコンタップ処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | sign_in_screen.dart | `lib/screens/sign_in/view/sign_in_screen.dart` | 指紋認証アイコンのonTap処理（行264-266）を確認 |
| 2-2 | sign_in_screen.dart | `lib/screens/sign_in/view/sign_in_screen.dart` | startAuthenticationメソッド（行386-429）を確認 |

**主要処理フロー**:
1. **行255-268**: 指紋認証アイコン表示条件（getFingerPrintUserが空でない場合）
2. **行264-266**: onTapでstartAuthentication(false)呼び出し
3. **行387**: auth.isDeviceSupported()でデバイス対応確認
4. **行390-393**: auth.authenticate()で認証実行
5. **行413-418**: didAuthenticate=false時のerrorNotification呼び出し
6. **行424-426**: isDeviceSupported=false時のerrorNotification呼び出し

#### Step 3: 通知表示層を理解する

通知の実際の表示処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show_message.dart | `lib/widgets/show_message.dart` | errorNotificationメソッドの実装を確認 |

**主要処理フロー**:
- **行38-56**: errorNotificationメソッドの実装

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

```
SignInScreen (sign_in_screen.dart)
    │
    ├─ LottieBuilder.asset (指紋認証アイコン) (行258-262)
    │      │
    │      └─ onTap (行264-266)
    │             │
    │             └─ startAuthentication(false)
    │
    └─ startAuthentication (行386-429)
           │
           ├─ auth.isDeviceSupported() (行387)
           │      │
           │      └─ false → ShowMessage.errorNotification (行425)
           │
           └─ auth.authenticate() (行390-393)
                  │
                  ├─ didAuthenticate=true → ログイン処理
                  │
                  └─ didAuthenticate=false → ShowMessage.errorNotification (行415)
```

### データフロー図

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

指紋認証           startAuthentication            認証結果
アイコン      ───▶  メソッド呼び出し     ───▶    (true/false)
タップ                   │                         │
                        ▼                         ▼
                auth.isDeviceSupported        条件分岐
                        │                         │
                        ▼                         ▼
                  auth.authenticate        ShowMessage
                        │               .errorNotification
                        ▼                    (失敗時)
                  LocalAuthentication              │
                   (OS生体認証)                    ▼
                                          オーバーレイ通知表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| sign_in_screen.dart | `lib/screens/sign_in/view/sign_in_screen.dart` | ソース | サインイン画面UI、生体認証処理 |
| show_message.dart | `lib/widgets/show_message.dart` | ソース | 通知表示ウィジェット |
| string_constants.dart | `lib/utils/string_constants.dart` | ソース | 文字列定数（authenticationFailed） |
| app_storage_pref.dart | `lib/utils/app_storage_pref.dart` | ソース | ローカルストレージ管理（指紋ユーザー情報） |
| pubspec.yaml | `pubspec.yaml` | 設定 | local_authパッケージ依存関係 |
