# 機能設計書 86-公開ボード閲覧

## 概要

本ドキュメントは、Fizzyアプリケーションにおける「公開ボード閲覧」機能の設計仕様を定義する。外部に公開されたボードを認証なしで閲覧できる機能である。

### 本機能の処理概要

公開ボード閲覧機能は、ボード管理者が公開設定したボードを、ログインしていない外部ユーザーでも閲覧できるようにする機能である。公開キーを含むURLでアクセスでき、ボードの概要、カラム、トリアージ待ちのカードを表示する。

**業務上の目的・背景**：プロジェクトの進捗状況やロードマップを社外のステークホルダーや顧客と共有するために、認証不要でボードを公開できる機能が必要である。これにより、透明性の高いプロジェクト管理やパブリックな課題追跡が可能になる。

**機能の利用シーン**：外部ユーザーが公開URLにアクセスしてボードの内容を閲覧する。例えば、製品のパブリックロードマップ、オープンソースプロジェクトの課題トラッカー、顧客向けの進捗共有などに使用される。

**主要な処理内容**：
1. 公開キーからボードを特定
2. アカウントがキャンセル済みでないことを確認
3. ボードの説明文とカラム一覧を表示
4. トリアージ待ちのカード一覧を表示（ゴールデンカードを優先）
5. OGP（Open Graph Protocol）メタタグを設定

**関連システム・外部連携**：なし

**権限による制御**：認証不要。ただし、公開設定されたボードのみアクセス可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 67 | 公開ボード詳細画面 | 主画面 | 公開ボードの概要とカード一覧を表示 |
| 68 | 公開ボードカラム画面 | 補助画面 | 特定カラムのカード一覧を表示 |
| 69 | 公開ボードストリーム画面 | 補助画面 | ストリームカラムのカード一覧を表示 |
| 70 | 公開ボードNot Now画面 | 補助画面 | Not Nowカラムのカード一覧を表示 |
| 71 | 公開ボードクローズド画面 | 補助画面 | クローズされたカード一覧を表示 |

## 機能種別

参照・表示 / 公開API

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| id | String | Yes | 公開キー（publication.key） | URLパラメータ |

### 入力データソース

URLパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| board.name | String | ボード名 |
| board.public_description | RichText | ボードの公開説明文 |
| columns | Array | カラム一覧 |
| cards | Array | トリアージ待ちカード一覧 |

### 出力先

HTML画面表示（publicレイアウト）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ GET /public/boards/:id
2. 公開キーからボード取得
   └─ Board.find_by_published_key(params[:id])
3. アクセス可否チェック
   └─ アカウントがキャンセル済みでないことを確認
4. キャッシュ設定
   └─ 30秒間のパブリックキャッシュを設定
5. カード一覧取得
   └─ トリアージ待ち、最新順、ゴールデン優先でページネーション
6. ビューレンダリング
   └─ publicレイアウトで表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[公開キーからボード取得]
    B --> C{ボード存在?}
    C -->|No| D[404 Not Found]
    C -->|Yes| E{アカウントキャンセル済み?}
    E -->|Yes| F[404 Not Found]
    E -->|No| G[キャッシュ設定]
    G --> H[カード一覧取得]
    H --> I[OGPメタタグ設定]
    I --> J[画面レンダリング]
    J --> K[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-86-01 | 公開キーアクセス | 公開キーを知っている人のみがアクセス可能 | 常時 |
| BR-86-02 | キャンセルアカウント制限 | キャンセル済みアカウントのボードは表示しない | 常時 |
| BR-86-03 | キャッシュ設定 | 30秒間のパブリックキャッシュを設定 | 常時 |
| BR-86-04 | カードソート | ゴールデンカードを先頭に、その後は最新順 | カード表示時 |
| BR-86-05 | トリアージ表示 | トリアージ待ち（awaiting_triage）のカードのみ表示 | 初期表示時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ボード取得 | board_publications | SELECT | 公開キーでボードを特定 |
| ボード取得 | boards | SELECT | 関連するボード情報を取得 |
| カード取得 | cards | SELECT | トリアージ待ちカードを取得 |

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

#### board_publications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | board_id | key = params[:id] | 公開キーで検索 |

#### boards

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | name, public_description等 | id = publication.board_id | リレーション経由 |

#### cards

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全カラム | board_id = @board.id AND awaiting_triage | ページネーション付き |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | NotFound | 公開キーが存在しない | エラーページ表示 |
| 404 | NotFound | アカウントがキャンセル済み | エラーページ表示 |

### リトライ仕様

該当なし

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

参照のみのためトランザクション制御なし

## パフォーマンス要件

- レスポンス時間: 500ms以内
- キャッシュ: 30秒間のパブリックキャッシュ（CDN等で利用可能）

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

- 公開キーは推測困難なランダム文字列（has_secure_token使用）
- 認証不要のため、公開設定されたボードの情報のみ表示
- キャンセル済みアカウントのボードは非表示

## 備考

OGPメタタグにより、SNSでURLを共有した際にボード名や説明文がプレビュー表示される。

---

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

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

### 推奨読解順序

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

公開ボードの仕組み（Board::Publication、Publishable concern）を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | publication.rb | `app/models/board/publication.rb` | Board::Publicationモデルの構造 |
| 1-2 | publishable.rb | `app/models/board/publishable.rb` | Publishable concernの実装 |

**読解のコツ**: `has_secure_token :key`により公開キーが自動生成される。`find_by_published_key`クラスメソッドでキーからボードを取得する。

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

Public::BoardsControllerとPublic::BaseControllerの処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | base_controller.rb | `app/controllers/public/base_controller.rb` | 基底コントローラーの処理 |
| 2-2 | boards_controller.rb | `app/controllers/public/boards_controller.rb` | showアクションの処理 |

**主要処理フロー**:
1. **2行目**: `allow_unauthenticated_access` - 認証不要の宣言
2. **4行目**: `before_action :set_board, :set_card, :set_public_cache_expiration`
3. **5行目**: `before_action :ensure_board_accessible` - アクセス可否チェック
4. **10-12行目**: `set_board` - 公開キーからボード取得
5. **18-20行目**: `set_public_cache_expiration` - 30秒キャッシュ設定

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

公開ボード画面の表示内容を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | show.html.erb | `app/views/public/boards/show.html.erb` | メイン画面の構造 |
| 3-2 | _columns.html.erb | `app/views/public/boards/show/_columns.html.erb` | カラム一覧表示 |

**主要処理フロー**:
- **4-13行目**: OGPメタタグの設定
- **22-26行目**: public_descriptionの表示
- **28行目**: カラム一覧パーシャルの呼び出し

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

```
Public::BoardsController#show
    │
    ├─ Public::BaseController#set_board
    │      └─ Board.find_by_published_key(params[:id])
    │             └─ Board::Publication.find_by!(key: key).board
    │
    ├─ Public::BaseController#ensure_board_accessible
    │      └─ raise RoutingError if @board&.account&.cancelled?
    │
    ├─ Public::BaseController#set_public_cache_expiration
    │      └─ expires_in 30.seconds, public: true
    │
    └─ @board.cards.awaiting_triage.latest.with_golden_first
```

### データフロー図

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

URLパラメータ ───▶ Public::BoardsController ───▶ HTML画面
  - id (公開キー)         │
                          ▼
                    board_publications ───▶ ボード特定
                          │
                          ▼
                    boards ───▶ ボード情報
                          │
                          ▼
                    cards ───▶ カード一覧
                          │               （トリアージ待ち、ゴールデン優先）
                          ▼
                    publicレイアウト ───▶ OGPメタタグ付きHTML
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| boards_controller.rb | `app/controllers/public/boards_controller.rb` | ソース | 公開ボードコントローラー |
| base_controller.rb | `app/controllers/public/base_controller.rb` | ソース | 公開ページ基底コントローラー |
| publication.rb | `app/models/board/publication.rb` | ソース | 公開設定モデル |
| publishable.rb | `app/models/board/publishable.rb` | ソース | 公開機能concern |
| show.html.erb | `app/views/public/boards/show.html.erb` | テンプレート | 公開ボード画面 |
| _columns.html.erb | `app/views/public/boards/show/_columns.html.erb` | テンプレート | カラム一覧パーシャル |
| public.html.erb | `app/views/layouts/public.html.erb` | テンプレート | 公開ページレイアウト |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（194-208行目） |
