---
generated_at: 2026-02-25 02:50:00
metrics:
  claims_total: 110
  claims_with_evidence: 107
  claims_without_evidence: 3
confidence_derived: 0.97
---

# 根拠レポート：controllers-root 単体テストケース一覧

## 本レポートについて

### 目的
本レポートは、生成された単体テストケース一覧の信頼性を検証し、人間レビュアーが効率的にレビューできるようにすることを目的としています。

### チェック方法
以下の観点でドキュメントの内容（Claim：主張）を検証しています：

1. **根拠の有無確認**：各主張に対して、ソースコード・既存設計書・要件定義書などの根拠（Evidence）が存在するか
2. **根拠との整合性**：主張の内容が根拠と矛盾していないか
3. **網羅性**：参照すべき情報源を適切にカバーしているか

### 信頼度スコアの算出
- **confidence_derived** = 根拠あり件数 / 総主張件数
- 状態「○」：根拠あり、「△」：根拠不足または要確認

### 本レポートの使い方
1. まず「サマリー」で全体の信頼度と優先レビュー項目を確認
2. 「Claims と根拠の対応」で △ の項目を重点的にレビュー
3. 「不足情報」で補完が必要な情報源を確認

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**0.97**
  - 根拠あり：107 / 110、根拠なし：3
- 優先レビュー（高）
  1. **UT-CRT-002/003 (allow_browser)**: モダンブラウザの定義と具体的なエラーコードが要確認
  2. **UT-CRT-094 (AdminController権限チェック)**: ensure_staffの実装詳細がconcernにある可能性
  3. **UT-CRT-097 (ClientConfigurations不正パラメータ)**: 具体的なエラー挙動が要確認

## 2) 参照した情報（Evidence一覧）
> ここに「実在するもの」だけ列挙。抽出フェーズで付けたIDをそのまま出す。

- E-01: `app/controllers/application_controller.rb`
- E-02: `app/controllers/boards_controller.rb`
- E-03: `app/controllers/events_controller.rb`
- E-04: `app/controllers/join_codes_controller.rb`
- E-05: `app/controllers/tags_controller.rb`
- E-06: `app/controllers/notifications_controller.rb`
- E-07: `app/controllers/webhooks_controller.rb`
- E-08: `app/controllers/users_controller.rb`
- E-09: `app/controllers/sessions_controller.rb`
- E-10: `app/controllers/signups_controller.rb`
- E-11: `app/controllers/qr_codes_controller.rb`
- E-12: `app/controllers/pwa_controller.rb`
- E-13: `app/controllers/cards_controller.rb`
- E-14: `app/controllers/admin_controller.rb`
- E-15: `app/controllers/client_configurations_controller.rb`
- E-16: `app/controllers/searches_controller.rb`
- E-17: `app/controllers/filters_controller.rb`
- E-18: `app/controllers/landings_controller.rb`
- E-19: `docs/code-to-docs/単体テストケース一覧/plan.md`

## 3) Claims と根拠の対応（レビューの主戦場）

### ApplicationController (E-01)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | ETagにv1が設定される | E-01 L10: `etag { "v1" }` | ○ |
| C-02 | モダンブラウザでアクセス可能 | E-01 L12: `allow_browser versions: :modern` | △ |
| C-03 | 非モダンブラウザがブロックされる | E-01 L12: `allow_browser versions: :modern` | △ |

### BoardsController (E-02)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-04 | JSON形式でボード一覧返却 | E-02 L8-10: `if request.format.json?` | ○ |
| C-05 | HTML形式でボード一覧返却 | E-02 L11-13: `else set_page_and_extract_portion_from` | ○ |
| C-06 | ボード0件で空配列返却 | E-02 L9: `Current.user.boards.ordered_by_recently_accessed` | ○ |
| C-07 | フィルタ未使用時にカラム表示 | E-02 L17-21: `if @filter.used?` + `show_columns` | ○ |
| C-08 | フィルタ使用時にフィルタ済みカード表示 | E-02 L17-18: `if @filter.used?` + `show_filtered_cards` | ○ |
| C-09 | 存在しないボードIDでRecordNotFound | E-02 L70: `Current.user.boards.find params[:id]` | ○ |
| C-10 | 新規ボードフォーム表示 | E-02 L24-26: `def new` + `@board = Board.new` | ○ |
| C-11 | ボードが正常に作成される | E-02 L28-35: `Board.create! board_params` | ○ |
| C-12 | JSON形式で201返却 | E-02 L33: `format.json { head :created` | ○ |
| C-13 | 名前空でエラー | E-02 L29: `Board.create!` + バリデーション | ○ |
| C-14 | 編集フォームにユーザー一覧 | E-02 L37-41: `def edit` + partition | ○ |
| C-15 | ボード情報更新 | E-02 L43-44: `@board.update! board_params` | ○ |
| C-16 | ユーザーアクセス権更新 | E-02 L45: `@board.accesses.revise` | ○ |
| C-17 | 自分が除外時にルートリダイレクト | E-02 L51-52: `else redirect_to root_path` | ○ |
| C-18 | 管理権限なしで403 | E-02 L73-76: `ensure_permission_to_admin_board` | ○ |
| C-19 | ボード削除 | E-02 L59-66: `@board.destroy` | ○ |
| C-20 | 削除時に管理権限なしで403 | E-02 L5, L73-76: `before_action :ensure_permission_to_admin_board` | ○ |

### EventsController (E-03)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-21 | タイムラインイベント表示 | E-03 L4-6: `def index` + `@day_timeline` | ○ |
| C-22 | ETag/Last-Modified設定 | E-03 L5: `fresh_when @day_timeline` | ○ |

### JoinCodesController (E-04)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-23 | 参加コード入力フォーム表示 | E-04 L11-12: `def new` | ○ |
| C-24 | 無効なコードで404 | E-04 L49-50: `if @join_code.nil?` + `head :not_found` | ○ |
| C-25 | 非アクティブなコードで410 | E-04 L51-52: `elsif !@join_code.active?` + `render :inactive, status: :gone` | ○ |
| C-26 | 既存ユーザーがアカウント参加 | E-04 L15-16: `@join_code.redeem_if` + `@identity.join(account)` | ○ |
| C-27 | 新規ユーザーがアカウント参加 | E-04 L32-41: `set_identity` + `@identity.save!` | ○ |
| C-28 | セットアップ済みユーザーがランディングリダイレクト | E-04 L18-19: `if @identity == Current.identity && user.setup?` | ○ |
| C-29 | 不正なメールで422 | E-04 L36-37: `if @identity.invalid?` + `head :unprocessable_entity` | ○ |
| C-30 | レート制限超過で429 | E-04 L3: `rate_limit to: 10, within: 3.minutes` | ○ |

### TagsController (E-05)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-31 | タグ一覧がアルファベット順 | E-05 L3: `Current.account.tags.alphabetically` | ○ |
| C-32 | タグ0件で空配列 | E-05 L3: スコープ呼び出し | ○ |

### NotificationsController (E-06)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-33 | 未読・既読通知分離返却 | E-06 L6-7: `@unread` + `set_page_and_extract_portion_from` | ○ |
| C-34 | JSON形式で最大100件の未読 | E-06 L3, L17-18: `MAX_UNREAD_NOTIFICATIONS_VIA_API = 100` | ○ |
| C-35 | HTML形式で最大500件の未読 | E-06 L2, L17-18: `MAX_UNREAD_NOTIFICATIONS = 500` | ○ |
| C-36 | 未読0件で空配列 | E-06 L6: `notifications.unread` | ○ |
| C-37 | ページネーションでturbo_stream | E-06 L10: `format.turbo_stream if current_page_param` | ○ |

### WebhooksController (E-07)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-38 | Webhook一覧返却 | E-07 L7-9: `def index` + `@board.webhooks.ordered` | ○ |
| C-39 | 管理者権限なしでエラー | E-07 L4: `before_action :ensure_admin` | ○ |
| C-40 | Webhook詳細表示 | E-07 L11-12: `def show` | ○ |
| C-41 | 新規Webhookフォーム表示 | E-07 L14-16: `def new` + `@board.webhooks.new` | ○ |
| C-42 | Webhook作成 | E-07 L18-21: `@board.webhooks.create!(webhook_params)` | ○ |
| C-43 | 必須パラメータ欠如でエラー | E-07 L19: `create!` + バリデーション | ○ |
| C-44 | Webhook編集フォーム表示 | E-07 L23-24: `def edit` | ○ |
| C-45 | Webhook更新（URL変更不可） | E-07 L26-28: `webhook_params.except(:url)` | ○ |
| C-46 | URL変更が無視される | E-07 L27: `webhook_params.except(:url)` | ○ |
| C-47 | Webhook削除 | E-07 L31-34: `@webhook.destroy!` | ○ |

### UsersController (E-08)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-48 | アクティブユーザー一覧アルファベット順 | E-08 L6: `Current.account.users.active.alphabetically` | ○ |
| C-49 | ユーザー1人で1件返却 | E-08 L6: スコープ呼び出し | ○ |
| C-50 | ユーザー詳細表示 | E-08 L9-10: `def show` | ○ |
| C-51 | 非アクティブユーザーでRecordNotFound | E-08 L40: `users.active.find(params[:id])` | ○ |
| C-52 | ユーザー編集フォーム表示 | E-08 L12-13: `def edit` | ○ |
| C-53 | ユーザー情報更新 | E-08 L15-27: `@user.update(user_params)` | ○ |
| C-54 | JSON形式で204返却 | E-08 L19: `format.json { head :no_content }` | ○ |
| C-55 | 変更権限なしで403 | E-08 L43-45: `ensure_permission_to_change_user` | ○ |
| C-56 | バリデーションエラー時に422 | E-08 L24: `format.json { render json: @user.errors, status: :unprocessable_entity }` | ○ |
| C-57 | ユーザー非アクティブ化 | E-08 L29-36: `@user.deactivate` | ○ |
| C-58 | 削除時に変更権限なしで403 | E-08 L3, L43-45: `before_action :ensure_permission_to_change_user` | ○ |

### SessionsController (E-09)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-59 | ログインフォーム表示 | E-09 L8-9: `def new` | ○ |
| C-60 | 認証済みでリダイレクト | E-09 L3: `require_unauthenticated_access except: :destroy` | ○ |
| C-61 | 既存ユーザーにマジックリンク送信 | E-09 L12-13: `if identity = Identity.find_by` + `sign_in identity` | ○ |
| C-62 | サインアップ受付中に新規ユーザー登録 | E-09 L14-15: `elsif Account.accepting_signups?` + `sign_up` | ○ |
| C-63 | サインアップ停止中は偽リンク画面 | E-09 L16-17: `redirect_to_fake_session_magic_link` | ○ |
| C-64 | レート制限超過で429 | E-09 L4, L44-51: `rate_limit to: 10` + `rate_limit_exceeded` | ○ |
| C-65 | セッション終了しリダイレクト | E-09 L21-28: `terminate_session` + `redirect_to_logout_url` | ○ |
| C-66 | JSON形式で204返却 | E-09 L26: `format.json { head :no_content }` | ○ |

### SignupsController (E-10)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-67 | サインアップフォーム表示 | E-10 L10-12: `def new` + `@signup = Signup.new` | ○ |
| C-68 | 認証済みでリダイレクト | E-10 L5, L24-25: `redirect_authenticated_user` | ○ |
| C-69 | サインアップ停止中はセッション画面リダイレクト | E-10 L6, L28-29: `enforce_tenant_limit` | ○ |
| C-70 | 有効なメールでサインアップ | E-10 L14-18: `signup.valid?(:identity_creation)` + `create_identity` | ○ |
| C-71 | 不正なメールで422 | E-10 L18-19: `head :unprocessable_entity` | ○ |
| C-72 | レート制限超過でリダイレクト | E-10 L4: `rate_limit to: 10` | ○ |

### QrCodesController (E-11)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-73 | QRコードSVG返却 | E-11 L7-11: `RQRCode::QRCode` + `as_svg` | ○ |
| C-74 | キャッシュヘッダー1年設定 | E-11 L5: `expires_in 1.year, public: true` | ○ |
| C-75 | 不正な署名でエラー | E-11 L8: `QrCodeLink.from_signed(params[:id])` | ○ |

### PwaController (E-12)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-76 | Service Worker返却 | E-12 L6-7: `def service_worker` | ○ |
| C-77 | CSRFトークンなしでアクセス可能 | E-12 L3: `skip_forgery_protection` | ○ |

### CardsController (E-13)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-78 | フィルタ済みカード一覧返却 | E-13 L10: `@filter.cards` | ○ |
| C-79 | フィルタ結果0件で空配列 | E-13 L10: スコープ呼び出し | ○ |
| C-80 | HTML形式で下書きカード作成 | E-13 L15-18: `Current.user.draft_new_card_in(@board)` | ○ |
| C-81 | JSON形式で公開カード作成 | E-13 L20-23: `status: "published"` + `head :created` | ○ |
| C-82 | 存在しないボードIDでRecordNotFound | E-13 L52-53: `Current.user.boards.find params[:board_id]` | ○ |
| C-83 | カード詳細表示 | E-13 L27-28: `def show` | ○ |
| C-84 | 下書きカードで下書き画面リダイレクト | E-13 L60-62: `redirect_if_drafted` | ○ |
| C-85 | 存在しないカード番号でRecordNotFound | E-13 L56-57: `find_by!(number: params[:id])` | ○ |
| C-86 | カード編集フォーム表示 | E-13 L30-31: `def edit` | ○ |
| C-87 | カード情報更新 | E-13 L33-34: `@card.update! card_params` | ○ |
| C-88 | turbo_stream形式でレスポンス | E-13 L37: `format.turbo_stream` | ○ |
| C-89 | JSON形式でカード詳細返却 | E-13 L38: `format.json { render :show }` | ○ |
| C-90 | カード削除 | E-13 L42-49: `@card.destroy!` | ○ |
| C-91 | JSON形式で204返却 | E-13 L47: `format.json { head :no_content }` | ○ |
| C-92 | 管理権限なしで403 | E-13 L64-66: `ensure_permission_to_administer_card` | ○ |

### AdminController (E-14)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-93 | スタッフユーザーがアクセス可能 | E-14 L3: `before_action :ensure_staff` | ○ |
| C-94 | 非スタッフユーザーがアクセス不可 | E-14 L3: `before_action :ensure_staff` | △ |

### ClientConfigurationsController (E-15)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-95 | クライアント設定返却 | E-15 L6-8: `render action: client_configuration_name` | ○ |
| C-96 | キャッシュヘッダー1分設定 | E-15 L6: `expires_in 1.minute, public: true` | ○ |
| C-97 | 存在しないplatform/versionでエラー | E-15 L12-13: `client_configuration_name` | △ |
| C-98 | 認証なしでアクセス可能 | E-15 L2-3: `skip_before_action` + `allow_unauthorized_access` | ○ |

### SearchesController (E-16)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-99 | 検索クエリで検索結果返却 | E-16 L7-10: `Current.user.search(@query)` | ○ |
| C-100 | カードIDで直接カード返却 | E-16 L7-8: `find_by_id(@query)` | ○ |
| C-101 | 最近の検索クエリ10件まで返却 | E-16 L11: `search_queries.order(updated_at: :desc).limit(10)` | ○ |
| C-102 | 検索クエリ空でnilが設定 | E-16 L5: `params[:q].blank? ? nil : params[:q]` | ○ |

### FiltersController (E-17)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-103 | フィルタ保存 | E-17 L5: `Current.user.filters.remember filter_params` | ○ |
| C-104 | パラメータ正規化 | E-17 L18-19: `Filter.normalize_params` | ○ |
| C-105 | フィルタ削除 | E-17 L8-10: `@filter.destroy!` | ○ |
| C-106 | 存在しないフィルタIDでRecordNotFound | E-17 L9: `Current.user.filters.find(params[:id])` | ○ |

### LandingsController (E-18)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-107 | ボード1つでそのボードにリダイレクト | E-18 L5-6: `if Current.user.boards.one?` | ○ |
| C-108 | ボード複数でルートリダイレクト | E-18 L7-8: `else redirect_to root_path` | ○ |
| C-109 | フラッシュメッセージ維持 | E-18 L3: `flash.keep(:welcome_letter)` | ○ |
| C-110 | ボード0件でルートリダイレクト | E-18 L5-8: `boards.one?`はfalseになりroot_pathへ | ○ |

## 4) 不足情報（Unknown / Missing）
- **allow_browserの具体的な挙動**: `versions: :modern`の定義がRails内部にあり、具体的なエラーコード（426等）の確認が必要
  - 候補: Railsドキュメント / ActionController::AllowBrowserソースコード
- **ensure_staffメソッドの実装**: AdminControllerでは`before_action :ensure_staff`が呼ばれているが、実装はconcernにある可能性
  - 候補: `app/controllers/concerns/` 内のファイル
- **ClientConfigurationsControllerの存在しないテンプレートエラー**: 不正なplatform/versionの組み合わせ時の具体的なエラー挙動は、テンプレートの存在に依存
  - 候補: `app/views/client_configurations/` 内のテンプレート一覧

## 5) リスクフラグ（レビュー観点）
- **リスク0（低リスク）**: 大部分のテストケースはソースコードから直接確認可能な機能のテスト
- **リスク1（中リスク）**: C-02, C-03 - allow_browserの挙動はRails内部実装に依存
- **リスク1（中リスク）**: C-94 - ensure_staffの実装詳細がconcernにあり、具体的な挙動確認が必要
- **リスク1（中リスク）**: C-97 - テンプレートの存在に依存するエラー挙動

## 6) レビュアーチェックリスト（最小）
- [ ] C-02, C-03: allow_browserの具体的なエラーコードとモダンブラウザの定義を確認
- [ ] C-94: ensure_staffメソッドの実装を確認（concernsディレクトリ）
- [ ] C-97: client_configurationsのテンプレート一覧を確認し、不正パラメータ時のエラーを確認
- [ ] 全体: 権限チェック系のテストケース（C-18, C-20, C-55, C-58, C-92）の網羅性確認
- [ ] 全体: レート制限系のテストケース（C-30, C-64, C-72）の閾値とエラーレスポンスの確認
