# 機能設計書 93-グループWebhook

## 概要

本ドキュメントは、GitLabにおけるグループWebhook機能の設計仕様を記載する。本機能は、グループレベルで発生した各種イベント（プッシュ、マージリクエスト、イシュー、サブグループ作成等）を外部のHTTPエンドポイントに通知するための設定・管理・実行機能を提供する。Premium/Ultimate限定機能である。

### 本機能の処理概要

グループWebhook機能は、グループ配下のすべてのプロジェクトで発生するイベントを一元的に管理し、指定されたURLへHTTP POSTリクエストを送信する。プロジェクトWebhookとは異なり、グループ全体をスコープとするため、複数プロジェクトへの一括設定や、サブグループ・メンバー変更といったグループ固有のイベント通知が可能である。

**業務上の目的・背景**：大規模な組織では、複数のプロジェクトに対して同一のWebhook設定を行う必要がある。グループWebhookを使用することで、グループ配下の全プロジェクトに対する通知を一括で管理でき、設定の重複を排除し、管理コストを削減できる。また、サブグループの作成・削除やメンバー変更といったグループ固有のイベントも監視できる。

**機能の利用シーン**：本機能は以下のシーンで利用される。
- グループ配下の全プロジェクトのプッシュイベントを統合監視
- メンバー追加・削除時のアクセス管理システムへの連携
- サブグループ作成時の自動セットアップトリガー
- グループ全体のCI/CDパイプライン状態の統合監視
- プロジェクト作成・削除の監査ログ連携

**主要な処理内容**：
1. グループWebhookの登録・編集・削除（CRUD操作）
2. グループ固有イベント（サブグループ、メンバー、プロジェクト）の通知設定
3. 配下プロジェクトのイベント一括通知
4. イベント発生時のHTTPリクエスト送信
5. リクエスト/レスポンスのログ記録
6. 失敗時の自動無効化とリトライ処理

**関連システム・外部連携**：外部HTTPエンドポイント、Sidekiq（非同期処理）、SSL/TLS（暗号化通信）

**権限による制御**：グループWebhookの閲覧・作成・編集・削除は管理者またはグループOwnerのみが実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | グループ設定 > Webhooks | 主機能 | グループWebhook設定の一覧・編集 |

## 機能種別

CRUD操作 / イベント通知 / 外部システム連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| url | String | Yes | 通知先URL | パブリックURL |
| token | String | No | 認証用シークレットトークン | - |
| name | String | No | Webhook名 | 255文字以内 |
| description | String | No | 説明 | - |
| push_events | Boolean | No | プッシュイベントを通知 | - |
| push_events_branch_filter | String | No | ブランチフィルタ | 正規表現またはワイルドカード |
| branch_filter_strategy | String | No | ブランチフィルタ戦略 | wildcard/regex/all_branches |
| issues_events | Boolean | No | イシューイベントを通知 | - |
| confidential_issues_events | Boolean | No | 機密イシューイベントを通知 | - |
| merge_requests_events | Boolean | No | MRイベントを通知 | - |
| tag_push_events | Boolean | No | タグプッシュイベントを通知 | - |
| note_events | Boolean | No | コメントイベントを通知 | - |
| confidential_note_events | Boolean | No | 機密コメントイベントを通知 | - |
| job_events | Boolean | No | ジョブイベントを通知 | - |
| pipeline_events | Boolean | No | パイプラインイベントを通知 | - |
| wiki_page_events | Boolean | No | Wikiイベントを通知 | - |
| deployment_events | Boolean | No | デプロイイベントを通知 | - |
| feature_flag_events | Boolean | No | フィーチャーフラグイベントを通知 | - |
| releases_events | Boolean | No | リリースイベントを通知 | - |
| milestone_events | Boolean | No | マイルストーンイベントを通知 | - |
| emoji_events | Boolean | No | 絵文字イベントを通知 | - |
| resource_access_token_events | Boolean | No | アクセストークン期限イベントを通知 | - |
| subgroup_events | Boolean | No | サブグループイベントを通知 | グループ固有 |
| member_events | Boolean | No | メンバーイベントを通知 | グループ固有 |
| project_events | Boolean | No | プロジェクトイベントを通知 | グループ固有 |
| enable_ssl_verification | Boolean | No | SSL証明書検証を有効化 | デフォルト: true |
| custom_webhook_template | String | No | カスタムペイロードテンプレート | - |
| url_variables | Hash | No | URL変数（テンプレート置換用） | JSON形式 |
| custom_headers | Hash | No | カスタムHTTPヘッダー | JSON形式 |

### 入力データソース

- 画面入力（グループ設定 > Webhooks）
- REST API（/api/v4/groups/:id/hooks）
- イベントデータ（各種サービスからのトリガー）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | Webhook ID |
| url | String | 通知先URL |
| name | String | Webhook名 |
| description | String | 説明 |
| group_id | Integer | グループID |
| push_events | Boolean | プッシュイベント設定 |
| subgroup_events | Boolean | サブグループイベント設定 |
| member_events | Boolean | メンバーイベント設定 |
| project_events | Boolean | プロジェクトイベント設定 |
| *_events | Boolean | 各種イベント設定 |
| enable_ssl_verification | Boolean | SSL検証設定 |
| created_at | DateTime | 作成日時 |
| disabled_until | DateTime | 無効化解除予定日時 |
| alert_status | String | アラート状態 |

### 出力先

- 画面表示（グループWebhook一覧・詳細）
- REST API レスポンス
- 外部HTTPエンドポイント（イベント通知時）
- WebHookLogテーブル（実行ログ）

## 処理フロー

### 処理シーケンス

```
1. グループWebhook登録
   └─ グループOwner/管理者がWebhook設定を作成

2. イベント発生
   └─ グループ配下のプロジェクトまたはグループ自体でイベント発生
   └─ グループに紐づくWebhookを取得

3. イベントフィルタリング
   └─ 該当イベントタイプが有効かチェック
   └─ ブランチフィルタの適用（push_events時）

4. 非同期実行
   └─ WebHookWorkerにジョブをエンキュー
   └─ レート制限チェック
   └─ 再帰検出チェック

5. HTTP送信（WebHookService#execute）
   └─ ペイロード構築
   └─ ヘッダー構築（認証トークン、カスタムヘッダー）
   └─ Gitlab::HTTP.postでリクエスト送信

6. レスポンス処理
   └─ ログ記録
   └─ 失敗時の自動無効化
```

### フローチャート

```mermaid
flowchart TD
    A[グループイベント発生] --> B{グループWebhook存在?}
    B -->|No| C[終了]
    B -->|Yes| D{イベント対象?}
    D -->|No| C
    D -->|Yes| E{実行可能?}
    E -->|No| F[スキップ]
    E -->|Yes| G{レート制限?}
    G -->|Yes| F
    G -->|No| H[WebHookWorkerへエンキュー]
    H --> I[HTTPリクエスト送信]
    I --> J{成功?}
    J -->|Yes| K[成功ログ記録]
    J -->|No| L[失敗ログ記録]
    K --> C
    L --> C
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-93-01 | ライセンス要件 | Premium/Ultimate限定機能 | 全操作 |
| BR-93-02 | 権限要件 | 管理者またはグループOwnerのみ操作可能 | 全操作 |
| BR-93-03 | 継承対象 | グループ配下の全プロジェクトのイベントを対象 | イベント通知時 |
| BR-93-04 | 自動無効化 | 連続失敗時にWebhookを自動的に無効化 | 送信失敗時 |
| BR-93-05 | レート制限 | テスト送信は5リクエスト/分に制限 | テスト送信時 |
| BR-93-06 | サブグループイベント | サブグループの作成・削除時に通知 | subgroup_events有効時 |
| BR-93-07 | メンバーイベント | グループメンバーの追加・削除・変更時に通知 | member_events有効時 |
| BR-93-08 | プロジェクトイベント | グループ配下のプロジェクト作成・削除時に通知 | project_events有効時 |

### 計算ロジック

プロジェクトWebhookと同様の処理を使用（WebHookService）。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Webhook作成 | web_hooks | INSERT | 新規グループWebhook設定の登録（type: GroupHook） |
| Webhook更新 | web_hooks | UPDATE | グループWebhook設定の変更 |
| Webhook削除 | web_hooks | DELETE | グループWebhook設定の削除 |
| ログ記録 | web_hook_logs | INSERT | 実行ログの記録 |
| 状態更新 | web_hooks | UPDATE | disabled_until, recent_failuresの更新 |

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

#### web_hooks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | type, url, token, group_id, *_events | フォーム入力値 | type='GroupHook'、暗号化して保存 |
| UPDATE | url, token, *_events, disabled_until | フォーム入力値/自動更新 | - |
| DELETE | - | id条件 | 関連ログも削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | 権限エラー | Owner以外がアクセス | 適切な権限を持つユーザーで操作 |
| 404 | 未検出エラー | 存在しないグループまたはWebhook | 正しいIDを指定 |
| - | タイムアウト | レスポンスがタイムアウト | リトライ |
| - | 接続エラー | 接続先に到達できない | URLを確認 |
| - | SSL検証エラー | SSL証明書が無効 | SSL検証無効化または証明書修正 |

### リトライ仕様

プロジェクトWebhookと同様、連続失敗時は自動無効化される。

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

プロジェクトWebhookと同様。

## パフォーマンス要件

- HTTPリクエストタイムアウト：10秒（設定可能）
- テスト送信レート制限：5リクエスト/分（グループ・ユーザーごと）
- イベント再送レート制限：5リクエスト/分（Webhookごと）

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

- **ライセンス制限**：Premium/Ultimate限定
- **権限制限**：管理者またはグループOwnerのみ
- **URL暗号化**：AES-256-GCMで暗号化して保存
- **トークン暗号化**：AES-256-GCMで暗号化して保存
- **X-Gitlab-Token**：認証用ヘッダーとしてトークンを送信
- **SSL検証**：デフォルトで有効

## 備考

- グループ固有のイベント（subgroup_events, member_events, project_events）はグループWebhook特有の機能
- プロジェクトWebhookとは異なり、グループ配下の全プロジェクトのイベントを一括で受信可能
- URL変更時はトークンがリセットされる

---

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

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

### 推奨読解順序

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

GroupHookはWebHookを継承したSTI（Single Table Inheritance）モデル。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | web_hooks.yml | `db/docs/web_hooks.yml` | GroupHookがweb_hooksテーブルのSTIクラスであることを確認 |
| 1-2 | hook.rb | `app/models/concerns/web_hooks/hook.rb` | Webhookの基本機能（プロジェクトWebhookと共通） |

**読解のコツ**: GroupHookはweb_hooksテーブルの`type`カラムで識別される。基本的なWebhook機能はProjectHookと共通であり、`WebHooks::Hook` concernに実装されている。

#### Step 2: APIエンドポイントを理解する

グループWebhookはREST APIで管理される。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | group_webhooks.md | `doc/api/group_webhooks.md` | REST APIの仕様、Premium/Ultimate限定であることの確認 |

**主要エンドポイント**:
- `GET /groups/:id/hooks` - 一覧取得
- `GET /groups/:id/hooks/:hook_id` - 詳細取得
- `POST /groups/:id/hooks` - 作成
- `PUT /groups/:id/hooks/:hook_id` - 更新
- `DELETE /groups/:id/hooks/:hook_id` - 削除
- `POST /groups/:id/hooks/:hook_id/test/:trigger` - テスト送信
- `GET /groups/:id/hooks/:hook_id/events` - イベントログ取得

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

Webhook送信処理はプロジェクトWebhookと共通のサービスを使用。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | web_hook_service.rb | `app/services/web_hook_service.rb` | HTTP送信処理（プロジェクトWebhookと共通） |

#### Step 4: グループ固有イベントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | triggerable_hooks.rb | `app/models/concerns/triggerable_hooks.rb` | member_hooks, subgroup_hooks, project_hooksの定義 |

**グループ固有のトリガー**:
- **33行目**: `member_hooks: :member_events` - メンバー変更イベント
- **38行目**: `project_hooks: :project_events` - プロジェクト作成・削除イベント
- **43行目**: `subgroup_hooks: :subgroup_events` - サブグループ作成・削除イベント

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

```
API::Groups::Hooks (想定)
    |
    +-- WebHooks::CreateService#execute
    +-- WebHooks::DestroyService#execute
    |
    +-- Group#trigger_hooks（グループイベント時）
            |
            +-- GroupHook.hooks_for(:member_hooks)
            +-- GroupHook.hooks_for(:subgroup_hooks)
            +-- GroupHook.hooks_for(:project_hooks)
            +-- WebHook#async_execute
                    |
                    +-- WebHookWorker.perform_async
                            |
                            +-- WebHookService#execute
```

### データフロー図

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

API入力             ---->   Groups::HooksController      ---->  DB保存
(url, token等)              WebHooks::CreateService            (web_hooks)

グループイベント    ---->   Group#trigger_hooks          ---->  外部HTTP
(member, subgroup等)        WebHookService#execute             エンドポイント
                                    |
                                    v
                            WebHooks::LogExecutionWorker ---->  DB保存
                                                               (web_hook_logs)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| web_hooks.yml | `db/docs/web_hooks.yml` | 設定 | テーブル定義（GroupHookのSTI）|
| hook.rb | `app/models/concerns/web_hooks/hook.rb` | ソース | Webhook基本機能 |
| triggerable_hooks.rb | `app/models/concerns/triggerable_hooks.rb` | ソース | グループ固有トリガー定義 |
| web_hook_service.rb | `app/services/web_hook_service.rb` | ソース | HTTP送信サービス |
| group_webhooks.md | `doc/api/group_webhooks.md` | ドキュメント | REST API仕様 |
