# 機能設計書 9-グループ作成

## 概要

本ドキュメントは、GitLabにおけるグループ作成機能の詳細設計を記述する。この機能は、プロジェクトやサブグループをまとめて管理するための名前空間（グループ）を新規作成する機能である。

### 本機能の処理概要

グループ作成機能は、組織構造を反映したプロジェクト管理のための階層的な名前空間を作成する機能を提供する。

**業務上の目的・背景**：企業や組織の構造に合わせてプロジェクトをグループ化し、メンバー管理、権限管理、設定の継承を効率的に行う必要がある。グループ機能により、複数のプロジェクトに対する一括操作や、サブグループによる階層構造の表現が可能になる。

**機能の利用シーン**：
- 新規チームやプロジェクトグループを立ち上げる時
- 組織構造に合わせた名前空間を作成する時
- サブグループとしてチームを細分化する時
- Mattermostチームと連携するグループを作成する時

**主要な処理内容**：
1. グループ作成権限の確認
2. 可視性レベルの検証・設定
3. 組織IDの設定
4. 親グループからの設定継承（サブグループの場合）
5. グループの保存
6. オーナーメンバーシップの追加
7. デフォルトインテグレーションの作成
8. Mattermostチーム連携（オプション）

**関連システム・外部連携**：
- Mattermost（チーム連携）
- インテグレーション（デフォルト設定継承）

**権限による制御**：
- トップレベルグループ：create_group権限が必要
- サブグループ：親グループでcreate_subgroup権限が必要
- 可視性レベルはアプリケーション設定に従う

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 31 | グループ新規作成 | 主画面 | グループ情報入力・作成 |

## 機能種別

CRUD操作（Create）/ データ連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | グループ名 | 必須、文字数制限 |
| path | String | Yes | URLパス | 一意性、フォーマット |
| parent_id | Integer | No | 親グループID | 存在確認、権限確認 |
| visibility_level | Integer | No | 可視性レベル | 許可されたレベル |
| description | String | No | 説明 | - |
| avatar | File | No | アバター画像 | 画像フォーマット |
| organization_id | Integer | No | 組織ID | 存在確認、権限確認 |
| create_chat_team | Boolean | No | Mattermostチーム作成 | Mattermost有効時のみ |

### 入力データソース

- 画面入力（Web UI - New group画面）
- API リクエスト（REST API / GraphQL）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| group | Group | 作成されたグループ |
| message | String | エラーメッセージ（失敗時） |

### 出力先

- データベース（namespaces, routes, members等）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受付（GroupsController#create）
   └─ パラメータ確認

2. 権限チェック（authorize_create_group!）
   ├─ トップレベル：create_group権限
   └─ サブグループ：create_subgroup権限

3. サービス呼び出し（Groups::CreateService#execute）

4. グループ構築
   ├─ 不許可パラメータ削除
   ├─ 可視性レベル設定
   ├─ 組織設定
   └─ 名前空間設定構築

5. バリデーション
   ├─ 可視性レベル検証
   └─ ユーザー権限検証

6. グループ作成（トランザクション内）
   ├─ グループ保存
   ├─ オーナー追加
   ├─ 作成者追加
   └─ デフォルトインテグレーション作成

7. Mattermostチーム作成（オプション）

8. レスポンス返却
   └─ グループページへリダイレクト
```

### フローチャート

```mermaid
flowchart TD
    A[開始: create リクエスト] --> B{権限チェック}
    B -->|サブグループ| C{create_subgroup権限?}
    B -->|トップレベル| D{create_group権限?}
    C -->|No| E[エラー: 権限なし]
    D -->|No| E
    C -->|Yes| F[CreateService#execute]
    D -->|Yes| F
    F --> G[build_group]
    G --> H{可視性レベル有効?}
    H -->|No| I[エラー: 可視性不正]
    H -->|Yes| J{ユーザー権限有効?}
    J -->|No| K[エラー: 権限不足]
    J -->|Yes| L{組織設定有効?}
    L -->|No| M[エラー: 組織不正]
    L -->|Yes| N[create_group]
    N --> O[グループ保存]
    O --> P{保存成功?}
    P -->|No| Q[エラー返却]
    P -->|Yes| R[オーナー追加]
    R --> S[インテグレーション作成]
    S --> T{Mattermost有効?}
    T -->|Yes| U[Mattermostチーム作成]
    T -->|No| V[成功レスポンス]
    U --> V

    E --> W[終了]
    I --> W
    K --> W
    M --> W
    Q --> W
    V --> W
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 権限必須 | グループ作成には適切な権限が必要 | 常時 |
| BR-002 | 可視性制限 | アプリケーション設定の可視性制限に従う | 常時 |
| BR-003 | 親継承 | サブグループは親の共有ランナー設定を継承 | サブグループ作成時 |
| BR-004 | 組織一致 | サブグループは親と同一組織に属する必要 | サブグループ作成時 |
| BR-005 | 名前デフォルト | nameが未指定の場合pathから設定 | name未指定時 |

### 計算ロジック

可視性レベル設定：
```ruby
# パラメータ未指定時はデフォルト値を使用
visibility_level = params[:visibility_level] || Gitlab::CurrentSettings.default_group_visibility
```

共有ランナー設定継承：
```ruby
# サブグループの場合、親の設定を継承
if @group.parent
  @group.shared_runners_enabled = @group.parent.shared_runners_enabled
  @group.allow_descendants_override_disabled_shared_runners = @group.parent.allow_descendants_override_disabled_shared_runners
end
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| グループ作成 | namespaces | INSERT | グループレコード作成 |
| ルート作成 | routes | INSERT | URLパス登録 |
| メンバー追加 | members | INSERT | オーナー権限追加 |
| 名前空間設定 | namespace_settings | INSERT | 設定レコード作成 |
| インテグレーション | integrations | INSERT | デフォルト設定作成 |
| Mattermostチーム | chat_teams | INSERT | チーム連携（オプション） |

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

#### namespaces

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | name | params[:name] or params[:path] | グループ名 |
| INSERT | path | params[:path] | URLパス |
| INSERT | type | 'Group' | グループ種別 |
| INSERT | parent_id | params[:parent_id] | 親グループID |
| INSERT | visibility_level | 設定値 | 可視性レベル |
| INSERT | organization_id | 設定値 | 組織ID |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| E001 | 権限エラー | グループ作成権限なし | 権限を取得 |
| E002 | 権限エラー | サブグループ作成権限なし | 親グループでの権限を取得 |
| E003 | 可視性エラー | 許可されない可視性レベル | 許可されたレベルに変更 |
| E004 | 組織エラー | 組織での権限なしまたは親と不一致 | 適切な組織を選択 |
| E005 | バリデーションエラー | 名前・パスの形式不正 | 正しい形式で入力 |

### リトライ仕様

- グループ作成失敗時はロールバック
- Mattermostチーム作成失敗時はエラーメッセージを返却

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

- グループ作成、オーナー追加、インテグレーション作成は同一トランザクション内
- Mattermostチーム作成は別トランザクション

## パフォーマンス要件

- グループ作成は即座に完了
- 低緊急度（urgency: :low）として設定

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

- 権限チェック必須
- 組織レベルでのアクセス制御
- default_branch_protection設定は特別な権限が必要

## 備考

- トップレベルグループ作成時、jwt_ci_cd_job_token_enabledがtrueに設定される
- Mattermostとの連携はMattermostが有効な場合のみ
- 作成者は自動的にオーナーとして追加される

---

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

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

### 推奨読解順序

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

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

**主要処理フロー**:
1. **83-109行目**: createアクションの定義
2. **316-327行目**: authorize_create_group!の権限チェック

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

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

**主要処理フロー**:
- **11-27行目**: executeメソッドのメイン処理
- **48-62行目**: build_groupでグループ構築
- **64-76行目**: create_groupでグループ保存
- **101-124行目**: valid_user_permissions?で権限検証
- **182-187行目**: inherit_group_shared_runners_settingsで設定継承

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

```
GroupsController#create
    │
    ├─ authorize_create_group!
    │      ├─ [サブグループ] can?(:create_subgroup, parent)
    │      └─ [トップレベル] can?(:create_group)
    │
    └─ Groups::CreateService#execute
           │
           ├─ build_group
           │      ├─ remove_unallowed_params
           │      ├─ set_visibility_level
           │      ├─ Group.new(params)
           │      ├─ set_organization
           │      ├─ set_jwt_ci_cd_job_token_enabled
           │      └─ handle_namespace_settings
           │
           ├─ after_build_hook
           │      └─ inherit_group_shared_runners_settings
           │
           ├─ valid?
           │      ├─ valid_visibility_level?
           │      └─ valid_user_permissions?
           │             ├─ サブグループ: can?(:create_subgroup, parent)
           │             ├─ トップレベル: can?(:create_group)
           │             └─ organization_setting_valid?
           │
           ├─ create_chat_team (オプション)
           │      └─ Mattermost::CreateTeamService
           │
           └─ create_group (トランザクション)
                  ├─ @group.save
                  ├─ @group.add_owner(current_user)
                  ├─ @group.add_creator(current_user)
                  └─ Integration.create_from_default_integrations
```

### データフロー図

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

グループ作成           GroupsController#create
フォーム入力                 │
         │                  │
         ▼                  ▼
              ┌───────────────────────────────┐
              │ 権限チェック                   │
              │ authorize_create_group!        │
              └─────────────┬─────────────────┘
                            │
                            ▼
              ┌───────────────────────────────┐
              │ Groups::CreateService#execute │
              │                               │
              │ ├─ build_group                │
              │ ├─ バリデーション             │
              │ └─ create_group               │
              └─────────────┬─────────────────┘
                            │
                            ▼
              ┌───────────────────────────────┐      ┌─────────────────────┐
              │ トランザクション               │      │ namespaces          │
              │ ├─ group.save                 │ ───▶ │ routes              │
              │ ├─ add_owner                  │      │ members             │
              │ └─ create_integrations        │      │ integrations        │
              └─────────────┬─────────────────┘      └─────────────────────┘
                            │
                            ▼
              ┌───────────────────────────────┐
              │ [オプション]                   │
              │ Mattermost::CreateTeamService │
              └─────────────┬─────────────────┘
                            │
                            ▼
              ┌───────────────────────────────┐
              │ リダイレクト                   │
              │ → グループページ              │
              └───────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| groups_controller.rb | `app/controllers/groups_controller.rb` | ソース | コントローラー |
| create_service.rb | `app/services/groups/create_service.rb` | ソース | 作成ビジネスロジック |
| group.rb | `app/models/group.rb` | ソース | グループモデル |
| namespace.rb | `app/models/namespace.rb` | ソース | 名前空間モデル |
| namespace_setting.rb | `app/models/namespace_setting.rb` | ソース | 名前空間設定 |
| create_team_service.rb | `app/services/mattermost/create_team_service.rb` | ソース | Mattermostチーム作成 |
