# 機能設計書 92-PWAマニフェスト

## 概要

本ドキュメントは、FizzyアプリケーションのPWA（Progressive Web App）マニフェスト提供機能の設計仕様を定義する。

### 本機能の処理概要

Webアプリケーションをネイティブアプリのようにインストール・利用可能にするためのPWAマニフェストファイルを提供する機能。ブラウザがアプリの名前、アイコン、表示モード、ショートカット等の情報を取得するために利用する。

**業務上の目的・背景**：近年のWebアプリケーションでは、ユーザーがデスクトップやホーム画面にアプリをインストールして、ネイティブアプリに近い体験を得ることが期待されている。PWAマニフェストを提供することで、Fizzyをスタンドアロンアプリとしてインストール可能にし、ユーザーの利便性を向上させる。また、プッシュ通知の基盤としても機能する。

**機能の利用シーン**：
- ユーザーがブラウザからFizzyをホーム画面にインストールする場合
- ブラウザがPWAとしての情報（アプリ名、アイコン等）を取得する場合
- PWAショートカット機能を使って特定の画面に直接アクセスする場合
- オフライン対応やプッシュ通知の基盤として利用する場合

**主要な処理内容**：
1. `/manifest`エンドポイントへのHTTP GETリクエストを受信
2. ERBテンプレートを処理してJSONマニフェストを生成
3. アプリ名、アイコン、表示モード、ショートカット等の情報を含むJSONを返却

**関連システム・外部連携**：
- Webブラウザ（Chrome、Edge、Safari等）のPWAインストール機能
- Service Worker（プッシュ通知、オフライン対応）

**権限による制御**：本エンドポイントは認証なしで誰でもアクセス可能。PWAのインストール時に認証状態が不確定なため。

## 関連画面

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

## 機能種別

設定情報提供・PWA対応

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | パラメータは不要 | - |

### 入力データソース

HTTPリクエスト（GET /manifest）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| name | String | アプリケーション名（"Fizzy"、開発環境では環境名付き） |
| icons | Array | アプリアイコン情報の配列（192px、512px、maskable） |
| start_url | String | アプリ起動時のURL（"/"） |
| display | String | 表示モード（"standalone"） |
| scope | String | PWAのスコープ（"/"） |
| description | String | アプリの説明 |
| categories | Array | アプリカテゴリ（"bugs", "business", "productivity"） |
| shortcuts | Array | ショートカットメニュー情報 |

### 出力先

HTTPレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. HTTP GETリクエストを /manifest で受信
   └─ Rails::PwaControllerが処理を担当

2. ERBテンプレートを処理
   └─ app/views/pwa/manifest.json.erb を評価

3. 動的な値を埋め込み
   └─ アプリ名（環境名付き）
   └─ ショートカットURLの生成

4. JSONレスポンスを返却
   └─ Content-Type: application/json
```

### フローチャート

```mermaid
flowchart TD
    A[HTTP GET /manifest] --> B[Rails::PwaController]
    B --> C[manifest.json.erb テンプレート処理]
    C --> D{本番環境?}
    D -->|Yes| E[name: "Fizzy"]
    D -->|No| F[name: "Fizzy - 環境名"]
    E --> G[ショートカットURL生成]
    F --> G
    G --> H[JSONレスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-92-01 | 認証不要 | マニフェストエンドポイントは認証なしでアクセス可能 | 常時 |
| BR-92-02 | 環境名表示 | 本番環境以外ではアプリ名に環境名を付与 | 開発・ステージング環境 |
| BR-92-03 | スタンドアロン表示 | displayモードは"standalone"（ブラウザUIなし） | 常時 |

### 計算ロジック

アプリ名の生成ロジック:
```ruby
[ "Fizzy", Rails.env.production? ? nil : Rails.env ].compact.join(" - ")
```
- 本番環境: "Fizzy"
- 開発環境: "Fizzy - development"
- テスト環境: "Fizzy - test"

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

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

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

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

データベース操作なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 500 | Internal Server Error | テンプレート処理エラー | アプリケーションログの確認 |

### リトライ仕様

クライアント側でリトライを実施（ブラウザのデフォルト動作）。

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

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

## パフォーマンス要件

| 要件 | 値 |
|------|-----|
| レスポンス時間 | 100ms以下 |
| キャッシュ | ブラウザキャッシュ可能（静的コンテンツ） |

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

- 認証なしでアクセス可能なエンドポイントであるため、機密情報を含まないこと
- CSRFトークンは不要（読み取り専用）
- HTTPSでの配信が推奨（PWAの要件）

## 備考

- エンドポイントURLは`/manifest`（`pwa_manifest_path`）
- `config/routes.rb`で`get "manifest" => "rails/pwa#manifest"`として定義
- Service Workerは別途`/service-worker`で提供（PwaController#service_worker）

---

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

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

### 推奨読解順序

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

まず、マニフェストエンドポイントがどのように定義されているかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | routes.rb | `config/routes.rb` | PWA関連エンドポイントの定義を確認 |

**主要処理フロー**:
1. **245行目**: `get "manifest" => "rails/pwa#manifest", as: :pwa_manifest`でマニフェストエンドポイント定義
2. **246行目**: `get "service-worker" => "pwa#service_worker"`でService Workerエンドポイント定義

**読解のコツ**: `rails/pwa#manifest`はRails標準のコントローラーを指す。一方、`pwa#service_worker`はアプリケーション独自の`PwaController`を指す。

#### Step 2: マニフェストテンプレートを理解する

マニフェストの内容がどのように構成されているかを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | manifest.json.erb | `app/views/pwa/manifest.json.erb` | マニフェストの構造と動的値の生成 |

**主要処理フロー**:
1. **2行目**: アプリ名の動的生成（環境名付与）
2. **3-19行目**: アイコン定義（192px、512px、maskable）
3. **21-24行目**: 基本設定（start_url、display、scope、description）
4. **25行目**: カテゴリ定義
5. **26-38行目**: ショートカット定義（Notifications、Latest Activity）

**読解のコツ**: ERBテンプレート内でRailsヘルパー（`notifications_path`、`root_path`、`image_url`）を使用してURLを動的に生成している。

#### Step 3: Service Workerの関連機能を理解する

PWAの重要な構成要素であるService Workerの実装を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pwa_controller.rb | `app/controllers/pwa_controller.rb` | Service Workerエンドポイントの定義 |
| 3-2 | service_worker.js | `app/views/pwa/service_worker.js` | Service Workerの実装内容 |

**pwa_controller.rb 主要処理フロー**:
1. **2行目**: `disallow_account_scope` - アカウントスコープ外で動作
2. **3行目**: `skip_forgery_protection` - CSRF保護をスキップ
3. **6-7行目**: `service_worker`アクション（空実装、テンプレートを返すのみ）

**service_worker.js 主要処理フロー**:
1. **1-10行目**: fetchイベントハンドラ（オフライン対応）
2. **12-15行目**: pushイベントハンドラ（プッシュ通知表示）
3. **17-23行目**: 通知表示とバッジ更新
4. **25-41行目**: 通知クリック時のURL遷移処理

**読解のコツ**: Service WorkerはJavaScriptで実装され、ブラウザのバックグラウンドで動作する。`self`はService Workerのグローバルスコープを指す。

#### Step 4: アイコンアセットを確認する

マニフェストで参照されるアイコンファイルの存在を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | app-icon-192.png | `public/app-icon-192.png` | 192x192サイズのアイコン |
| 4-2 | app-icon.png | `public/app-icon.png` | 512x512サイズのアイコン |
| 4-3 | app-icon-192-maskable.png | `public/app-icon-192-maskable.png` | マスカブルアイコン |

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

```
HTTP GET /manifest
    │
    └─ Rails Router (config/routes.rb:245)
           │
           └─ Rails::PwaController#manifest (Rails標準)
                  │
                  └─ manifest.json.erb (app/views/pwa/)
                         │
                         ├─ Rails.env (環境判定)
                         ├─ notifications_path (URLヘルパー)
                         ├─ root_path (URLヘルパー)
                         └─ image_url (アセットヘルパー)

HTTP GET /service-worker
    │
    └─ Rails Router (config/routes.rb:246)
           │
           └─ PwaController#service_worker (app/controllers/)
                  │
                  └─ service_worker.js (app/views/pwa/)
```

### データフロー図

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

HTTP GET /manifest ───▶ Rails::PwaController ───▶ JSON Response
                        │
                        └▶ manifest.json.erb
                           │
                           ├─ アプリ名生成
                           ├─ アイコンURL解決
                           └─ ショートカットURL生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（245-246行目） |
| manifest.json.erb | `app/views/pwa/manifest.json.erb` | テンプレート | マニフェストJSON生成 |
| pwa_controller.rb | `app/controllers/pwa_controller.rb` | ソース | Service Workerエンドポイント |
| service_worker.js | `app/views/pwa/service_worker.js` | ソース | Service Worker実装 |
| app-icon-192.png | `public/app-icon-192.png` | アセット | 192x192アイコン |
| app-icon.png | `public/app-icon.png` | アセット | 512x512アイコン |
| app-icon-192-maskable.png | `public/app-icon-192-maskable.png` | アセット | マスカブルアイコン |
| pwa.css | `app/assets/stylesheets/pwa.css` | アセット | PWA用スタイルシート |
