# 画面設計書 53-HCaptcha画面

## 概要

本ドキュメントはWikipedia iOSアプリにおける「HCaptcha画面」（CAPTCHA認証画面）の設計仕様を定義するものです。

### 本画面の処理概要

**業務上の目的・背景**：
本画面は、アカウント作成やログイン時にボット（自動プログラム）による不正アクセスを防止するためのCAPTCHA認証を提供します。hCaptchaは、従来のreCAPTCHAに代わるプライバシー重視のCAPTCHAソリューションであり、Wikipediaでは特定の条件下（大量のアカウント作成試行、不審なログイン活動など）でユーザーに対してチャレンジを要求します。本画面はWebView内にhCaptchaチャレンジを表示し、ユーザーが人間であることを確認した後、認証トークンを取得して認証フローを継続します。

**画面へのアクセス方法**：
本画面へは以下のルートでアクセスします：
1. アカウント作成処理中にサーバーからCAPTCHA要求を受け取った場合
2. ログイン処理中にサーバーからCAPTCHA要求を受け取った場合
3. 編集保存時にCAPTCHA要求を受け取った場合

**主要な操作・処理内容**：
1. hCaptchaチャレンジの表示 - WebView内にhCaptchaウィジェットを表示
2. ユーザーによるチャレンジ完了 - 画像選択等のチャレンジタスクを実行
3. トークン取得 - チャレンジ成功後に認証トークンを取得
4. 結果のコールバック - successActionまたはerrorActionで呼び出し元に結果を返す

**画面遷移**：
- 遷移元：AccountCreation画面、ログイン処理、編集保存処理
- 遷移先：なし（モーダル表示、トークン取得後は自動的に呼び出し元の処理を継続）

**権限による表示制御**：
本画面は認証フロー中にサーバーがCAPTCHA要求を返した場合にのみ表示されます。表示の有無はサーバー側で判定されます。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 43 | 認証管理 | 補助機能 | CAPTCHA認証によるボット対策 |

## 画面種別

認証・確認（CAPTCHA認証画面）

## URL/ルーティング

本画面はモーダルで表示されるため、URLルーティングは使用しません。
- ViewController: WMFHCaptchaViewController
- hCaptcha関連URL: WMFDeveloperSettingsDataControllerの設定から取得

## 入出力項目

| 項目名 | 項目ID | 入出力 | データ型 | 必須 | 最大長 | バリデーション | 備考 |
|--------|--------|--------|----------|------|--------|----------------|------|
| hCaptcha設定 | featureConfig.hCaptcha | 入力（内部） | HCaptchaConfig | 必須 | - | URL形式確認 | WMFDeveloperSettingsDataControllerから取得 |
| 認証トークン | token | 出力 | String | - | - | - | チャレンジ成功時にsuccessActionで返却 |
| エラー | error | 出力 | Error | - | - | - | 失敗時にerrorActionで返却 |

## 表示項目

| 項目名 | 表示内容 | データソース |
|--------|----------|--------------|
| スピナー | ローディングインジケータ | UIActivityIndicatorView |
| CAPTCHAコンテナ | hCaptchaチャレンジ | WebView内のhCaptchaウィジェット |
| 背景 | 半透明黒オーバーレイ | UIColor.black.withAlphaComponent(0.5) |

## イベント仕様

### 1-hCaptcha初期化（viewDidAppear）

**トリガー**: 画面表示完了時

**処理フロー**:
1. WMFDeveloperSettingsDataControllerからhCaptcha設定を取得
2. 設定が存在しない場合、hCaptchaMissingConfigエラーでerrorAction呼び出し
3. 各URLの妥当性確認、不正な場合hCaptchaInvalidURLエラー
4. HCaptchaインスタンス生成（apiKey, baseURL, jsSrc等設定）
5. イベントハンドラ設定（challengeExpired, close, error, expired, open）
6. WebView設定（フレーム、背景透明化、captchaContainerへの追加）

### 2-CAPTCHA検証実行

**トリガー**: validate()メソッド呼び出し（外部から）

**処理フロー**:
1. hCaptcha.validate()をcaptchaContainer上で実行
2. チャレンジ完了を待機
3. 成功時：トークンをdematerialize()で取得、successAction(token)呼び出し
4. 失敗時：errorAction(error)呼び出し
5. WebViewをsuperviewから削除、nilに設定

### 3-hCaptchaイベントハンドリング

**トリガー**: hCaptchaウィジェットからのイベント

**処理フロー**:
- challengeExpired: hCaptchaExpiredエラーでerrorAction呼び出し
- close: hCaptchaClosedエラーでerrorAction呼び出し
- error: hCaptchaErrorエラーでerrorAction呼び出し
- expired: hCaptchaExpiredエラーでerrorAction呼び出し
- open: 処理なし（チャレンジ開始を示すだけ）

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | 本画面単体ではデータベース更新なし。取得したトークンは呼び出し元で使用 |

### テーブル別更新項目詳細

本画面はCAPTCHAトークンを取得するのみで、直接的なデータベース更新は行いません。

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|---------|
| - | エラー | hCaptchaMissingConfig | hCaptcha設定が取得できない場合 |
| - | エラー | hCaptchaInvalidURL | 設定URLが不正な場合 |
| - | エラー | hCaptchaExpired | チャレンジ有効期限切れ |
| - | エラー | hCaptchaClosed | ユーザーがチャレンジを閉じた場合 |
| - | エラー | hCaptchaError | hCaptcha内部エラー |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| 設定未取得 | hCaptchaMissingConfigエラーでerrorAction呼び出し、画面は表示状態のまま |
| URL不正 | hCaptchaInvalidURLエラーでerrorAction呼び出し |
| チャレンジ期限切れ | hCaptchaExpiredエラーでerrorAction呼び出し |
| ユーザーキャンセル | hCaptchaClosedエラーでerrorAction呼び出し |
| hCaptchaエラー | hCaptchaErrorエラーまたはHCaptchaErrorでerrorAction呼び出し |
| HCaptcha初期化失敗 | 初期化時のcatch句でerrorAction呼び出し |

## 備考

- hCaptchaライブラリ（サードパーティ）を使用
- WebView（WKWebView）内でhCaptchaチャレンジを表示
- ThemeableViewControllerを継承し、ダークモード対応（hCaptchaのthemeパラメータも連動）
- 背景は半透明黒（alpha 0.5）でモーダル感を演出
- validate()は外部から呼び出す必要があり、viewDidAppearでは自動実行されない
- スピナーは初期化完了まで表示、validate完了後に非表示
- CustomError enumで独自エラー型を定義（hCaptchaInvalidURL, hCaptchaExpired, hCaptchaClosed, hCaptchaError, hCaptchaMissingConfig）

---

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

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

### 推奨読解順序

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

hCaptcha設定とエラー型の定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WMFHCaptchaViewController.swift | `Wikipedia/Code/WMFHCaptchaViewController.swift` | CustomError enum（9-15行目）- 独自エラー型定義 |
| 1-2 | WMFDeveloperSettingsDataController | `WMF Framework/` | hCaptcha設定構造体（apiKey, baseURL, jsSrc等） |

**読解のコツ**: hCaptcha設定はWMFDeveloperSettingsDataController.shared.loadFeatureConfig()?.ios.hCaptchaで取得します。

#### Step 2: UIレイアウトを理解する

画面のレイアウト構成とUI要素を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WMFHCaptchaViewController.swift | `Wikipedia/Code/WMFHCaptchaViewController.swift` | captchaContainer, spinner定義（17-30行目）、setupLayout()（54-66行目） |

**主要処理フロー**:
1. **17-22行目**: captchaContainerの定義（UIView、AutoLayout対応）
2. **24-30行目**: spinnerの定義（UIActivityIndicatorView、中央配置）
3. **54-66行目**: AutoLayoutによるレイアウト設定

#### Step 3: hCaptcha初期化処理を理解する

hCaptchaインスタンスの生成と設定を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | WMFHCaptchaViewController.swift | `Wikipedia/Code/WMFHCaptchaViewController.swift` | setupHCaptcha()（90-147行目） |

**主要処理フロー**:
- **92-95行目**: 設定取得とnil確認
- **97-105行目**: URL妥当性確認
- **107-115行目**: HCaptchaインスタンス生成（各種パラメータ設定）
- **122-136行目**: イベントハンドラ設定
- **138-146行目**: WebView設定とcaptchaContainerへの追加

#### Step 4: 検証処理を理解する

CAPTCHAチャレンジの実行と結果処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | WMFHCaptchaViewController.swift | `Wikipedia/Code/WMFHCaptchaViewController.swift` | validate()（68-87行目） |

**主要処理フロー**:
- **70行目**: hCaptcha.validate()呼び出し
- **76行目**: dematerialize()でトークン取得
- **77行目**: successAction?(token)でコールバック
- **78-81行目**: エラー時のerrorAction呼び出し
- **84-85行目**: WebViewのクリーンアップ

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

```
WMFHCaptchaViewController
    │
    ├─ viewDidLoad() [40行目]
    │      ├─ setupLayout() [54行目]
    │      │      └─ AutoLayoutによるUI配置
    │      │
    │      ├─ spinner.startAnimating() [44行目]
    │      │
    │      └─ apply(theme:) [45行目]
    │
    ├─ viewDidAppear() [48行目]
    │      └─ setupHCaptcha() [90行目]
    │             ├─ WMFDeveloperSettingsDataController.shared.loadFeatureConfig()
    │             │
    │             ├─ HCaptcha初期化 [107行目]
    │             │      └─ apiKey, baseURL, jsSrc, theme等設定
    │             │
    │             ├─ hCaptcha.onEvent [122行目]
    │             │      └─ イベントハンドラ設定
    │             │
    │             └─ hCaptcha.configureWebView [138行目]
    │                    └─ WebView設定とコンテナへの追加
    │
    └─ validate() [68行目] ※外部から呼び出し
           └─ hCaptcha.validate() [70行目]
                  │
                  ├─ 成功時: successAction?(token) [77行目]
                  │
                  └─ 失敗時: errorAction?(error) [79-81行目]
```

### データフロー図

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

WMFDeveloperSettings ──▶ setupHCaptcha() ──▶ HCaptcha初期化
    DataController              │
                                ▼
                        WebView内にチャレンジ表示
                                │
                        [ユーザー操作]
                                │
                                ▼
                         validate() ──┬──▶ 成功: successAction(token)
                                      │         │
                                      │         └──▶ 呼び出し元で
                                      │              認証処理継続
                                      │
                                      └──▶ 失敗: errorAction(error)
                                                │
                                                └──▶ 呼び出し元で
                                                     エラー処理
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WMFHCaptchaViewController.swift | `Wikipedia/Code/WMFHCaptchaViewController.swift` | ソース | メインViewController |
| ThemeableViewController.swift | `Wikipedia/Code/ThemeableViewController.swift` | ソース | 親クラス（テーマ対応） |
| WMFDeveloperSettingsDataController.swift | `WMF Framework/` | ソース | hCaptcha設定提供 |
| HCaptcha (External) | `Pods/HCaptcha/` | 外部ライブラリ | hCaptchaチャレンジ実行 |
