# 機能設計書 57-デプロイキー管理

## 概要

本ドキュメントは、GitLabリポジトリへのアクセス用SSH鍵（デプロイキー）の管理機能について記述した機能設計書である。

### 本機能の処理概要

デプロイキー管理機能は、CI/CDパイプラインや外部システムからリポジトリにアクセスするためのSSH公開鍵を登録・管理する機能である。

**業務上の目的・背景**：CI/CDパイプラインや外部サーバーからGitリポジトリをクローン・プッシュする際、ユーザーの個人SSH鍵を使用するのはセキュリティ上望ましくない。デプロイキーを使用することで、特定の用途に限定したアクセス権を付与でき、必要に応じて取り消しも容易に行える。

**機能の利用シーン**：
- CI/CDパイプラインからリポジトリをクローンする場合
- 外部デプロイサーバーからコードを取得する場合
- 複数プロジェクトで共通のデプロイキーを使用する場合
- 読み取り専用または書き込み可能なアクセスを設定する場合
- デプロイキーの有効期限を設定する場合

**主要な処理内容**：
1. デプロイキーの作成（SSH公開鍵の登録）
2. デプロイキーの編集（タイトル、権限）
3. デプロイキーの有効化/無効化
4. デプロイキー一覧の表示（有効/利用可能/公開）
5. デプロイキーの削除

**関連システム・外部連携**：
- SSH認証システム
- Gitリポジトリ
- 他のGitLabプロジェクト（公開デプロイキーの共有）

**権限による制御**：
- デプロイキー管理: `admin_project`権限が必要
- デプロイキー編集: `update_deploy_key`または`update_deploy_keys_project`権限が必要
- タイトル編集: `update_deploy_key_title`権限が必要

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 111 | リポジトリ設定 | 主画面 | デプロイキー設定の管理 |
| 123 | デプロイキー編集 | 主画面 | デプロイキーの編集 |

## 機能種別

CRUD操作 / SSH鍵管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | String | Yes（作成時） | SSH公開鍵 | 形式チェック |
| title | String | Yes（作成時） | デプロイキーのタイトル | - |
| can_push | Boolean | No | 書き込み権限の有無 | - |
| expires_at | Date | No | 有効期限 | - |

### 入力データソース

- 画面入力（デプロイキー設定フォーム）
- APIリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | デプロイキーID |
| title | String | タイトル |
| key | String | SSH公開鍵（マスク表示） |
| fingerprint | String | 鍵のフィンガープリント |
| can_push | Boolean | 書き込み権限 |
| created_at | DateTime | 作成日時 |
| expires_at | Date | 有効期限 |

### 出力先

- 画面表示（デプロイキー一覧）
- JSONレスポンス（API）
- リダイレクト（リポジトリ設定画面）

## 処理フロー

### 処理シーケンス

```
1. 認証・権限チェック
   └─ admin_project 権限の確認

2. 操作種別の判定
   └─ 作成/編集/有効化/無効化/削除

3. サービス/モデル操作
   └─ 該当する処理を実行

4. レスポンス生成
   └─ リダイレクトまたはJSONレスポンス
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{admin_project権限?}
    B -->|No| C[アクセス拒否]
    B -->|Yes| D{操作種別}
    D -->|作成| E[CreateService実行]
    D -->|編集| F{update権限?}
    D -->|有効化| G[EnableService実行]
    D -->|無効化| H[DisableService実行]
    F -->|No| C
    F -->|Yes| I[DeployKey更新]
    E --> J{成功?}
    I --> J
    G --> J
    H --> J
    J -->|Yes| K[リポジトリ設定へリダイレクト]
    J -->|No| L[エラー表示]
    K --> M[終了]
    L --> M
    C --> M
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-57-01 | 公開鍵形式 | SSH公開鍵形式（ssh-rsa, ssh-ed25519等）のみ受け付け | 作成時 |
| BR-57-02 | プライベート/パブリック | デプロイキーはprivate（単一プロジェクト）またはpublic（共有可能）| 作成時 |
| BR-57-03 | 孤児キー削除 | プライベートキーでプロジェクト関連がなくなると自動削除 | 無効化時 |
| BR-57-04 | 書き込み権限 | can_push=trueでリポジトリへのプッシュが可能 | 操作時 |
| BR-57-05 | 保護ブランチ連携 | デプロイキーを保護ブランチのプッシュアクセスに設定可能 | 設定時 |

### 計算ロジック

- fingerprint_sha256: 公開鍵のSHA256ハッシュ（Base64エンコード）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| デプロイキー作成 | keys | INSERT | 新規デプロイキーレコード作成 |
| デプロイキー作成 | deploy_keys_projects | INSERT | プロジェクトとの関連作成 |
| デプロイキー編集 | keys | UPDATE | タイトル等の更新 |
| デプロイキー編集 | deploy_keys_projects | UPDATE | can_pushの更新 |
| 有効化 | deploy_keys_projects | INSERT | プロジェクトとの関連作成 |
| 無効化 | deploy_keys_projects | DELETE | プロジェクトとの関連削除 |

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

#### keys（deploy_keysとして継承）

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | key | SSH公開鍵 | - |
| INSERT | title | ユーザー入力値 | - |
| INSERT | fingerprint_sha256 | 自動計算 | - |
| INSERT | public | true/false | 共有可能かどうか |
| UPDATE | title | 新しいタイトル | update_deploy_key_title権限が必要 |

#### deploy_keys_projects

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | deploy_key_id | デプロイキーID | - |
| INSERT | project_id | プロジェクトID | - |
| INSERT | can_push | true/false | 書き込み権限 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 権限不足 | Maintainer以上の権限を取得 |
| 404 | Not Found | デプロイキー未検出 | 正しいIDを確認 |
| 422 | Validation Error | 無効な公開鍵形式 | 正しいSSH公開鍵を入力 |

### リトライ仕様

- 作成/編集失敗時は自動リトライなし

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

- デプロイキー作成時はkeyとdeploy_keys_projectsを同一トランザクションで作成
- 孤児キー削除もトランザクション内で実行

## パフォーマンス要件

- デプロイキー一覧取得: 1秒以内
- デプロイキー作成/編集: 1秒以内

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

- 秘密鍵は保存しない（公開鍵のみ）
- フィンガープリントによる鍵の一意性確認
- プロジェクト単位での権限チェック
- 有効期限による自動無効化

## 備考

- DeployKeyはKeyモデルを継承（STI: Single Table Inheritance）
- 検索はタイトルまたは鍵（Base64エンコードしたfingerprint_sha256）で可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | deploy_key.rb | `app/models/deploy_key.rb` | デプロイキーの属性、関連、スコープを理解する |

**読解のコツ**:
- **9行目**: `self.allow_legacy_sti_class = true` でSTI継承を確認
- **11-18行目**: has_many関連でプロジェクトとの関係を確認
- **42-47行目**: `private?`, `orphaned?`, `almost_orphaned?` で状態判定ロジックを確認
- **66-79行目**: プロジェクトへのアクセス権チェックロジックを確認
- **100-111行目**: 検索メソッドの実装を確認

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | deploy_keys_controller.rb | `app/controllers/projects/deploy_keys_controller.rb` | 各アクションの処理フローを確認 |

**主要処理フロー**:
- **9-10行目**: before_actionで権限チェック
- **17-24行目**: indexアクションでJSON形式で一覧返却
- **26-52行目**: enabled_keys, available_project_keys, available_public_keysで種類別一覧
- **58-63行目**: createアクションでCreateServiceを呼び出し
- **68-76行目**: updateアクションでデプロイキー更新
- **79-88行目**: enableアクションでEnableService呼び出し
- **90-98行目**: disableアクションでDisableService呼び出し

#### Step 3: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb | `app/services/deploy_keys/create_service.rb` | デプロイキー作成のビジネスロジック |

**主要処理フロー**:
- **5-6行目**: executeメソッドでDeployKey.createを呼び出し

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

```
Projects::DeployKeysController
    │
    ├─ #index / #enabled_keys / #available_*
    │      └─ DeployKeys::DeployKeysFinder#execute
    │
    ├─ #create
    │      └─ DeployKeys::CreateService#execute
    │
    ├─ #update
    │      └─ deploy_key.update
    │
    ├─ #enable
    │      └─ Projects::EnableDeployKeyService#execute
    │
    └─ #disable
           └─ Projects::DisableDeployKeyService#execute
```

### データフロー図

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

SSH公開鍵
設定フォーム ───▶ DeployKeysController ───▶ リポジトリ設定画面
                      │
                      ▼
              DeployKey (Model)
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
        keys   deploy_keys_  protected_
       テーブル   projects    branches
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| deploy_key.rb | `app/models/deploy_key.rb` | モデル | デプロイキーのデータモデル |
| deploy_keys_controller.rb | `app/controllers/projects/deploy_keys_controller.rb` | コントローラー | デプロイキー操作のエンドポイント |
| create_service.rb | `app/services/deploy_keys/create_service.rb` | サービス | デプロイキー作成ロジック |
| enable_deploy_key_service.rb | `app/services/projects/enable_deploy_key_service.rb` | サービス | デプロイキー有効化ロジック |
| disable_deploy_key_service.rb | `app/services/projects/disable_deploy_key_service.rb` | サービス | デプロイキー無効化ロジック |
| deploy_keys_project.rb | `app/models/deploy_keys_project.rb` | モデル | デプロイキーとプロジェクトの関連 |
