# 機能設計書 93-モバイルクライアント設定

## 概要

本ドキュメントは、Fizzyアプリケーションのモバイルクライアント（iOS/Android）向け設定情報提供機能の設計仕様を定義する。

### 本機能の処理概要

iOS/Androidのネイティブアプリ（Hotwire/Turbo Native）向けに、画面遷移ルールや表示設定などの設定情報をJSON形式で提供する機能。モバイルアプリがサーバーから設定を取得することで、アプリ更新なしに動作をカスタマイズできる。

**業務上の目的・背景**：Fizzyはモバイルネイティブアプリ（iOS/Android）を提供しており、Hotwire/Turbo Nativeフレームワークを使用してWebビューベースのハイブリッドアプリを実現している。モバイルアプリの動作設定（モーダル表示、プルトゥリフレッシュ、ネイティブ画面への遷移等）をサーバー側で一元管理することで、アプリのストア審査を待たずに動作を変更でき、運用の柔軟性が向上する。

**機能の利用シーン**：
- モバイルアプリ起動時に設定情報を取得する場合
- 特定のURLパターンでモーダル表示するか通常表示するかを判定する場合
- ネイティブ画面（ログイン、設定、通知等）への遷移を制御する場合
- プルトゥリフレッシュの有効/無効を制御する場合

**主要な処理内容**：
1. `/client_configurations/{platform}_v{version}`エンドポイントへのHTTP GETリクエストを受信
2. プラットフォーム（android/ios）とバージョンに応じた設定ファイルを選択
3. JSONレスポンスとして設定情報を返却（1分間のキャッシュ設定）

**関連システム・外部連携**：
- Fizzy iOSアプリ（Turbo Native）
- Fizzy Androidアプリ（Turbo Native / Hotwire）

**権限による制御**：本エンドポイントは認証なしで誰でもアクセス可能。アプリ起動時に認証前の状態で設定を取得する必要があるため。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | なし | - | 画面を持たないAPIエンドポイント |

## 機能種別

設定情報提供・モバイルアプリ連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| platform | String | Yes | プラットフォーム識別子 | "android" または "ios" のみ許可 |
| version | Integer | Yes | 設定バージョン番号 | 数字のみ（正規表現: `\d+`） |

### 入力データソース

HTTPリクエスト（GET /client_configurations/{platform}_v{version}）

例:
- `/client_configurations/android_v1`
- `/client_configurations/ios_v1`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| settings | Object | グローバル設定（現在は空オブジェクト） |
| rules | Array | URLパターンに対する表示ルールの配列 |

#### rulesオブジェクトの構造

| 項目名 | 型 | 説明 |
|--------|-----|------|
| patterns | Array<String> | マッチ対象のURLパターン（正規表現） |
| properties | Object | マッチ時に適用するプロパティ |

#### propertiesオブジェクトの構造（プラットフォーム共通）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| context | String | 表示コンテキスト（"default" / "modal"） |
| pull_to_refresh_enabled | Boolean | プルトゥリフレッシュの有効/無効 |
| query_string_presentation | String | クエリ文字列の扱い（"replace"等） |

#### Android固有のproperties

| 項目名 | 型 | 説明 |
|--------|-----|------|
| presentation | String | 画面表示方式 |
| uri | String | Hotwire URIスキーム |
| fallback_uri | String | フォールバックURI |

#### iOS固有のproperties

| 項目名 | 型 | 説明 |
|--------|-----|------|
| view_controller | String | 使用するビューコントローラー名 |

### 出力先

HTTPレスポンス（JSON形式）、Cache-Control: public, max-age=60

## 処理フロー

### 処理シーケンス

```
1. HTTP GETリクエストを /client_configurations/{platform}_v{version} で受信
   └─ ルーティングでplatformとversionをパラメータとして抽出

2. ClientConfigurationsControllerがリクエストを処理
   └─ 認証をスキップ（skip_before_action）
   └─ 認可をスキップ（allow_unauthorized_access）

3. キャッシュヘッダーを設定
   └─ expires_in 1.minute, public: true

4. 対応するビューテンプレートを選択
   └─ app/views/client_configurations/{platform}_v{version}.json

5. JSONレスポンスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[HTTP GET /client_configurations/{platform}_v{version}] --> B{platform検証}
    B -->|android/ios以外| C[404 Not Found]
    B -->|android/ios| D{version検証}
    D -->|数字以外| C
    D -->|数字| E{テンプレート存在?}
    E -->|No| F[500 Missing Template]
    E -->|Yes| G[キャッシュヘッダー設定]
    G --> H[JSONレスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-93-01 | 認証不要 | 設定エンドポイントは認証なしでアクセス可能 | 常時 |
| BR-93-02 | プラットフォーム制限 | android/ios以外のプラットフォームは404エラー | 不正なプラットフォーム指定時 |
| BR-93-03 | バージョン制限 | 数字以外のバージョン指定は404エラー | 不正なバージョン指定時 |
| BR-93-04 | キャッシュ有効 | レスポンスは1分間パブリックキャッシュ可能 | 常時 |
| BR-93-05 | モーダル表示 | /new, /edit, /draftなどの編集系URLはモーダル表示 | URL パターンマッチ時 |

### 計算ロジック

設定ファイル名の生成ロジック:
```ruby
"#{params.require(:platform)}_v#{params.require(:version)}"
```
- 例: platform="android", version="1" → "android_v1"

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| なし | - | - | データベースアクセスは行わない |

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | 不正なplatformまたはversion指定 | 正しいパラメータでリトライ |
| 500 | Missing Template | 存在しないバージョン指定 | サポートされているバージョンを使用 |

### リトライ仕様

クライアント側でリトライを実施（モバイルアプリのデフォルト動作）。

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

トランザクションは使用しない。

## パフォーマンス要件

| 要件 | 値 |
|------|-----|
| レスポンス時間 | 100ms以下 |
| キャッシュ時間 | 60秒（パブリック） |
| 同時リクエスト数 | 制限なし（静的コンテンツ相当） |

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

- 認証なしでアクセス可能なエンドポイントであるため、機密情報を含まないこと
- 設定情報はURLパターンと表示設定のみで、ユーザー固有の情報は含まない
- パブリックキャッシュが有効なため、CDN経由での配信も可能

## 備考

- 現在サポートされているバージョン: v1（android/ios両方）
- Hotwire/Turbo Nativeフレームワークを使用したハイブリッドアプリ向け
- 新しいバージョンを追加する場合は`app/views/client_configurations/`に対応するJSONファイルを追加

---

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

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

### 推奨読解順序

#### Step 1: ルーティング定義を理解する

まず、モバイルクライアント設定エンドポイントがどのように定義されているかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | routes.rb | `config/routes.rb` | クライアント設定エンドポイントの定義とパラメータ制約 |

**主要処理フロー**:
1. **248-250行目**: モバイルクライアント設定ルートの定義

```ruby
get "client_configurations/(:platform)_v(:version)" => "client_configurations#show",
  platform: /android|ios/, version: /\d+/
```

**読解のコツ**:
- `(:platform)`と`(:version)`はURLから抽出されるパラメータ
- `platform: /android|ios/`は正規表現による制約（android/iosのみ許可）
- `version: /\d+/`は数字のみ許可する制約
- 制約にマッチしない場合はルーティングエラー（404）

#### Step 2: コントローラーを理解する

リクエスト処理のメインロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | client_configurations_controller.rb | `app/controllers/client_configurations_controller.rb` | コントローラーの実装 |

**主要処理フロー**:
1. **2行目**: `skip_before_action :require_account, :require_authentication` - 認証をスキップ
2. **3行目**: `allow_unauthorized_access` - 認可チェックをスキップ
3. **5-8行目**: `show`アクション - キャッシュ設定とビューレンダリング
4. **12-14行目**: `client_configuration_name`プライベートメソッド - テンプレート名生成

```ruby
def show
  expires_in 1.minute, public: true
  render action: client_configuration_name
end

def client_configuration_name
  "#{params.require(:platform)}_v#{params.require(:version)}"
end
```

**読解のコツ**:
- `expires_in 1.minute, public: true`はHTTPキャッシュヘッダー（Cache-Control）を設定
- `render action:`で対応するビューテンプレートをレンダリング

#### Step 3: Android設定ファイルを理解する

Android向けの設定内容を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | android_v1.json | `app/views/client_configurations/android_v1.json` | Android設定の構造 |

**主要処理フロー**:
1. **1-3行目**: settingsオブジェクト（空）
2. **4-16行目**: デフォルトルール（すべてのURLにマッチ）
3. **17-32行目**: モーダル表示ルール（/new, /edit, /draft等）
4. **33-88行目**: ネイティブ画面遷移ルール（login, settings, pins, notifications）

**読解のコツ**:
- `patterns`は正規表現文字列の配列
- `hotwire://fragment/`はHotwireネイティブ画面へのURIスキーム
- ルールは上から順に評価され、最初にマッチしたものが適用される

#### Step 4: iOS設定ファイルを理解する

iOS向けの設定内容を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | ios_v1.json | `app/views/client_configurations/ios_v1.json` | iOS設定の構造 |

**主要処理フロー**:
1. **1-3行目**: settingsオブジェクト（空）
2. **4-14行目**: デフォルトルール
3. **15-28行目**: モーダル表示ルール
4. **29-87行目**: ネイティブビューコントローラー遷移ルール

**読解のコツ**:
- `view_controller`はiOSネイティブのビューコントローラー名
- iOSでは`uri`の代わりに`view_controller`を使用
- Android/iOSで同じURLパターンでも、遷移方法が異なる場合がある

#### Step 5: テストを理解する

コントローラーのテストケースを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | client_configurations_controller_test.rb | `test/controllers/client_configurations_controller_test.rb` | テストケース |

**主要処理フロー**:
1. **4-6行目**: Android正常系テスト
2. **8-10行目**: iOS正常系テスト
3. **12-14行目**: 不正プラットフォームテスト（RoutingError期待）
4. **16-18行目**: 不正バージョン形式テスト（RoutingError期待）
5. **20-23行目**: 存在しないバージョンテスト（MissingTemplate期待）

**読解のコツ**:
- `without_action_dispatch_exception_handling`で例外を直接キャッチ
- キャッシュヘッダー（`cache_control`）のアサーションも含まれる

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

```
HTTP GET /client_configurations/{platform}_v{version}
    │
    └─ Rails Router (config/routes.rb:248-250)
           │ platform/version制約チェック
           │
           └─ ClientConfigurationsController#show
                  │
                  ├─ skip_before_action (認証スキップ)
                  │
                  ├─ expires_in 1.minute, public: true
                  │
                  └─ render action: "{platform}_v{version}"
                         │
                         └─ app/views/client_configurations/
                                ├─ android_v1.json
                                └─ ios_v1.json
```

### データフロー図

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

HTTP GET                    ClientConfigurations
/client_configurations      Controller                          JSON Response
/android_v1.json                │                               (settings + rules)
        │                       │
        └──────────────────▶ パラメータ抽出                              │
                                │                                      │
                            platform = "android"                       │
                            version = "1"                              │
                                │                                      │
                            テンプレート選択                             │
                            "android_v1"                               │
                                │                                      │
                            キャッシュヘッダー設定 ────────────────────▶ Cache-Control:
                            expires_in 1.minute                        public, max-age=60
                                │
                            JSON生成 ─────────────────────────────────▶ {settings, rules}
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（248-250行目） |
| client_configurations_controller.rb | `app/controllers/client_configurations_controller.rb` | ソース | コントローラー実装 |
| android_v1.json | `app/views/client_configurations/android_v1.json` | 設定 | Android v1設定 |
| ios_v1.json | `app/views/client_configurations/ios_v1.json` | 設定 | iOS v1設定 |
| client_configurations_controller_test.rb | `test/controllers/client_configurations_controller_test.rb` | テスト | コントローラーテスト |
| authentication.rb | `app/controllers/concerns/authentication.rb` | ソース | 認証concern（スキップ対象） |
| authorization.rb | `app/controllers/concerns/authorization.rb` | ソース | 認可concern（スキップ対象） |
