---
generated_at: 2026-01-29 15:30:00
metrics:
  claims_total: 141
  claims_with_evidence: 138
  claims_without_evidence: 3
confidence_derived: 0.98
---

# 根拠レポート: recommendations モジュール 単体テストケース一覧

## 本レポートについて

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

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

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

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

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

---

## 1) サマリー(まず見るところ)
- 総合信頼度(derived): **0.98**
  - 根拠あり: 138 / 141、根拠なし: 3
- 優先レビュー(高)
  1. **UT-REC-046, 047**: updateRecommendationsEnabledSetting の詳細動作 - 設定サービスの実装詳細が不明
  2. **UT-REC-122**: RecommendationMetadataService のフォールバック動作 - 実際のリトライロジックの検証が必要

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

- E-01: `ghost/core/core/server/models/recommendation.js` - Recommendationモデル定義
- E-02: `ghost/core/core/server/models/recommendation-click-event.js` - クリックイベントモデル定義
- E-03: `ghost/core/core/server/models/recommendation-subscribe-event.js` - 購読イベントモデル定義
- E-04: `ghost/core/core/server/services/recommendations/service/recommendation.ts` - Recommendationエンティティ(ドメインロジック)
- E-05: `ghost/core/core/server/services/recommendations/service/recommendation-service.ts` - RecommendationService
- E-06: `ghost/core/core/server/services/recommendations/service/click-event.ts` - ClickEventエンティティ
- E-07: `ghost/core/core/server/services/recommendations/service/subscribe-event.ts` - SubscribeEventエンティティ
- E-08: `ghost/core/core/server/services/recommendations/service/recommendation-controller.ts` - RecommendationController
- E-09: `ghost/core/core/server/services/recommendations/service/bookshelf-recommendation-repository.ts` - BookshelfRecommendationRepository
- E-10: `ghost/core/core/server/services/recommendations/service/bookshelf-click-event-repository.ts` - BookshelfClickEventRepository
- E-11: `ghost/core/core/server/services/recommendations/service/bookshelf-subscribe-event-repository.ts` - BookshelfSubscribeEventRepository
- E-12: `ghost/core/core/server/services/recommendations/service/bookshelf-repository.ts` - 基底BookshelfRepository
- E-13: `ghost/core/core/server/services/recommendations/service/unsafe-data.ts` - UnsafeData(バリデーションユーティリティ)
- E-14: `ghost/core/core/server/services/recommendations/service/well-known-service.ts` - WellknownService
- E-15: `ghost/core/core/server/services/recommendations/service/recommendation-metadata-service.ts` - RecommendationMetadataService
- E-16: `ghost/core/core/server/services/recommendations/service/incoming-recommendation-service.ts` - IncomingRecommendationService
- E-17: `ghost/core/core/server/services/recommendations/service/incoming-recommendation-controller.ts` - IncomingRecommendationController
- E-18: `ghost/core/core/server/services/recommendations/service/incoming-recommendation-email-renderer.ts` - IncomingRecommendationEmailRenderer
- E-19: `ghost/core/core/server/services/recommendations/service/recommendation-repository.ts` - RecommendationRepository(インターフェース)

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

### Recommendation エンティティ (UT-REC-001 〜 019)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | create: 正常なデータでエンティティ作成 | E-04 (L132-155) | ○ |
| C-02 | create: ID自動生成 | E-04 (L133) ObjectId使用 | ○ |
| C-03 | create: createdAt自動設定 | E-04 (L144) | ○ |
| C-04 | validate: タイトル空チェック | E-04 (L96-100) | ○ |
| C-05 | validate: タイトル2000文字上限 | E-04 (L102-106) | ○ |
| C-06 | validate: タイトル2000文字境界 | E-04 (L102) 条件は `> 2000` | ○ |
| C-07 | validate: description 200文字上限 | E-04 (L108-112) | ○ |
| C-08 | validate: description 200文字境界 | E-04 (L108) 条件は `> 200` | ○ |
| C-09 | clean: 空description -> null | E-04 (L116-118) | ○ |
| C-10 | clean: 空excerpt -> null | E-04 (L120-122) | ○ |
| C-11 | clean: excerpt 2000文字切り詰め | E-04 (L124-126) | ○ |
| C-12 | clean: ミリ秒を0に設定 | E-04 (L128-129) | ○ |
| C-13 | edit: タイトル変更 | E-04 (L177-196) | ○ |
| C-14 | edit: undefined プロパティ無視 | E-04 (L183) | ○ |
| C-15 | edit: 変更なしの場合updatedAt不変 | E-04 (L189-191) | ○ |
| C-16 | delete: 削除フラグ設定 | E-04 (L198-200) | ○ |
| C-17 | plain: プレーンオブジェクト取得 | E-04 (L157-172) | ○ |
| C-18 | clickCount ゲッター | E-04 (L71-73) | ○ |
| C-19 | subscriberCount ゲッター | E-04 (L75-77) | ○ |

### ClickEvent / SubscribeEvent エンティティ (UT-REC-020 〜 026)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-20 | ClickEvent.create 正常系 | E-06 (L20-31) | ○ |
| C-21 | ClickEvent memberIdがnull許容 | E-06 (L20, 26) | ○ |
| C-22 | ClickEvent ID自動生成 | E-06 (L21) | ○ |
| C-23 | ClickEvent deleted常にfalse | E-06 (L9-11) | ○ |
| C-24 | SubscribeEvent.create 正常系 | E-07 (L20-30) | ○ |
| C-25 | SubscribeEvent ID自動生成 | E-07 (L21) | ○ |
| C-26 | SubscribeEvent deleted常にfalse | E-07 (L9-11) | ○ |

### RecommendationService (UT-REC-027 〜 047)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-27 | addRecommendation 正常系 | E-05 (L123-143) | ○ |
| C-28 | addRecommendation 重複URL検出 | E-05 (L127-132) | ○ |
| C-29 | readRecommendation 正常系 | E-05 (L111-121) | ○ |
| C-30 | readRecommendation NotFoundError | E-05 (L114-118) | ○ |
| C-31 | editRecommendation 正常系 | E-05 (L199-217) | ○ |
| C-32 | editRecommendation NotFoundError | E-05 (L202-206) | ○ |
| C-33 | deleteRecommendation 正常系 | E-05 (L219-236) | ○ |
| C-34 | deleteRecommendation NotFoundError | E-05 (L220-225) | ○ |
| C-35 | listRecommendations 正常系 | E-05 (L254-257) | ○ |
| C-36 | listRecommendations フィルタ | E-05 (L254) filter引数 | ○ |
| C-37 | countRecommendations | E-05 (L259-261) | ○ |
| C-38 | trackClicked 正常系 | E-05 (L263-266) | ○ |
| C-39 | trackClicked memberIdなし | E-05 (L264) memberId省略可 | ○ |
| C-40 | trackSubscribed 正常系 | E-05 (L268-271) | ○ |
| C-41 | checkRecommendation 既存URL | E-05 (L145-152) | ○ |
| C-42 | checkRecommendation 新規URL | E-05 (L154-177) | ○ |
| C-43 | checkRecommendation エラー時デフォルト | E-05 (L157-167) catch節 | ○ |
| C-44 | readRecommendationByUrl 正常系 | E-05 (L273-280) | ○ |
| C-45 | readRecommendationByUrl null返却 | E-05 (L275-278) | ○ |
| C-46 | updateRecommendationsEnabledSetting true設定 | E-05 (L89-98) | △ |
| C-47 | updateRecommendationsEnabledSetting false設定 | E-05 (L89-98) | △ |

### RecommendationController (UT-REC-048 〜 063)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-48 | read API | E-08 (L37-46) | ○ |
| C-49 | add API | E-08 (L48-66) | ○ |
| C-50 | edit API | E-08 (L84-103) | ○ |
| C-51 | destroy API | E-08 (L105-109) | ○ |
| C-52 | browse API | E-08 (L145-169) | ○ |
| C-53 | browse デフォルト値 | E-08 (L148-149) | ○ |
| C-54 | check API | E-08 (L74-82) | ○ |
| C-55 | trackClicked API | E-08 (L171-179) | ○ |
| C-56 | trackSubscribed API | E-08 (L181-190) | ○ |
| C-57 | trackSubscribed 認証チェック | E-08 (L192-204) UnauthorizedError | ○ |
| C-58 | #stringToOrder 正常系 | E-08 (L111-143) | ○ |
| C-59 | #stringToOrder 複数条件 | E-08 (L122-140) | ○ |
| C-60 | #stringToOrder デフォルト | E-08 (L112-119) | ○ |
| C-61 | #serializePagination | E-08 (L246-257) | ○ |
| C-62 | #serializePagination prev=null | E-08 (L254) | ○ |
| C-63 | #serializePagination next=null | E-08 (L255) | ○ |

### Repository クラス (UT-REC-064 〜 087)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-64 | getByUrl 正常系 | E-09 (L100-116) | ○ |
| C-65 | getByUrl www正規化 | E-09 (L111) | ○ |
| C-66 | getByUrl パス正規化 | E-09 (L112) | ○ |
| C-67 | getByUrl null返却 | E-09 (L104-105) | ○ |
| C-68 | toPrimitive | E-09 (L44-58) | ○ |
| C-69 | modelToEntity 正常系 | E-09 (L60-81) | ○ |
| C-70 | modelToEntity エラー時null | E-09 (L76-79) | ○ |
| C-71 | applyCustomQuery clickCount | E-09 (L31-35) | ○ |
| C-72 | applyCustomQuery subscriberCount | E-09 (L37-41) | ○ |
| C-73 | ClickEventRepository toPrimitive | E-10 (L17-24) | ○ |
| C-74 | ClickEventRepository modelToEntity | E-10 (L26-39) | ○ |
| C-75 | SubscribeEventRepository toPrimitive | E-11 (L17-24) | ○ |
| C-76 | SubscribeEventRepository modelToEntity | E-11 (L26-39) | ○ |
| C-77 | BookshelfRepository save 新規 | E-12 (L86-98) | ○ |
| C-78 | BookshelfRepository save 更新 | E-12 (L93-95) | ○ |
| C-79 | BookshelfRepository save 削除 | E-12 (L87-90) | ○ |
| C-80 | getById 正常系 | E-12 (L101-110) | ○ |
| C-81 | getById null | E-12 (L106-109) | ○ |
| C-82 | getAll | E-12 (L152-158) | ○ |
| C-83 | getPage | E-12 (L160-168) | ○ |
| C-84 | getPage pageバリデーション | E-12 (L115-117) | ○ |
| C-85 | getPage limitバリデーション | E-12 (L118-120) | ○ |
| C-86 | getCount | E-12 (L170-176) | ○ |
| C-87 | getGroupedCount | E-12 (L178-195) | ○ |

### UnsafeData (UT-REC-088 〜 113)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-88 | string 正常系 | E-13 (L127-132) | ○ |
| C-89 | string 型エラー | E-13 (L128-130) | ○ |
| C-90 | boolean 正常系 | E-13 (L134-139) | ○ |
| C-91 | boolean 型エラー | E-13 (L135-137) | ○ |
| C-92 | number 正常系 | E-13 (L141-157) | ○ |
| C-93 | number 文字列変換 | E-13 (L142-148) | ○ |
| C-94 | number NaN | E-13 (L153-155) | ○ |
| C-95 | integer 正常系 | E-13 (L159-173) | ○ |
| C-96 | integer 小数エラー | E-13 (L169-171) | ○ |
| C-97 | url 正常系 | E-13 (L175-191) | ○ |
| C-98 | url 無効URL | E-13 (L188-190) | ○ |
| C-99 | url プロトコル制限 | E-13 (L184-186) | ○ |
| C-100 | key 正常系 | E-13 (L68-80) | ○ |
| C-101 | key 必須チェック | E-13 (L73-75) | ○ |
| C-102 | key オブジェクトチェック | E-13 (L69-71) | ○ |
| C-103 | optionalKey 正常系 | E-13 (L54-66) | ○ |
| C-104 | optionalKey undefined | E-13 (L59-61) | ○ |
| C-105 | nullable null時 | E-13 (L88-124) | ○ |
| C-106 | nullable 非null時 | E-13 (L124) | ○ |
| C-107 | array 正常系 | E-13 (L200-205) | ○ |
| C-108 | array 型エラー | E-13 (L201-203) | ○ |
| C-109 | index 正常系 | E-13 (L207-216) | ○ |
| C-110 | index 範囲外 | E-13 (L212-214) | ○ |
| C-111 | index 負の値 | E-13 (L209-211) | ○ |
| C-112 | enum 正常系 | E-13 (L193-198) | ○ |
| C-113 | enum 不正値 | E-13 (L194-196) | ○ |

### WellknownService / MetadataService / IncomingRecommendation (UT-REC-114 〜 141)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-114 | WellknownService set | E-14 (L41-46) | ○ |
| C-115 | WellknownService ディレクトリ作成 | E-14 (L44) recursive: true | ○ |
| C-116 | getPath | E-14 (L33-35) | ○ |
| C-117 | getURL | E-14 (L37-39) | ○ |
| C-118 | #formatRecommendation | E-14 (L25-31) | ○ |
| C-119 | MetadataService Ghostサイト | E-15 (L84-115) | ○ |
| C-120 | MetadataService 一般サイト | E-15 (L117-127) | ○ |
| C-121 | MetadataService パス末尾スラッシュ | E-15 (L86-88) | ○ |
| C-122 | MetadataService フォールバック | E-15 (L96-102) | △ |
| C-123 | #castUrl 正常系 | E-15 (L73-82) | ○ |
| C-124 | #castUrl null | E-15 (L74-76) | ○ |
| C-125 | #castUrl 無効URL | E-15 (L78-81) | ○ |
| C-126 | IncomingRecommendationService list | E-16 (L146-159) | ○ |
| C-127 | IncomingRecommendationService デフォルト値 | E-16 (L147-148) | ○ |
| C-128 | sendRecommendationEmail | E-16 (L130-144) | ○ |
| C-129 | sendRecommendationEmail 無効Mention | E-16 (L132-134) | ○ |
| C-130 | #mentionToIncomingRecommendation | E-16 (L107-128) | ○ |
| C-131 | #mentionToIncomingRecommendation 相互レコメンド | E-16 (L112-113) | ○ |
| C-132 | #mentionToIncomingRecommendation エラー時 | E-16 (L124-127) | ○ |
| C-133 | IncomingRecommendationController browse | E-17 (L21-33) | ○ |
| C-134 | IncomingRecommendationController #serialize | E-17 (L35-50) | ○ |
| C-135 | EmailRenderer renderSubject | E-18 (L20-22) | ○ |
| C-136 | EmailRenderer renderHTML | E-18 (L24-29) | ○ |
| C-137 | EmailRenderer renderText | E-18 (L31-36) | ○ |
| C-138 | RecommendationClickEvent(Model) edit禁止 | E-02 (L7-11) | ○ |
| C-139 | RecommendationClickEvent(Model) destroy禁止 | E-02 (L13-17) | ○ |
| C-140 | RecommendationSubscribeEvent(Model) edit禁止 | E-03 (L7-11) | ○ |
| C-141 | RecommendationSubscribeEvent(Model) destroy禁止 | E-03 (L13-17) | ○ |

## 4) 不足情報(Unknown / Missing)

- **C-46, C-47: updateRecommendationsEnabledSetting の詳細動作**
  - RecommendationEnablerService の実装詳細が本解析の対象外
  - 候補: `ghost/core/core/server/services/recommendations/recommendation-enabler-service.js`

- **C-122: RecommendationMetadataService のフォールバック動作**
  - サブパスでのGhostサイト検出失敗時にルートへリトライする動作の詳細検証が必要
  - 実際の外部リクエストの挙動に依存

## 5) リスクフラグ(レビュー観点)

| リスクレベル | 項目 | 理由 |
|---|---|---|
| 1 (中) | C-46, C-47 | 設定管理の外部依存 |
| 1 (中) | C-122 | 外部HTTPリクエストの挙動依存 |
| 0 (低) | その他全て | ソースコードから直接確認可能 |

## 6) レビュアーチェックリスト(最小)

- [ ] バリデーションロジック(タイトル2000文字、説明200文字)の境界値テストが正確か
- [ ] URL重複チェックのwww/末尾スラッシュ正規化が網羅されているか
- [ ] 認証が必要なエンドポイント(trackSubscribed)のテストケースが適切か
- [ ] イベントモデル(ClickEvent, SubscribeEvent)の編集/削除禁止テストが含まれているか
- [ ] BookshelfRepositoryの基底クラスメソッドが全て網羅されているか
- [ ] UnsafeDataの全型変換メソッドのテストケースが網羅されているか
