# 機能設計書 13-サブグループ管理

## 概要

本ドキュメントは、GitLabにおけるサブグループ管理機能の設計仕様を定義する。グループ内にサブグループ（子グループ）を作成・管理する機能について、処理フロー、入出力仕様、ビジネスルールを記載する。

### 本機能の処理概要

サブグループ管理機能は、既存のグループ配下に階層構造を持つサブグループを作成・管理する機能である。サブグループは親グループの設定を継承しつつ、独自の設定を持つことができる。

**業務上の目的・背景**：組織の階層構造（本部 > 部署 > チーム等）をGitLab上で表現し、適切なアクセス権限の継承と管理を実現する。大規模組織において、プロジェクトを論理的にグルーピングし、権限管理を効率化することが目的である。

**機能の利用シーン**：
- 部署内にチーム単位のサブグループを作成する場合
- プロジェクトを機能別、地域別等でグルーピングする場合
- 階層的な権限管理を実現する場合
- 複数のプロジェクトに共通設定を適用する場合

**主要な処理内容**：
1. サブグループ作成権限の確認
2. サブグループの作成（名前、パス、説明、可視性等の設定）
3. 親グループからの設定継承（可視性レベル、2FA設定、共有Runner設定等）
4. サブグループメンバーの管理
5. サブグループの編集・削除

**関連システム・外部連携**：
- Mattermostチームとの連携（オプション）
- インテグレーション設定の継承

**権限による制御**：
- 親グループでのサブグループ作成権限（create_subgroup）が必要
- グループ設定の`subgroup_creation_level`により、作成権限を持つロールが決定される
- デフォルトはOwnerのみ、設定によりMaintainerにも許可可能

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 141 | グループ詳細 | 参照画面 | サブグループ一覧の表示 |
| 142 | グループ新規作成 | 主画面 | サブグループの作成操作 |
| 143 | グループ編集 | 参照画面 | サブグループ設定の編集 |
| 190 | グループ新規作成（組織配下） | 参照画面 | 組織配下でのサブグループ作成 |

## 機能種別

CRUD操作（Create/Read/Update/Delete）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| parent_id | Integer | Yes | 親グループのID | 存在するグループであること |
| name | String | Yes | サブグループ名 | 255文字以内、命名規則準拠 |
| path | String | Yes | サブグループパス | 255文字以内、URL safe |
| description | String | No | 説明 | 任意 |
| visibility_level | Integer | No | 可視性レベル | 0:Private, 10:Internal, 20:Public |
| avatar | File | No | グループアバター | 画像ファイル |

### 入力データソース

- 画面入力：グループ作成フォームからのユーザー入力
- URLパラメータ：親グループID

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| group | Group | 作成されたサブグループオブジェクト |
| success | Boolean | 作成成功/失敗 |
| errors | Array | エラーメッセージ（失敗時） |

### 出力先

- 画面表示：作成完了後、サブグループページにリダイレクト
- データベース：namespacesテーブルへの登録
- 監査ログ：作成操作の記録

## 処理フロー

### 処理シーケンス

```
1. サブグループ作成リクエスト受付
   └─ GroupsController#createが呼び出される（parent_id指定あり）

2. 親グループの取得と権限チェック
   └─ authorize_create_group!で親グループへのcreate_subgroup権限を確認

3. サブグループオブジェクト構築
   └─ Groups::CreateService#execute
      └─ 親グループからの設定継承
      └─ 可視性レベルの検証と調整

4. バリデーション
   └─ グループモデルのバリデーション実行

5. データベース保存
   └─ グループレコードの作成
   └─ 関連レコードの作成（namespace_settings, group_feature等）

6. 後処理
   └─ システムフックの実行
   └─ インテグレーション設定の作成
   └─ Mattermostチームの作成（オプション）
```

### フローチャート

```mermaid
flowchart TD
    A[サブグループ作成リクエスト] --> B{親グループ存在?}
    B -->|No| C[404エラー]
    B -->|Yes| D{作成権限?}
    D -->|No| E[403エラー]
    D -->|Yes| F[パラメータ検証]
    F --> G{可視性レベル有効?}
    G -->|No| H[親の可視性に調整]
    G -->|Yes| I[グループオブジェクト作成]
    H --> I
    I --> J{バリデーション}
    J -->|NG| K[エラー表示]
    J -->|OK| L[DB保存]
    L --> M[後処理実行]
    M --> N[システムフック]
    N --> O[サブグループページへ遷移]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 作成権限 | 親グループでのcreate_subgroup権限が必要 | 常時 |
| BR-02 | 作成レベル設定 | subgroup_creation_levelにより作成可能ロールを制限 | 常時 |
| BR-03 | 可視性継承 | サブグループの可視性は親グループ以下でなければならない | 常時 |
| BR-04 | 2FA継承 | 親グループで2FAが許可されていない場合、サブグループでも有効化不可 | 常時 |
| BR-05 | パス一意性 | 同一親グループ内でパスは一意でなければならない | 常時 |
| BR-06 | 名前規則 | グループ名は命名規則に準拠 | 常時 |
| BR-07 | 階層制限 | ネスト階層に制限がある場合がある（設定依存） | 設定時 |
| BR-08 | 共有Runner継承 | 親の共有Runner設定を継承 | 常時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| サブグループ作成 | namespaces | INSERT | グループレコード作成 |
| 設定作成 | namespace_settings | INSERT | グループ設定作成 |
| 機能設定作成 | group_features | INSERT | 機能設定作成 |
| ルート作成 | routes | INSERT | URLルーティング作成 |
| メンバー作成 | members | INSERT | 作成者をOwnerとして追加 |

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

#### namespaces

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | type | 'Group' | - |
| INSERT | name | 入力値 | - |
| INSERT | path | 入力値 | - |
| INSERT | parent_id | 親グループID | - |
| INSERT | visibility_level | 入力値または親の値 | - |
| INSERT | organization_id | 親グループと同じ | - |

#### members

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | source_type | 'Namespace' | - |
| INSERT | source_id | 作成されたグループID | - |
| INSERT | user_id | 作成者ID | - |
| INSERT | access_level | 50 (Owner) | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 権限エラー | 作成権限がない場合 | 権限確認、管理者に依頼 |
| - | バリデーションエラー | パス重複、名前不正等 | 入力内容を修正 |
| - | 可視性エラー | 親より高い可視性を指定 | 可視性を調整 |
| - | 2FAエラー | 禁止されている2FA設定を指定 | 2FA設定を無効化 |

### リトライ仕様

- トランザクション内でエラーが発生した場合、ロールバック
- ユーザーは入力内容を修正して再試行

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

- グループ作成処理全体がトランザクション内で実行
- 関連レコード（settings, features, members等）も同一トランザクション内で作成

## パフォーマンス要件

- グループ作成は即時完了が期待される
- Mattermostチーム作成等の外部連携は非同期で実行される場合がある

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

- サブグループ作成権限の厳格なチェック
- 可視性レベルの継承による情報漏洩防止
- 作成者への自動的なOwner権限付与

## 備考

- サブグループのネスト深さに実質的な制限はないが、パフォーマンスへの影響に注意
- 親グループの設定変更は、サブグループに自動的に反映される場合がある

---

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

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

### 推奨読解順序

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

グループの階層構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | group.rb | `app/models/group.rb` | parent_id、has_parent?等の階層管理 |
| 1-2 | namespace.rb | `app/models/namespace.rb` | 名前空間の基本構造、traversal_ids |

**読解のコツ**: Groupモデルはparent_idで親子関係を管理。has_parent?メソッドでサブグループかどうかを判定できる。

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

コントローラーのサブグループ作成処理を確認する。

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

**主要処理フロー**:
1. **77-81行目**: newアクション、parent_idから親グループ取得
2. **83-109行目**: createアクション、Groups::CreateServiceの呼び出し
3. **316-327行目**: authorize_create_group!、作成権限のチェック

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

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

**主要処理フロー**:
- グループオブジェクトの構築
- 親グループからの設定継承
- バリデーションと保存

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

```
GroupsController#new
    └─ 親グループの取得 (params[:parent_id])

GroupsController#create
    │
    ├─ authorize_create_group! (権限チェック)
    │      └─ can?(current_user, :create_subgroup, parent)
    │
    └─ Groups::CreateService#execute
           ├─ グループオブジェクト構築
           ├─ 可視性レベル調整
           ├─ group.save!
           ├─ namespace_settings作成
           ├─ group_feature作成
           ├─ Members::CreatorService (Owner追加)
           └─ system_hook_service.execute_hooks_for(group, :create)
```

### データフロー図

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

親グループID ───▶ GroupsController ───▶ サブグループページ
グループ情報          │
                      ▼
              Groups::CreateService
                      │
                      ▼
              バリデーション
                      │
                      ▼
              ┌───────────────────┐
              │ トランザクション     │
              │                   │
              │ namespaces        │
              │ namespace_settings │
              │ group_features    │
              │ routes            │
              │ members           │
              └───────────────────┘
                      │
                      ▼
              システムフック発行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| 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` | モデル | グループ設定 |
| group_feature.rb | `app/models/groups/feature_setting.rb` | モデル | グループ機能設定 |
| route.rb | `app/models/route.rb` | モデル | URLルーティング |
