# 機能設計書 58-デプロイトークン管理

## 概要

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

### 本機能の処理概要

デプロイトークン管理機能は、CI/CDパイプラインや外部システムからリポジトリ、コンテナレジストリ、パッケージレジストリにアクセスするためのトークンを発行・管理する機能である。

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

**機能の利用シーン**：
- CI/CDパイプラインからリポジトリをHTTPS経由でクローンする場合
- コンテナレジストリへのイメージプッシュ/プルを自動化する場合
- パッケージレジストリからパッケージを取得する場合
- 外部システムからGitLabリソースにアクセスする場合
- プロジェクト単位またはグループ単位でアクセス権を管理する場合

**主要な処理内容**：
1. デプロイトークンの作成（スコープ指定）
2. デプロイトークンの失効（Revoke）
3. デプロイトークン一覧の表示
4. 有効期限管理と期限切れ通知

**関連システム・外部連携**：
- Git HTTPS認証
- コンテナレジストリ
- パッケージレジストリ
- 仮想レジストリ（Virtual Registry）

**権限による制御**：
- デプロイトークン管理: `destroy_deploy_token`権限が必要
- グループトークン管理: グループオーナー権限が必要

## 関連画面

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

## 機能種別

CRUD操作 / トークン管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | トークン名 | 最大255文字 |
| expires_at | Date | No | 有効期限 | ISO8601形式 |
| username | String | No | カスタムユーザー名 | 英数字と`._+-`のみ、最大255文字 |
| read_repository | Boolean | No | リポジトリ読み取りスコープ | - |
| read_registry | Boolean | No | レジストリ読み取りスコープ | - |
| write_registry | Boolean | No | レジストリ書き込みスコープ | - |
| read_package_registry | Boolean | No | パッケージ読み取りスコープ | - |
| write_package_registry | Boolean | No | パッケージ書き込みスコープ | - |
| read_virtual_registry | Boolean | No | 仮想レジストリ読み取りスコープ | - |
| write_virtual_registry | Boolean | No | 仮想レジストリ書き込みスコープ | - |

### 入力データソース

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

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | デプロイトークンID |
| name | String | トークン名 |
| username | String | ユーザー名（デフォルト: `gitlab+deploy-token-{id}`） |
| token | String | トークン値（作成時のみ表示） |
| scopes | Array | 有効なスコープ一覧 |
| expires_at | Date | 有効期限 |
| revoked | Boolean | 失効状態 |
| created_at | DateTime | 作成日時 |

### 出力先

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

## 処理フロー

### 処理シーケンス

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

2. 操作種別の判定
   └─ 作成/失効/削除

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

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

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{destroy_deploy_token権限?}
    B -->|No| C[アクセス拒否]
    B -->|Yes| D{操作種別}
    D -->|作成| E[CreateService実行]
    D -->|失効| F[revoke!実行]
    E --> G{成功?}
    F --> G
    G -->|Yes| H[リポジトリ設定へリダイレクト]
    G -->|No| I[エラー表示]
    H --> J[終了]
    I --> J
    C --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-58-01 | スコープ必須 | 最低1つのスコープが必要 | 作成時 |
| BR-58-02 | トークンプレフィックス | トークンは`gldt-`プレフィックスで始まる | 作成時 |
| BR-58-03 | 有効期限デフォルト | 有効期限未指定時は無期限（Forever.date） | 作成時 |
| BR-58-04 | 失効後アクセス不可 | revokedまたは期限切れのトークンは認証不可 | 認証時 |
| BR-58-05 | プロジェクト/グループ型 | トークンはproject_typeまたはgroup_typeのいずれか | 作成時 |
| BR-58-06 | gitlab-deploy-token | 特別なトークン名で自動検出可能 | 設定時 |

### 計算ロジック

- `active?`: revoked=false AND expires_at >= NOW()
- `username`: カスタム値または `gitlab+deploy-token-{id}`
- `scopes`: AVAILABLE_SCOPESのうち有効なものを返却

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| トークン作成 | deploy_tokens | INSERT | 新規トークンレコード作成 |
| トークン作成 | project_deploy_tokens | INSERT | プロジェクトとの関連作成 |
| トークン失効 | deploy_tokens | UPDATE | revoked=trueに更新 |

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

#### deploy_tokens

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | ユーザー入力値 | 最大255文字 |
| INSERT | token_encrypted | 暗号化トークン | 自動生成 |
| INSERT | deploy_token_type | 1(group) or 2(project) | - |
| INSERT | expires_at | 入力値またはForever.date | - |
| INSERT | creator_id | 現在のユーザーID | 監査用 |
| UPDATE | revoked | true | 失効時 |

#### project_deploy_tokens

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | deploy_token_id | デプロイトークンID | - |
| INSERT | project_id | プロジェクトID | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | 権限不足 | Maintainer以上の権限を取得 |
| 404 | Not Found | トークン未検出 | 正しいIDを確認 |
| 422 | Validation Error | スコープ未指定 | 最低1つのスコープを選択 |
| 422 | Validation Error | ユーザー名形式不正 | 英数字と許可文字のみ使用 |

### リトライ仕様

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

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

- トークン作成時はdeploy_tokensとproject_deploy_tokensを同一トランザクションで作成
- 失効処理は単一UPDATE操作

## パフォーマンス要件

- トークン一覧取得: 1秒以内
- トークン作成/失効: 1秒以内

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

- トークン値は作成時のみ表示（以後は取得不可）
- トークンは暗号化して保存（`token_encrypted`）
- プロジェクト/グループ単位での権限チェック
- 有効期限による自動無効化
- 期限切れ前の通知機能（7日、30日、60日前）

## 備考

- AVAILABLE_SCOPES: read_repository, read_registry, write_registry, read_package_registry, write_package_registry, read_virtual_registry, write_virtual_registry
- GITLAB_DEPLOY_TOKEN_NAME: `gitlab-deploy-token`（特別なトークン名で自動検出）
- DEPLOY_TOKEN_PREFIX: `gldt-`

---

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

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

### 推奨読解順序

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

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

**読解のコツ**:
- **9-11行目**: `AVAILABLE_SCOPES`で利用可能な全スコープを確認
- **12-13行目**: 特別なトークン名とプレフィックスを確認
- **15-19行目**: `NOTIFICATION_INTERVALS`で通知間隔を確認
- **21行目**: `add_authentication_token_field`でトークン暗号化を確認
- **50-53行目**: `enum :deploy_token_type`でトークン種別を確認
- **59行目**: `scope :active`でアクティブ判定条件を確認
- **103-105行目**: `revoke!`メソッドで失効処理を確認
- **107-109行目**: `active?`メソッドで有効性判定ロジックを確認
- **115-117行目**: `scopes`メソッドで有効スコープ取得ロジックを確認

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

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

**主要処理フロー**:
- **4行目**: before_actionで`authorize_destroy_deploy_token!`権限チェック
- **9-14行目**: revokeアクションでトークン失効とリダイレクト

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb | `app/services/projects/deploy_tokens/create_service.rb` | トークン作成のビジネスロジック |
| 3-2 | revoke_service.rb | `app/services/projects/deploy_tokens/revoke_service.rb` | トークン失効のサービス（API用） |
| 3-3 | deploy_token_methods.rb | `app/services/concerns/deploy_token_methods.rb` | 共通メソッド |

**主要処理フロー**:
- **create_service.rb 8-11行目**: `create_deploy_token_for`でトークン作成
- **revoke_service.rb 8-18行目**: 権限チェック後に`revoke!`呼び出し
- **deploy_token_methods.rb 4-13行目**: トークン作成の共通ロジック

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

```
Projects::DeployTokensController
    │
    └─ #revoke
           ├─ project.deploy_tokens.find
           └─ deploy_token.revoke!

Projects::DeployTokens::CreateService
    │
    └─ #execute
           └─ DeployTokenMethods#create_deploy_token_for
                  └─ entity.deploy_tokens.create

Projects::DeployTokens::RevokeService (API用)
    │
    └─ #execute
           ├─ can_revoke_token? (権限チェック)
           └─ deploy_token.revoke!
```

### データフロー図

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

トークン作成
フォーム ───────▶ CreateService ───────────▶ トークン表示（1回のみ）
                      │
                      ▼
              DeployToken (Model)
                      │
          ┌───────────┼───────────┐
          ▼           ▼           ▼
    deploy_tokens  project_    group_
      テーブル    deploy_tokens deploy_tokens
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| deploy_token.rb | `app/models/deploy_token.rb` | モデル | デプロイトークンのデータモデル |
| deploy_tokens_controller.rb | `app/controllers/projects/deploy_tokens_controller.rb` | コントローラー | revokeアクションのエンドポイント |
| create_service.rb | `app/services/projects/deploy_tokens/create_service.rb` | サービス | トークン作成ロジック |
| revoke_service.rb | `app/services/projects/deploy_tokens/revoke_service.rb` | サービス | トークン失効ロジック |
| deploy_token_methods.rb | `app/services/concerns/deploy_token_methods.rb` | Concern | 作成/削除の共通メソッド |
| tokens_finder.rb | `app/finders/deploy_tokens/tokens_finder.rb` | Finder | トークン検索ロジック |
| expiring_worker.rb | `app/workers/deploy_tokens/expiring_worker.rb` | Worker | 期限切れ通知ワーカー |
| project_deploy_token.rb | `app/models/project_deploy_token.rb` | モデル | プロジェクトとトークンの関連 |
| group_deploy_token.rb | `app/models/group_deploy_token.rb` | モデル | グループとトークンの関連 |
