# 機能設計書 1-プロジェクト作成

## 概要

本ドキュメントは、GitLabにおける新規プロジェクト作成機能の詳細設計を記述する。この機能は、ユーザーが新しいプロジェクトを作成し、名前、説明、可視性レベル（Private/Internal/Public）などの基本設定を行うための中核機能である。

### 本機能の処理概要

プロジェクト作成機能は、GitLabのバージョン管理およびコラボレーションプラットフォームにおいて、ソフトウェア開発プロジェクトを開始するための最初のステップを提供する。

**業務上の目的・背景**：ソフトウェア開発において、コードの管理・共有・コラボレーションを行うためには、まずプロジェクト（リポジトリ）を作成する必要がある。この機能により、開発チームは即座にバージョン管理を開始し、CI/CD、イシュー管理、コードレビューなどのGitLabの豊富な機能を活用できる基盤を得る。

**機能の利用シーン**：
- 新規ソフトウェア開発プロジェクトの立ち上げ時
- 既存プロジェクトをテンプレートとして新プロジェクトを作成する時
- 外部リポジトリ（GitHub、Bitbucketなど）からプロジェクトをインポートする時
- オープンソースプロジェクトを公開リポジトリとして作成する時

**主要な処理内容**：
1. ユーザー入力の検証（プロジェクト名、パス、可視性レベルなど）
2. 名前空間（ユーザー個人またはグループ）の指定と権限チェック
3. プロジェクトレコードのデータベース作成
4. Gitリポジトリの初期化
5. プロジェクト機能設定（Wiki、イシュー、マージリクエストなど）の適用
6. オーナー権限の付与とメンバーシップ設定
7. デフォルトインテグレーション（連携設定）の適用
8. システムフックの実行（プロジェクト作成イベントの通知）

**関連システム・外部連携**：
- Gitaly（Gitリポジトリ管理サーバー）
- インテグレーション（Slack、Jiraなど）のデフォルト設定
- Container Registry（コンテナイメージ保存）
- Pages（静的サイトホスティング）

**権限による制御**：
- グループへのプロジェクト作成には、グループへのDeveloper以上のロールが必要
- 個人名前空間へのプロジェクト作成は、ユーザー自身のみ可能
- 可視性レベルは名前空間の可視性レベル以下に制限される
- インスタンス設定により、プロジェクト作成権限自体が制限される場合がある

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 25 | プロジェクト新規作成 | 主画面 | 新規プロジェクトの作成処理 |
| 24 | プロジェクト詳細 | 結果表示画面 | プロジェクトトップページ・概要表示 |

## 機能種別

CRUD操作（Create）/ データ連携 / バリデーション

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | プロジェクト名 | 空白不可、255文字以内 |
| path | String | No | プロジェクトパス（URL用） | 英数字・ハイフン・アンダースコア、pathが未指定の場合はnameから自動生成 |
| namespace_id | Integer | No | 所属する名前空間ID | 指定しない場合はユーザー個人名前空間 |
| description | String | No | プロジェクト説明 | 2000文字以内 |
| visibility_level | Integer | No | 可視性レベル（0:Private, 10:Internal, 20:Public） | 名前空間の可視性以下である必要あり |
| initialize_with_readme | Boolean | No | README.mdを初期作成するか | - |
| initialize_with_sast | Boolean | No | SASTを初期設定するか | - |
| initialize_with_secret_detection | Boolean | No | シークレット検出を初期設定するか | - |
| import_url | String | No | インポート元リポジトリURL | 有効なGit URL形式 |
| template_name | String | No | テンプレート名 | 有効なテンプレート名 |
| template_project_id | Integer | No | テンプレートプロジェクトID | 存在するプロジェクトID |
| avatar | File | No | プロジェクトアバター画像 | 画像ファイル形式 |

### 入力データソース

- 画面入力（Web UI）
- API リクエスト（REST API / GraphQL）
- インポート処理からの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| project | Project | 作成されたプロジェクトオブジェクト |
| project.id | Integer | プロジェクトID |
| project.full_path | String | プロジェクトのフルパス |
| project.web_url | String | プロジェクトのWeb URL |
| errors | Array | エラーメッセージ配列（失敗時） |

### 出力先

- データベース（projectsテーブル、関連テーブル）
- Gitリポジトリ（Gitalyサーバー上）
- 画面リダイレクト（成功時は作成されたプロジェクトページへ）
- システムフック（外部通知）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受付（ProjectsController#create）
   └─ パラメータのサニタイズとパーミッション確認

2. サービス呼び出し（Projects::CreateService#execute）
   └─ ビジネスロジックの実行開始

3. テンプレート判定
   └─ テンプレート使用時はProjects::CreateFromTemplateServiceへ委譲

4. プロジェクトインスタンス生成
   └─ Project.newでオブジェクト生成、属性設定

5. バリデーション実行
   ├─ インポートソース有効性確認
   ├─ 可視性レベル制限確認
   ├─ 名前空間権限確認
   └─ 個人プロジェクト制限確認

6. データベース保存（トランザクション内）
   ├─ プロジェクトネームスペース作成
   ├─ プロジェクトレコード保存
   ├─ インテグレーション設定コピー
   └─ ラベル作成（インポート以外）

7. リポジトリ作成
   └─ Gitalyを通じてGitリポジトリ初期化

8. 作成後処理（after_create_actions）
   ├─ ログ記録
   ├─ Wiki作成（有効時）
   ├─ プロジェクト設定保存
   ├─ イベント記録
   ├─ システムフック実行
   ├─ 権限設定（オーナー追加）
   ├─ README作成（オプション）
   ├─ SAST設定（オプション）
   └─ イベント発行

9. レスポンス返却
   └─ 成功時：プロジェクトページへリダイレクト
      失敗時：エラーメッセージ表示
```

### フローチャート

```mermaid
flowchart TD
    A[開始: create リクエスト受付] --> B{認証済み?}
    B -->|No| C[認証エラー]
    B -->|Yes| D{テンプレート使用?}
    D -->|Yes| E[CreateFromTemplateService]
    D -->|No| F[プロジェクトインスタンス生成]
    F --> G{可視性レベル許可?}
    G -->|No| H[可視性エラー]
    G -->|Yes| I{名前空間権限あり?}
    I -->|No| J[権限エラー]
    I -->|Yes| K{個人プロジェクト制限?}
    K -->|制限超過| L[制限エラー]
    K -->|OK| M[トランザクション開始]
    M --> N[プロジェクト保存]
    N --> O{保存成功?}
    O -->|No| P[保存エラー]
    O -->|Yes| Q[リポジトリ作成]
    Q --> R{リポジトリ作成成功?}
    R -->|No| S[ロールバック]
    R -->|Yes| T[作成後処理]
    T --> U[システムフック実行]
    U --> V[成功レスポンス]

    C --> W[終了]
    E --> W
    H --> W
    J --> W
    L --> W
    P --> W
    S --> W
    V --> W
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 名前空間可視性継承 | プロジェクトの可視性は名前空間の可視性を超えられない | プロジェクト作成時 |
| BR-002 | 個人プロジェクト制限 | ユーザーには個人プロジェクト数の上限がある場合がある | 個人名前空間への作成時 |
| BR-003 | 共有ランナー継承 | グループ内プロジェクトはグループの共有ランナー設定を継承 | グループへの作成時 |
| BR-004 | パス自動生成 | パス未指定時はプロジェクト名からパスを自動生成 | pathパラメータ未指定時 |
| BR-005 | テンプレート優先 | テンプレート指定時は専用サービスで処理 | template_nameまたはtemplate_project_id指定時 |

### 計算ロジック

可視性レベル決定ロジック：
```ruby
# 名前空間の可視性レベルを超えない範囲で設定
visibility_level = [project.visibility_level, namespace.visibility_level].min
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| プロジェクト作成 | projects | INSERT | プロジェクトレコード作成 |
| ネームスペース作成 | namespaces | INSERT | プロジェクトネームスペース作成 |
| 機能設定作成 | project_features | INSERT | プロジェクト機能設定 |
| CI/CD設定作成 | project_ci_cd_settings | INSERT | CI/CD関連設定 |
| 統計レコード作成 | project_statistics | INSERT | プロジェクト統計情報 |
| メンバー追加 | members | INSERT | オーナーメンバーシップ |
| 権限設定 | project_authorizations | INSERT | プロジェクトアクセス権限 |
| インテグレーション | integrations | INSERT | デフォルトインテグレーション |
| ラベル作成 | labels | INSERT | デフォルトラベル |
| ルート作成 | routes | INSERT | URLルーティング情報 |

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

#### projects

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | 入力値またはpathから生成 | プロジェクト名 |
| INSERT | path | 入力値またはnameから生成 | URLパス |
| INSERT | namespace_id | 指定値または個人名前空間ID | 所属名前空間 |
| INSERT | creator_id | current_user.id | 作成者 |
| INSERT | visibility_level | 入力値（制限適用後） | 可視性 |
| INSERT | description | 入力値 | 説明 |
| INSERT | repository_storage | デフォルトストレージ | リポジトリ保存先 |
| INSERT | runners_token | 自動生成 | CI Runner用トークン |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E001 | 権限エラー | 名前空間への作成権限なし | 適切な権限を持つ名前空間を選択 |
| E002 | バリデーションエラー | 必須項目未入力 | 必須項目を入力 |
| E003 | 可視性エラー | 名前空間の可視性を超える設定 | 可視性レベルを下げる |
| E004 | 重複エラー | 同一パスのプロジェクトが存在 | 異なるパスを指定 |
| E005 | 制限エラー | 個人プロジェクト数上限超過 | 既存プロジェクトを削除またはグループに作成 |
| E006 | インポートソースエラー | 無効なインポートソース指定 | 有効なインポートソースを指定 |
| E007 | リポジトリエラー | Gitリポジトリ作成失敗 | Gitalyサーバーの状態確認 |

### リトライ仕様

- リポジトリ作成失敗時：トランザクションロールバック、手動リトライ必要
- 非同期処理（PostCreationWorker）は自動リトライあり

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

- プロジェクト作成はデータベーストランザクション内で実行
- プロジェクトネームスペース、プロジェクト本体、関連設定が一括でコミット
- リポジトリ作成失敗時はロールバック
- 作成後処理（after_create_actions）はコミット後に実行

## パフォーマンス要件

- プロジェクト作成処理は通常3秒以内に完了
- 大規模テンプレートからの作成時は非同期処理
- リポジトリ初期化はGitalyへの同期呼び出し

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

- ユーザー認証必須
- 名前空間への作成権限チェック
- 可視性レベルの制限適用
- runners_tokenの暗号化保存
- インポートURLのプロトコル・ポート検証
- 監査ログへの記録

## 備考

- テンプレートプロジェクトからの作成は別サービス（CreateFromTemplateService）で処理
- インポート処理は非同期で実行される
- システムフックにより外部システムへの通知が可能

---

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

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

### 推奨読解順序

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

まず、プロジェクトモデルの構造とリレーションを理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | project.rb | `app/models/project.rb` | Projectモデルの属性、バリデーション、リレーション定義 |
| 1-2 | project_feature.rb | `app/models/project_feature.rb` | プロジェクト機能設定の構造 |
| 1-3 | namespace.rb | `app/models/namespace.rb` | 名前空間の構造と継承関係 |

**読解のコツ**: Projectモデルは多数のモジュールをincludeしているため、まずbelongs_to/has_manyリレーションを把握し、その後attribute定義とcallbackを確認する。

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

処理の起点となるコントローラーを特定。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | projects_controller.rb | `app/controllers/projects_controller.rb` | createアクションの実装 |

**主要処理フロー**:
1. **114-125行目**: createアクションの定義、CreateServiceの呼び出し
2. **477-482行目**: project_paramsメソッドでの許可パラメータ定義
3. **527-572行目**: project_params_attributesで許可される属性一覧

#### Step 3: ビジネスロジック層を理解する

プロジェクト作成のコアロジック。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb | `app/services/projects/create_service.rb` | プロジェクト作成の中心ロジック |

**主要処理フロー**:
- **10-25行目**: コンストラクタでのパラメータ初期化
- **27-104行目**: executeメソッドのメイン処理フロー
- **126-157行目**: after_create_actionsでの作成後処理
- **250-275行目**: save_project_and_import_dataでのトランザクション処理

#### Step 4: 権限・バリデーション層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | project_policy.rb | `app/policies/project_policy.rb` | プロジェクト関連の権限定義 |

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

```
ProjectsController#create
    │
    ├─ Projects::CreateService#execute
    │      │
    │      ├─ Projects::CreateFromTemplateService (テンプレート使用時)
    │      │
    │      ├─ Project.new (インスタンス生成)
    │      │
    │      ├─ validate_create_permissions
    │      │
    │      ├─ validate_import_permissions
    │      │
    │      ├─ save_project_and_import_data (トランザクション)
    │      │      │
    │      │      ├─ Namespaces::ProjectNamespace.create_from_project!
    │      │      │
    │      │      ├─ Integration.create_from_default_integrations
    │      │      │
    │      │      └─ project.create_repository
    │      │             └─ Gitaly::RepositoryService
    │      │
    │      └─ after_create_actions
    │             │
    │             ├─ project.create_wiki
    │             │
    │             ├─ create_project_settings
    │             │
    │             ├─ event_service.create_project
    │             │
    │             ├─ execute_hooks (SystemHookService)
    │             │
    │             ├─ setup_authorizations
    │             │      └─ ProjectAuthorization.find_or_create_authorization_for
    │             │
    │             ├─ Projects::PostCreationWorker.perform_async
    │             │
    │             └─ publish_event (ProjectCreatedEvent)
    │
    └─ redirect_to project_path
```

### データフロー図

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

ユーザー入力          ProjectsController#create
  ├─ name                    │
  ├─ path                    ▼
  ├─ namespace_id     Projects::CreateService
  ├─ visibility              │
  └─ その他設定              │
         │                   │
         ▼                   ▼
                     ┌──────────────────┐
                     │ バリデーション     │
                     │ ・権限チェック     │
                     │ ・可視性チェック   │
                     │ ・制限チェック     │
                     └────────┬─────────┘
                              │
                              ▼
                     ┌──────────────────┐      ┌─────────────────┐
                     │ DB保存           │ ───▶ │ projectsテーブル │
                     │ (トランザクション) │      │ namespacesテーブル│
                     └────────┬─────────┘      │ その他関連テーブル│
                              │                └─────────────────┘
                              ▼
                     ┌──────────────────┐      ┌─────────────────┐
                     │ リポジトリ作成    │ ───▶ │ Gitaly          │
                     └────────┬─────────┘      │ (Gitリポジトリ)  │
                              │                └─────────────────┘
                              ▼
                     ┌──────────────────┐      ┌─────────────────┐
                     │ 作成後処理        │ ───▶ │ SystemHook      │
                     │ ・イベント発行    │      │ 外部通知         │
                     │ ・フック実行      │      └─────────────────┘
                     └────────┬─────────┘
                              │
                              ▼
                     ┌──────────────────┐
                     │ 成功レスポンス    │ ───▶ プロジェクトページ
                     └──────────────────┘       へリダイレクト
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| projects_controller.rb | `app/controllers/projects_controller.rb` | ソース | コントローラー、リクエスト処理 |
| create_service.rb | `app/services/projects/create_service.rb` | ソース | プロジェクト作成ビジネスロジック |
| create_from_template_service.rb | `app/services/projects/create_from_template_service.rb` | ソース | テンプレートからの作成処理 |
| project.rb | `app/models/project.rb` | ソース | プロジェクトモデル定義 |
| project_feature.rb | `app/models/project_feature.rb` | ソース | プロジェクト機能設定モデル |
| namespace.rb | `app/models/namespace.rb` | ソース | 名前空間モデル |
| project_policy.rb | `app/policies/project_policy.rb` | ソース | 権限ポリシー定義 |
| post_creation_worker.rb | `app/workers/projects/post_creation_worker.rb` | ソース | 非同期作成後処理 |
| system_hook_service.rb | `app/services/system_hook_service.rb` | ソース | システムフック実行 |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義 |
