# 機能設計書 113-プロジェクト管理

## 概要

本ドキュメントは、GitLab管理画面におけるプロジェクト管理機能の設計仕様を記述する。システム管理者が全プロジェクトの一覧表示、詳細閲覧、編集、移行、削除、リポジトリチェックを行うための機能である。

### 本機能の処理概要

**業務上の目的・背景**：GitLabインスタンスには多数のプロジェクトが存在し、システム管理者はそれらを一元的に管理する必要がある。プロジェクトの移行（名前空間変更）、削除、設定変更、リポジトリの整合性チェックなど、通常のプロジェクトオーナー権限では行えない管理操作をサポートする。

**機能の利用シーン**：
- 組織変更に伴うプロジェクトの名前空間移行
- 不要プロジェクトの強制削除
- プロジェクト設定の管理者による変更
- リポジトリの整合性チェック実行
- プロジェクトメンバーシップの確認

**主要な処理内容**：
1. プロジェクト一覧の表示
2. プロジェクト詳細情報の表示（メンバー、グループメンバー、アクセスリクエスト）
3. プロジェクトの編集（名前、説明、Runner登録設定）
4. プロジェクトの別名前空間への移行
5. プロジェクトの削除（非同期削除）
6. リポジトリチェックのトリガー

**関連システム・外部連携**：
- Gitalyサービス（リポジトリチェック）
- Runner登録トークンのリセット機能

**権限による制御**：
- 本機能は管理者（Admin）権限を持つユーザーのみがアクセス可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 236 | プロジェクト一覧 | 主画面 | 管理者向けプロジェクト一覧表示 |
| 237 | プロジェクト詳細 | 主画面 | プロジェクト詳細情報、メンバー表示 |
| 238 | プロジェクト編集 | 主画面 | プロジェクト設定編集フォーム |

## 機能種別

CRUD操作（Read/Update/Delete） / 移行処理 / 整合性チェック

## 入力仕様

### 入力パラメータ

#### プロジェクト編集時

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | No | プロジェクト名 | 文字列 |
| description | String | No | プロジェクト説明 | テキスト |
| runner_registration_enabled | Boolean | No | Runner登録許可 | true/false |

#### プロジェクト移行時

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| new_namespace_id | Integer | Yes | 移行先名前空間ID | 有効な名前空間ID |

### 入力データソース

- 画面入力（プロジェクト編集フォーム、移行先選択）
- URLパラメータ（プロジェクトパス: namespace_id/id）
- セッション情報（現在の管理者ユーザー）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| project | Project | プロジェクト詳細データ |
| project_members | Array[Member] | プロジェクトメンバー一覧 |
| group_members | Array[Member] | グループ経由のメンバー一覧 |
| requesters | Array[Member] | アクセスリクエスト一覧 |
| flash_message | String | 操作結果メッセージ |

### 出力先

- 画面表示（HTML）
- リダイレクト（操作完了後）
- トースト通知（削除時）

## 処理フロー

### 処理シーケンス

```
1. プロジェクト詳細表示（show）
   └─ Project.find_by_full_path → group → present_members → render
2. プロジェクト編集（edit/update）
   └─ Projects::UpdateService.new.execute → ResetRegistrationTokenService → redirect
3. プロジェクト移行（transfer）
   └─ Namespace.find_by → Projects::TransferService.new.execute → redirect
4. プロジェクト削除（destroy）
   └─ Projects::DestroyService.new.async_execute → redirect
5. リポジトリチェック（repository_check）
   └─ RepositoryCheck::SingleRepositoryWorker.perform_async → redirect
```

### フローチャート

```mermaid
flowchart TD
    A[管理者がプロジェクト管理画面にアクセス] --> B{操作種別}
    B -->|詳細表示| C[Project.find_by_full_path]
    C --> D[グループメンバー取得]
    D --> E[プロジェクトメンバー取得]
    E --> F[アクセスリクエスト取得]
    F --> G[詳細画面表示]

    B -->|編集| H[edit画面表示]
    H --> I[フォーム入力]
    I --> J[Projects::UpdateService.execute]
    J --> K{成功?}
    K -->|Yes| L{Runner登録無効化?}
    L -->|Yes| M[ResetRegistrationTokenService]
    M --> N[詳細へリダイレクト]
    L -->|No| N
    K -->|No| O[エラー表示]

    B -->|移行| P[Namespace.find_by]
    P --> Q[Projects::TransferService.execute]
    Q --> R{エラー?}
    R -->|Yes| S[エラーアラート表示]
    R -->|No| T[詳細へリダイレクト]

    B -->|削除| U[Projects::DestroyService.async_execute]
    U --> V{成功?}
    V -->|Yes| W[一覧へリダイレクト]
    V -->|No| X[エラーアラート表示]

    B -->|リポジトリチェック| Y[SingleRepositoryWorker.perform_async]
    Y --> Z[詳細へリダイレクト]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-113-01 | Runner登録トークンリセット | Runner登録を無効化した場合、登録トークンをリセットする | プロジェクト更新時にrunner_registration_enabled=false |
| BR-113-02 | 非同期削除 | プロジェクト削除は非同期で実行される | 削除操作時 |
| BR-113-03 | 移行エラー表示 | プロジェクト移行時のエラーはnew_namespaceエラーとしてアラート表示 | 移行操作失敗時 |
| BR-113-04 | フルパス指定 | プロジェクトはnamespace_id/idのフルパスで特定される | 全操作時 |

### 計算ロジック

特になし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 詳細表示 | projects, members, namespaces | SELECT | プロジェクト関連情報取得 |
| 更新 | projects | UPDATE | プロジェクト情報更新 |
| 移行 | projects, routes | UPDATE | 名前空間変更、ルート更新 |
| 削除 | projects, 関連テーブル多数 | DELETE | プロジェクトと関連データ削除（非同期） |

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

#### projectsテーブル

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, name, description, namespace_id等 | full_path指定 | routesテーブルと結合 |
| UPDATE | name, description, runner_registration_enabled | フォーム入力値 | |
| UPDATE | namespace_id | 移行先名前空間ID | TransferService経由 |
| DELETE | - | id指定 | 非同期実行 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | 存在しないリソース | 指定されたプロジェクトが見つからない | 404エラーページ表示 |
| 422 | バリデーションエラー | 入力値が不正 | エラーメッセージを表示して再入力を促す |
| - | 移行エラー | 移行先名前空間が無効、権限不足等 | new_namespaceエラーをアラート表示 |
| - | 削除エラー | 削除処理に失敗 | DestroyError例外をキャッチしてアラート表示 |

### リトライ仕様

- プロジェクト削除は非同期処理で実行され、`Projects::DestroyService`のワーカーによりリトライされる
- リポジトリチェックは`RepositoryCheck::SingleRepositoryWorker`で非同期実行

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

- プロジェクト更新はサービスクラス内で単一トランザクションとして処理
- プロジェクト移行はTransferService内でトランザクション管理
- プロジェクト削除は非同期処理のため、削除リクエストは即座にコミット

## パフォーマンス要件

- プロジェクトパス検索：`find_by_full_path`でルートテーブル経由の効率的な検索

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

- 管理者権限（Admin）が必須
- プロジェクト移行は任意の名前空間への移行が可能（管理者特権）

## 備考

- 本機能はEnterprise Edition（EE）で拡張される可能性があり、`prepend_mod_with`によりモジュールが追加される
- プロジェクト作成機能は管理画面には含まれない（通常のプロジェクト作成フローを使用）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | project.rb | `app/models/project.rb` | Projectモデルの属性、リレーションを理解 |

**読解のコツ**: Projectモデルは多くのモジュールをincludeしており、特に`Routable`（パス解決）、`Namespaced`（名前空間との関係）を確認する。

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

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

**主要処理フロー**:
1. **13-23行目**: `show`アクション - グループメンバー、プロジェクトメンバー、アクセスリクエスト取得
2. **26-33行目**: `destroy`アクション - 非同期削除、エラーハンドリング
3. **36-44行目**: `transfer`アクション - 名前空間移行、エラー表示
4. **49-61行目**: `update`アクション - プロジェクト更新、Runner登録トークンリセット
5. **64-71行目**: `repository_check`アクション - リポジトリチェックワーカー起動

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | update_service.rb | `app/services/projects/update_service.rb` | プロジェクト更新ロジック |
| 3-2 | transfer_service.rb | `app/services/projects/transfer_service.rb` | プロジェクト移行ロジック |
| 3-3 | destroy_service.rb | `app/services/projects/destroy_service.rb` | プロジェクト削除ロジック |

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

```
Admin::ProjectsController
    │
    ├─ show
    │      ├─ Project.find_by_full_path
    │      ├─ present_members(@group.members)
    │      ├─ present_members(@project.members)
    │      └─ AccessRequestsFinder
    │
    ├─ update
    │      ├─ Projects::UpdateService#execute
    │      └─ Ci::Runners::ResetRegistrationTokenService#execute
    │
    ├─ transfer
    │      ├─ Namespace.find_by(id:)
    │      └─ Projects::TransferService#execute
    │
    ├─ destroy
    │      └─ Projects::DestroyService#async_execute
    │
    └─ repository_check
           └─ RepositoryCheck::SingleRepositoryWorker.perform_async
```

### データフロー図

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

管理者操作 ───────▶ Admin::ProjectsController ──────▶ HTMLレスポンス
  │                      │                              │
  │                      ▼                              │
  │              Projects::*Service                     │
  │                      │                              │
  │                      ▼                              │
  │               Project Model                         │
  │                      │                              │
  └──────────────▶ projects テーブル ────────────────▶ トースト通知
                         │
                         ▼
                  Gitalyサービス
             (リポジトリチェック時)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| projects_controller.rb | `app/controllers/admin/projects_controller.rb` | コントローラー | プロジェクト管理のエントリーポイント |
| project.rb | `app/models/project.rb` | モデル | プロジェクトデータモデル |
| update_service.rb | `app/services/projects/update_service.rb` | サービス | プロジェクト更新ロジック |
| transfer_service.rb | `app/services/projects/transfer_service.rb` | サービス | プロジェクト移行ロジック |
| destroy_service.rb | `app/services/projects/destroy_service.rb` | サービス | プロジェクト削除ロジック |
| reset_registration_token_service.rb | `app/services/ci/runners/reset_registration_token_service.rb` | サービス | Runner登録トークンリセット |
| single_repository_worker.rb | `app/workers/repository_check/single_repository_worker.rb` | ワーカー | リポジトリチェック非同期処理 |
