# 機能設計書 179-バックアップコード

## 概要

本ドキュメントは、Chatwootにおける多要素認証（MFA）バックアップコード機能の設計仕様を定義する。この機能は、TOTPデバイスを紛失した場合の代替認証手段として使用できるバックアップコードを生成するAPIを提供する。

### 本機能の処理概要

**業務上の目的・背景**：
多要素認証（MFA）が有効な状態でTOTPデバイス（スマートフォン等）を紛失・故障した場合、ユーザーはアカウントにログインできなくなる。バックアップコードは、このような緊急時にアカウントへのアクセスを回復するための重要なセキュリティ機能である。各コードは1回限り使用可能で、使用後は無効化される。

**機能の利用シーン**：
- MFA有効化後、初めてバックアップコードを確認・保存する場合
- 既存のバックアップコードを使い切った、または紛失した場合に再生成する場合
- セキュリティ上の理由でバックアップコードをローテーションしたい場合

**主要な処理内容**：
1. MFA有効状態の確認
2. 現在のOTPコードによる認証
3. 新しいバックアップコードの生成
4. バックアップコードの保存と返却

**関連システム・外部連携**：
- TOTP: バックアップコード生成時の認証
- SecureRandom: 暗号学的に安全なコード生成

**権限による制御**：
認証済みでMFAが有効なユーザーのみがバックアップコードを生成可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 90 | MFA設定画面 | 主画面 | MFAバックアップコードの生成 |

## 機能種別

セキュリティ機能 / 認証リカバリー

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| otp_code | String | Yes | 6桁のTOTPコード | 有効なOTPコード |

### 入力データソース

- フロントエンド画面からのJSON形式リクエスト
- 認証トークンからのユーザー識別

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| backup_codes | Array | 生成されたバックアップコード（10個） |

### 出力先

- JSON形式でHTTPレスポンスとして返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ POST /api/v1/profile/mfa/backup_codes
2. 認証検証
   └─ current_userから対象ユーザーを特定
3. MFA有効確認
   └─ check_mfa_enabled（MFA無効ならエラー）
4. OTPコード検証
   └─ validate_otp（無効ならエラー）
5. バックアップコード生成
   └─ generate_backup_codes!
6. 保存
   └─ otp_backup_codesカラムに暗号化保存
7. レスポンス返却
   └─ 生成されたバックアップコードを返却
```

### フローチャート

```mermaid
flowchart TD
    A[POST /api/v1/profile/mfa/backup_codes] --> B{認証済み?}
    B -->|No| C[401 Unauthorized]
    B -->|Yes| D{MFA有効?}
    D -->|No| E[422 MFA not enabled]
    D -->|Yes| F{OTPコード有効?}
    F -->|No| G[422 Invalid code]
    F -->|Yes| H[バックアップコード生成]
    H --> I[暗号化して保存]
    I --> J[バックアップコード返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-179-01 | MFA必須 | MFAが有効でないとバックアップコードは生成不可 | 常時 |
| BR-179-02 | OTP認証必須 | バックアップコード生成には現在のOTPコードが必要 | 常時 |
| BR-179-03 | 10コード生成 | 常に10個のバックアップコードを生成 | 生成時 |
| BR-179-04 | 8文字16進数 | 各コードは8文字の16進数（SecureRandom.hex(4).upcase） | 生成時 |
| BR-179-05 | 既存コード上書き | 新しいコード生成時は既存のコードを全て置換 | 生成時 |
| BR-179-06 | 暗号化保存 | バックアップコードは暗号化して保存 | 保存時 |

### 計算ロジック

**バックアップコード生成**:
```ruby
Array.new(10) { SecureRandom.hex(4).upcase }
# 例: ["A1B2C3D4", "E5F6G7H8", ...]
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| バックアップコード生成 | users | UPDATE | otp_backup_codesカラムの更新 |

### テーブル別操作詳細

#### users

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | otp_backup_codes | 10個のコード配列（暗号化） | 既存コードを完全に置換 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 認証トークンが無効 | 再ログイン |
| 403 | Forbidden | MFA機能が無効 | システム管理者に連絡 |
| 422 | Unprocessable Entity | MFAが有効でない | MFAを有効化してから再試行 |
| 422 | Unprocessable Entity | OTPコードが無効 | 正しいコードを入力 |

### リトライ仕様

特になし（OTPコードの再入力で対応）

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

バックアップコードの生成と保存は単一のsave!呼び出しで実行される。

## パフォーマンス要件

- レスポンス時間: 300ms以内

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

- バックアップコードは暗号化して保存（encrypts :otp_backup_codes）
- 生成時にOTP認証が必須
- 各コードは1回限り使用可能（使用後は"XXXXXXXX"に置換）
- コード比較はタイミング攻撃対策済み（constant-time comparison）

## 備考

- バックアップコードは表示後、ユーザーが安全な場所に保存する必要がある
- 使用されたコードは"XXXXXXXX"に置換され、再利用不可
- 再生成すると既存のコードは全て無効化される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | user.rb | `app/models/user.rb` | otp_backup_codesカラム、暗号化設定 |

**読解のコツ**: otp_backup_codesはtextカラムでシリアライズ（80行目）され、暗号化（84行目）されている。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mfa_controller.rb | `app/controllers/api/v1/profile/mfa_controller.rb` | backup_codesアクションの実装 |

**主要処理フロー**:
1. **3行目**: `before_action :check_mfa_enabled, only: [:destroy, :backup_codes]` - MFA有効チェック
2. **5行目**: `before_action :validate_otp, only: [:verify, :backup_codes, :destroy]` - OTP検証
3. **22-24行目**: `backup_codes`アクション - バックアップコード生成・返却

#### Step 3: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | management_service.rb | `app/services/mfa/management_service.rb` | generate_backup_codes!メソッド |

**主要処理フロー**:
- **31-36行目**: `generate_backup_codes!` - 10個のバックアップコード生成
- **38-47行目**: `validate_backup_code!` - バックアップコードの検証と使用済みマーク
- **55-66行目**: `find_matching_code_index` - タイミング攻撃対策付きのコード検索
- **68-73行目**: `mark_code_as_used` - 使用済みコードの無効化

#### Step 4: ビューテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | backup_codes.json.jbuilder | `app/views/api/v1/profile/mfa/backup_codes.json.jbuilder` | レスポンスJSON構造 |

**主要処理フロー**:
- **1行目**: `json.backup_codes @backup_codes` - 生成されたコードの配列を出力

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

```
Api::V1::Profile::MfaController#backup_codes
    │
    ├─ check_mfa_enabled (before_action)
    │      └─ current_user.mfa_enabled?
    │
    ├─ validate_otp (before_action)
    │      └─ Mfa::AuthenticationService#authenticate
    │             └─ User#validate_and_consume_otp!
    │
    └─ Mfa::ManagementService#generate_backup_codes!
           └─ Array.new(10) { SecureRandom.hex(4).upcase }
           └─ user.otp_backup_codes = codes
           └─ user.save!
                  └─ users UPDATE (otp_backup_codes - encrypted)
```

### データフロー図

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

POST リクエスト ───────▶ MfaController#backup_codes ───────▶ {backup_codes: [...]}
(otp_code)                    │
                              ├─ mfa_enabled? チェック
                              │
                              ├─ OTP認証
                              │
                              └─ ManagementService#generate_backup_codes!
                                    │
                                    └─▶ users UPDATE (otp_backup_codes)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mfa_controller.rb | `app/controllers/api/v1/profile/mfa_controller.rb` | コントローラー | backup_codesアクションの定義（22-24行目） |
| management_service.rb | `app/services/mfa/management_service.rb` | サービス | バックアップコード生成ロジック |
| authentication_service.rb | `app/services/mfa/authentication_service.rb` | サービス | OTP/バックアップコード認証 |
| user.rb | `app/models/user.rb` | モデル | otp_backup_codesカラム、暗号化設定 |
| backup_codes.json.jbuilder | `app/views/api/v1/profile/mfa/backup_codes.json.jbuilder` | ビュー | レスポンステンプレート |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（382行目） |
