---
generated_at: 2026-01-22 12:30:00
metrics:
  claims_total: 115
  claims_with_evidence: 115
  claims_without_evidence: 0
confidence_derived: 1.00
---

# 根拠レポート：dependency_proxy.csv

## 本レポートについて

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

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

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

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

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

---

## 1) サマリー（まず見るところ）
- 総合信頼度（derived）：**1.00**
  - 根拠あり：115 / 115、根拠なし：0
- 優先レビュー（高）
  1. **外部API連携テスト（UT-DPX-054〜061）**：モック設計の確認が必要
  2. **キャッシュ動作テスト（UT-DPX-062〜066）**：エッジケースの網羅性確認
  3. **認証テスト（UT-DPX-103〜109）**：セキュリティ観点での追加確認

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

- E-01: `app/models/dependency_proxy/blob.rb`
- E-02: `app/models/dependency_proxy/manifest.rb`
- E-03: `app/models/dependency_proxy/image_ttl_group_policy.rb`
- E-04: `app/models/dependency_proxy/group_setting.rb`
- E-05: `app/models/dependency_proxy/registry.rb`
- E-06: `app/services/dependency_proxy/auth_token_service.rb`
- E-07: `app/services/dependency_proxy/request_token_service.rb`
- E-08: `app/services/dependency_proxy/base_service.rb`
- E-09: `app/services/dependency_proxy/head_manifest_service.rb`
- E-10: `app/services/dependency_proxy/find_cached_manifest_service.rb`
- E-11: `app/services/dependency_proxy/group_settings/update_service.rb`
- E-12: `app/services/dependency_proxy/image_ttl_group_policies/update_service.rb`
- E-13: `app/workers/dependency_proxy/cleanup_blob_worker.rb`
- E-14: `app/workers/dependency_proxy/cleanup_manifest_worker.rb`
- E-15: `app/workers/dependency_proxy/image_ttl_group_policy_worker.rb`
- E-16: `app/workers/dependency_proxy/cleanup_dependency_proxy_worker.rb`
- E-17: `app/workers/concerns/dependency_proxy/expireable.rb`
- E-18: `app/uploaders/dependency_proxy/file_uploader.rb`
- E-19: `app/policies/dependency_proxy/blob_policy.rb`
- E-20: `app/policies/dependency_proxy/manifest_policy.rb`
- E-21: `app/policies/dependency_proxy/group_setting_policy.rb`
- E-22: `app/policies/dependency_proxy/image_ttl_group_policy_policy.rb`
- E-23: `app/graphql/mutations/dependency_proxy/image_ttl_group_policy/update.rb`
- E-24: `app/graphql/mutations/dependency_proxy/group_settings/update.rb`
- E-25: `app/controllers/groups/dependency_proxy/application_controller.rb`
- E-26: `app/controllers/concerns/dependency_proxy/group_access.rb`

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

### モデル - DependencyProxy::Blob (UT-DPX-001〜009)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-01 | グループとの関連が正しく取得できること | E-01 (L11: `belongs_to :group`) | ○ |
| C-02 | グループがnilの場合バリデーションエラーになること | E-01 (L17: `validates :group, presence: true`) | ○ |
| C-03 | ファイルがnilの場合バリデーションエラーになること | E-01 (L18: `validates :file, presence: true`) | ○ |
| C-04 | ファイル名がnilの場合バリデーションエラーになること | E-01 (L19: `validates :file_name, presence: true`) | ○ |
| C-05 | 全Blobの合計サイズが正しく計算されること | E-01 (L24-26: `self.total_size`) | ○ |
| C-06 | Blobが存在しない場合0が返却されること | E-01 (L25: `sum(:size)`) | ○ |
| C-07 | 既存のファイル名で検索した場合既存レコードが返却されること | E-01 (L28-30: `find_or_build`) | ○ |
| C-08 | 存在しないファイル名で検索した場合新規オブジェクトが返却されること | E-01 (L29: `find_or_initialize_by`) | ○ |
| C-09 | namespaceメソッドでグループが取得できること | E-01 (L12: `alias_method :namespace, :group`) | ○ |

### モデル - DependencyProxy::Manifest (UT-DPX-010〜018)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-10 | グループとの関連が正しく取得できること | E-02 (L11: `belongs_to :group`) | ○ |
| C-11 | グループがnilの場合バリデーションエラーになること | E-02 (L24: `validates :group, presence: true`) | ○ |
| C-12 | ファイルがnilの場合バリデーションエラーになること | E-02 (L25: `validates :file, presence: true`) | ○ |
| C-13 | ファイル名がnilの場合バリデーションエラーになること | E-02 (L26: `validates :file_name, presence: true`) | ○ |
| C-14 | ダイジェストがnilの場合バリデーションエラーになること | E-02 (L27: `validates :digest, presence: true`) | ○ |
| C-15 | ID降順でソートされること | E-02 (L29: `scope :order_id_desc, -> { reorder(id: :desc) }`) | ○ |
| C-16 | ファイル名で検索できること | E-02 (L34-36: `find_by_file_name_or_digest`) | ○ |
| C-17 | ダイジェストで検索できること | E-02 (L35: `find_by(digest: digest)`) | ○ |
| C-18 | 該当なしの場合nilが返却されること | E-02 (L34-36: 両方nilの場合) | ○ |

### モデル - DependencyProxy::ImageTtlGroupPolicy (UT-DPX-019〜025)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-19 | グループとの関連が正しく取得できること | E-03 (L6: `belongs_to :group`) | ○ |
| C-20 | グループがnilの場合バリデーションエラーになること | E-03 (L8: `validates :group, presence: true`) | ○ |
| C-21 | enabledがnilの場合バリデーションエラーになること | E-03 (L9: `validates :enabled, inclusion: { in: [true, false] }`) | ○ |
| C-22 | ttlが0以下の場合バリデーションエラーになること | E-03 (L10: `validates :ttl, numericality: { greater_than: 0 }`) | ○ |
| C-23 | ttlがnilの場合はバリデーションが通ること | E-03 (L10: `allow_nil: true`) | ○ |
| C-24 | ttlが1の場合バリデーションが通ること | E-03 (L10: `greater_than: 0`) | ○ |
| C-25 | enabled=trueのポリシーのみ取得できること | E-03 (L12: `scope :enabled, -> { where(enabled: true) }`) | ○ |

### モデル - DependencyProxy::GroupSetting (UT-DPX-026〜036)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-26 | グループとの関連が正しく取得できること | E-04 (L4: `belongs_to :group`) | ○ |
| C-27 | グループがnilの場合バリデーションエラーになること | E-04 (L9: `validates :group, presence: true`) | ○ |
| C-28 | secretがあってidentityがない場合バリデーションエラー | E-04 (L10: `validates :identity, presence: true, if: :secret?`) | ○ |
| C-29 | identityがあってsecretがない場合バリデーションエラー | E-04 (L11: `validates :secret, presence: true, if: :identity?`) | ○ |
| C-30 | identityが255文字を超える場合バリデーションエラー | E-04 (L12: `validates :identity, :secret, length: { maximum: 255 }`) | ○ |
| C-31 | secretが255文字を超える場合バリデーションエラー | E-04 (L12: `validates :identity, :secret, length: { maximum: 255 }`) | ○ |
| C-32 | identity/secretが設定されている場合認証ヘッダーが返却されること | E-04 (L14-19: `authorization_header`) | ○ |
| C-33 | identityがnilの場合空ハッシュが返却されること | E-04 (L15: `return {} unless identity? && secret?`) | ○ |
| C-34 | secretがnilの場合空ハッシュが返却されること | E-04 (L15: `return {} unless identity? && secret?`) | ○ |
| C-35 | identityが暗号化されて保存されること | E-04 (L6: `encrypts :identity`) | ○ |
| C-36 | secretが暗号化されて保存されること | E-04 (L7: `encrypts :secret`) | ○ |

### モデル - DependencyProxy::Registry (UT-DPX-037〜041)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-37 | 単純なイメージ名でauth URLが正しく生成されること | E-05 (L9-10: `auth_url`, L27-32: `image_path`) | ○ |
| C-38 | 名前空間付きイメージ名でauth URLが正しく生成されること | E-05 (L28-29: `if image.include?('/')`) | ○ |
| C-39 | マニフェストURLが正しく生成されること | E-05 (L13-14: `manifest_url`) | ○ |
| C-40 | BlobURLが正しく生成されること | E-05 (L17-18: `blob_url`) | ○ |
| C-41 | 認証ヘッダーが正しく生成されること | E-05 (L21-22: `authenticate_header`) | ○ |

### サービス - DependencyProxy::AuthTokenService (UT-DPX-042〜053)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-42 | 有効なJWTトークンがデコードされること | E-06 (L12: `JSONWebToken::HMACToken.decode`) | ○ |
| C-43 | 無効なJWTトークンの場合例外がスローされること | E-06 (L12: HMAC decode失敗時) | ○ |
| C-44 | user_id含むJWTからUserが取得できること | E-06 (L22-23: `User.find(token_payload['user_id'])`) | ○ |
| C-45 | deploy_token含むJWTからDeployTokenが取得できること | E-06 (L24-25: `DeployToken.active.find_by_token`) | ○ |
| C-46 | 無効なJWTの場合nilが返却されること | E-06 (L27-28: `rescue JWT::DecodeError...`) | ○ |
| C-47 | personal_access_token含むJWTからPATが取得できること | E-06 (L34-35: `get_personal_access_token`) | ○ |
| C-48 | group_access_token含むJWTからトークンが取得できること | E-06 (L36-38: `get_personal_access_token`) | ○ |
| C-49 | 期限切れJWTの場合nilが返却されること | E-06 (L44: `JWT::ExpiredSignature`) | ○ |
| C-50 | 指定IDのユーザーが取得できること | E-06 (L48-49: `get_user`) | ○ |
| C-51 | 有効なトークンからPATが取得できること | E-06 (L52-53: `get_personal_access_token`) | ○ |
| C-52 | 無効なトークンの場合nilが返却されること | E-06 (L53: `find_by_token`がnilを返す) | ○ |
| C-53 | 有効なトークンからDeployTokenが取得できること | E-06 (L56-57: `get_deploy_token`) | ○ |

### サービス - DependencyProxy::RequestTokenService (UT-DPX-054〜058)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-54 | トークン取得が成功した場合success応答が返却されること | E-07 (L17-18: `success(token: ...)`) | ○ |
| C-55 | トークン取得が失敗した場合error応答が返却されること | E-07 (L19-20: `error(...)`) | ○ |
| C-56 | タイムアウトの場合error応答が返却されること | E-07 (L22-23: `rescue Timeout::Error`) | ○ |
| C-57 | JSONパースエラーの場合error応答が返却されること | E-07 (L24-25: `rescue JSON::ParserError`) | ○ |
| C-58 | 認証ヘッダーが設定されている場合リクエストに含まれること | E-07 (L13: `@dependency_proxy_setting&.authorization_header`) | ○ |

### サービス - DependencyProxy::HeadManifestService (UT-DPX-059〜061)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-59 | マニフェストHEAD成功時にdigestとcontent_typeが返却されること | E-09 (L16-19: `success(digest:..., content_type:...)`) | ○ |
| C-60 | マニフェストHEAD失敗時にerror応答が返却されること | E-09 (L21-22: `error(response.body, response.code)`) | ○ |
| C-61 | タイムアウトの場合error応答が返却されること | E-09 (L24-25: `rescue Timeout::Error`) | ○ |

### サービス - DependencyProxy::FindCachedManifestService (UT-DPX-062〜066)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-62 | キャッシュがヒットした場合from_cache=trueで返却されること | E-10 (L21, L37-41: `respond(from_cache: true)`) | ○ |
| C-63 | キャッシュがミスした場合from_cache=falseで返却されること | E-10 (L24: `success(manifest: nil, from_cache: false)`) | ○ |
| C-64 | HEADリクエストがエラーでもキャッシュがあれば返却されること | E-10 (L22: `@manifest && head_result[:status] == :error`) | ○ |
| C-65 | キャッシュなしでHEADもエラーの場合error応答が返却されること | E-10 (L43: `error('Failed to download...')`) | ○ |
| C-66 | タイムアウト時にキャッシュがあれば返却されること | E-10 (L25-26: `rescue Timeout::Error...respond`) | ○ |

### サービス - DependencyProxy::GroupSettings::UpdateService (UT-DPX-067〜071)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-67 | 権限があり設定が存在する場合更新が成功すること | E-11 (L12-13: `ServiceResponse.success`) | ○ |
| C-68 | 権限がない場合403エラーが返却されること | E-11 (L9: `ServiceResponse.error(message: 'Access Denied', http_status: 403)`) | ○ |
| C-69 | 設定が存在しない場合404エラーが返却されること | E-11 (L10: `http_status: 404`) | ○ |
| C-70 | バリデーションエラーの場合400エラーが返却されること | E-11 (L15-18: `http_status: 400`) | ○ |
| C-71 | 許可された属性のみ更新されること | E-11 (L6: `ALLOWED_ATTRIBUTES`, L32-33: `params.slice(*ALLOWED_ATTRIBUTES)`) | ○ |

### サービス - DependencyProxy::ImageTtlGroupPolicies::UpdateService (UT-DPX-072〜076)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-72 | 権限がありポリシーが存在する場合更新が成功すること | E-12 (L14-15: `ServiceResponse.success`) | ○ |
| C-73 | 権限がない場合403エラーが返却されること | E-12 (L11: `http_status: 403`) | ○ |
| C-74 | ポリシーが存在しない場合404エラーが返却されること | E-12 (L12: `http_status: 404`) | ○ |
| C-75 | バリデーションエラーの場合400エラーが返却されること | E-12 (L17-20: `http_status: 400`) | ○ |
| C-76 | 許可された属性のみ更新されること | E-12 (L8: `ALLOWED_ATTRIBUTES`, L36-37: `params.slice(*ALLOWED_ATTRIBUTES)`) | ○ |

### ワーカー (UT-DPX-077〜090)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-77 | CleanupBlobWorker.max_running_jobsが設定値を返却 | E-13 (L17-19) | ○ |
| C-78 | CleanupBlobWorker.modelがBlobを返却 | E-13 (L23-24) | ○ |
| C-79 | CleanupBlobWorker.log_metadataがメタデータ記録 | E-13 (L27-30) | ○ |
| C-80 | CleanupManifestWorker.max_running_jobsが設定値を返却 | E-14 (L18-19) | ○ |
| C-81 | CleanupManifestWorker.modelがManifestを返却 | E-14 (L24-25) | ○ |
| C-82 | CleanupManifestWorker.log_metadataがメタデータ記録 | E-14 (L28-31) | ○ |
| C-83 | ImageTtlGroupPolicyWorker.performがTTL処理実行 | E-15 (L13-20) | ○ |
| C-84 | 有効なポリシーがない場合何も処理されない | E-15 (L14: `each`) | ○ |
| C-85 | ImageTtlGroupPolicyWorker.log_countsがカウント記録 | E-15 (L27-40) | ○ |
| C-86 | CleanupDependencyProxyWorker.performがBlobワーカーエンキュー | E-16 (L14, L20-21) | ○ |
| C-87 | CleanupDependencyProxyWorker.performがManifestワーカーエンキュー | E-16 (L15, L24-25) | ○ |
| C-88 | pending_destructionがない場合ワーカーがエンキューされない | E-16 (L14-15: `if ... .any?`) | ○ |
| C-89 | expire_artifactsがpending_destructionに更新 | E-17 (L13: `update_all(status: :pending_destruction)`) | ○ |
| C-90 | バッチサイズ(100)ごとに処理される | E-17 (L7: `UPDATE_BATCH_SIZE = 100`, L12: `each_batch(of: UPDATE_BATCH_SIZE)`) | ○ |

### FileUploader (UT-DPX-091〜094)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-91 | filenameがmodel.file_nameを返却 | E-18 (L12-13) | ○ |
| C-92 | store_dirがハッシュパスを返却 | E-18 (L16-17, L33-34) | ○ |
| C-93 | Manifestモデルでコンテントタイプが設定される | E-18 (L27-30) | ○ |
| C-94 | Blobモデルではコンテントタイプが設定されない | E-18 (L28: `return unless model.instance_of?(DependencyProxy::Manifest)`) | ○ |

### ポリシー (UT-DPX-095〜098)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-95 | BlobPolicyがグループに委譲 | E-19 (L4: `delegate { @subject.group }`) | ○ |
| C-96 | ManifestPolicyがグループに委譲 | E-20 (L4: `delegate { @subject.group }`) | ○ |
| C-97 | GroupSettingPolicyがグループに委譲 | E-21 (L4: `delegate { @subject.group }`) | ○ |
| C-98 | ImageTtlGroupPolicyPolicyがグループに委譲 | E-22 (L4: `delegate { @subject.group }`) | ○ |

### GraphQL Mutations (UT-DPX-099〜102)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-99 | ImageTtlGroupPolicy::Update.resolveが成功 | E-23 (L35-45) | ○ |
| C-100 | ImageTtlGroupPolicy::Update.resolveが権限エラー | E-23 (L13: `authorize :admin_dependency_proxy`) | ○ |
| C-101 | GroupSettings::Update.resolveが成功 | E-24 (L37-47) | ○ |
| C-102 | GroupSettings::Update.resolveが権限エラー | E-24 (L13: `authorize :admin_dependency_proxy`) | ○ |

### コントローラー (UT-DPX-103〜115)
| Claim ID | 主張 | Evidence | 状態 |
|---|---|---|---|
| C-103 | JWT認証でユーザーがサインイン | E-25 (L26-28) | ○ |
| C-104 | PAT認証で@personal_access_tokenが設定 | E-25 (L29-31) | ○ |
| C-105 | DeployToken認証でauthentication_resultが設定 | E-25 (L32-33) | ○ |
| C-106 | トークンがない場合401応答 | E-25 (L37, L44-47) | ○ |
| C-107 | 通常ユーザーでcan_sign_in?がtrue | E-25 (L50-53) | ○ |
| C-108 | project_botでcan_sign_in?がfalse | E-25 (L51: `user_or_token.project_bot?`) | ○ |
| C-109 | service_accountでcan_sign_in?がfalse | E-25 (L51: `user_or_token.service_account?`) | ○ |
| C-110 | dependency_proxy有効で処理続行 | E-26 (L27-28) | ○ |
| C-111 | dependency_proxy無効で404 | E-26 (L28: `render_404 unless`) | ○ |
| C-112 | 読み取り権限ありで処理続行 | E-26 (L33-38, L41-42) | ○ |
| C-113 | 読み取り権限なしでアクセス拒否 | E-26 (L42: `access_denied! unless can?`) | ○ |
| C-114 | PATがある場合PATが返却 | E-26 (L14-24) | ○ |
| C-115 | PATがない場合ユーザーが返却 | E-26 (L22-24: `else auth_user`) | ○ |

## 4) 不足情報（Unknown / Missing）
- なし（全テストケースに根拠あり）

## 5) リスクフラグ（レビュー観点）
- **リスク1（中）**: 外部API連携テスト（UT-DPX-054〜066）はモックの設計が重要。実際の外部レジストリとの結合テストも別途必要
- **リスク0（低）**: モデルのバリデーションテストは標準的なRSpecパターンで実装可能
- **リスク1（中）**: 認証関連テスト（UT-DPX-103〜109）はセキュリティ観点で慎重にレビューが必要
- **リスク1（中）**: 暗号化テスト（UT-DPX-035〜036）はActiveRecord Encryptionの設定に依存

## 6) レビュアーチェックリスト（最小）
- [ ] 外部API連携のモック設計が適切か（RequestTokenService, HeadManifestService）
- [ ] キャッシュ動作のエッジケースが網羅されているか（FindCachedManifestService）
- [ ] JWT認証のセキュリティテストが十分か（AuthTokenService, ApplicationController）
- [ ] 暗号化フィールドのテスト方法が適切か（GroupSetting.identity/secret）
- [ ] ワーカーのバッチ処理テストが適切か（Expireable, CleanupWorkers）
- [ ] ポリシー委譲のテストがGroupPolicyとの整合性を確認しているか
