# 機能設計書 81-Webhook作成

## 概要

本ドキュメントは、Fizzyアプリケーションにおける「Webhook作成」機能の設計仕様を定義する。新しいWebhookをボードに作成し、外部サービスとの連携を設定する機能である。

### 本機能の処理概要

Webhook作成機能は、カンバンボードで発生するイベントを外部サービスに通知するためのWebhook設定を新規作成する機能である。

**業務上の目的・背景**：チームがFizzyで管理するタスクやカードの状態変化を、SlackやBasecamp Campfireなどの外部コミュニケーションツールに自動通知することで、チーム全体のタスク進捗の可視性を高め、コミュニケーション効率を向上させる。また、外部システムとのデータ連携を実現し、ワークフローの自動化を可能にする。

**機能の利用シーン**：管理者がボードの設定画面から新しいWebhookを追加する際に使用する。例えば、カードが公開されたときにSlackチャンネルに通知を送りたい場合や、カードがクローズされたときにBasecampのCampfireに投稿したい場合などに、この機能でWebhookを設定する。

**主要な処理内容**：
1. ユーザーがWebhook名、ペイロードURL、購読するイベントを入力
2. URLのバリデーション（HTTPまたはHTTPSスキームのみ許可）
3. Webhookレコードの作成と署名シークレットの自動生成
4. Delinquency Tracker（配信失敗追跡）の自動作成
5. 作成完了後、Webhook詳細画面へリダイレクト

**関連システム・外部連携**：Slack Webhook、Basecamp Campfire、汎用HTTPエンドポイントとの連携に対応。URL形式に応じてペイロード形式が自動判定される。

**権限による制御**：ボードの管理者（admin）権限を持つユーザーのみがWebhookを作成できる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 62 | Webhook一覧画面 | 参照画面 | 新規作成ボタンからこの機能を呼び出す |
| 63 | Webhook新規作成画面 | 主画面 | Webhook作成フォームを表示・送信 |

## 機能種別

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

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| name | String | Yes | Webhookの名前 | 必須、空白不可 |
| url | String | Yes | ペイロードを送信する先のURL | 必須、http://またはhttps://スキームのみ |
| subscribed_actions | Array | No | 購読するイベントアクションの配列 | PERMITTED_ACTIONSに含まれるもののみ |

### 入力データソース

画面フォームからの入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | UUID | 作成されたWebhookの一意識別子 |
| name | String | Webhook名 |
| url | String | ペイロードURL |
| subscribed_actions | Array | 購読イベント一覧 |
| signing_secret | String | 署名検証用シークレット |
| active | Boolean | アクティブ状態（初期値: true） |

### 出力先

- データベース（webhooksテーブル）
- 画面遷移（作成されたWebhook詳細画面へリダイレクト）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   └─ POST /boards/:board_id/webhooks
2. 認証・認可チェック
   └─ ログインユーザーかつボード管理者権限を確認
3. ボード取得
   └─ Current.userのボードからboard_idで検索
4. パラメータ抽出
   └─ webhook_paramsメソッドでname, url, subscribed_actionsを取得
5. Webhook作成
   └─ @board.webhooks.create!(webhook_params)
6. 関連レコード作成
   └─ after_createコールバックでdelinquency_trackerを作成
7. 署名シークレット生成
   └─ has_secure_tokenにより自動生成
8. リダイレクト
   └─ 作成されたWebhook詳細画面へ遷移
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{ログイン済み?}
    B -->|No| C[ログイン画面へ]
    B -->|Yes| D{管理者権限?}
    D -->|No| E[403 Forbidden]
    D -->|Yes| F[入力パラメータ取得]
    F --> G{URL有効?}
    G -->|No| H[バリデーションエラー]
    G -->|Yes| I[Webhookレコード作成]
    I --> J[署名シークレット生成]
    J --> K[Delinquency Tracker作成]
    K --> L[Webhook詳細画面へリダイレクト]
    L --> M[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-81-01 | URL形式制限 | URLはhttpまたはhttpsスキームのみ許可 | Webhook作成時 |
| BR-81-02 | アクション制限 | PERMITTED_ACTIONSに定義されたアクションのみ購読可能 | イベント選択時 |
| BR-81-03 | 初期状態 | 作成されたWebhookはデフォルトでアクティブ状態 | Webhook作成時 |
| BR-81-04 | 署名シークレット | 自動生成され、変更不可 | Webhook作成時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Webhook作成 | webhooks | INSERT | 新規Webhookレコード作成 |
| 失敗追跡作成 | webhook_delinquency_trackers | INSERT | Delinquency Tracker作成 |

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

#### webhooks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | UUIDを自動生成 | 主キー |
| INSERT | account_id | board.account_id | ボードから取得 |
| INSERT | board_id | パラメータから取得 | 必須 |
| INSERT | name | ユーザー入力 | 必須 |
| INSERT | url | ユーザー入力 | 必須 |
| INSERT | subscribed_actions | ユーザー選択（JSON配列） | 空配列可 |
| INSERT | signing_secret | has_secure_tokenで自動生成 | 24文字 |
| INSERT | active | true | デフォルト値 |
| INSERT | created_at | 現在時刻 | 自動設定 |
| INSERT | updated_at | 現在時刻 | 自動設定 |

#### webhook_delinquency_trackers

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | id | UUIDを自動生成 | 主キー |
| INSERT | account_id | webhook.account_id | 自動設定 |
| INSERT | webhook_id | 親Webhookのid | 外部キー |
| INSERT | consecutive_failures_count | 0 | 初期値 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 未ログイン | ログイン画面へリダイレクト |
| 403 | Forbidden | 管理者権限なし | 権限エラー表示 |
| 404 | NotFound | ボードが存在しない | エラーページ表示 |
| 422 | UnprocessableEntity | バリデーションエラー | フォーム再表示、エラーメッセージ表示 |

### リトライ仕様

該当なし（同期処理のため）

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

WebhookレコードとDelinquency Trackerの作成は、ActiveRecordのコールバック機構により同一トランザクション内で処理される。作成処理に失敗した場合は自動的にロールバックされる。

## パフォーマンス要件

- レスポンス時間: 1秒以内
- 同時作成リクエスト: 特に制限なし

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

- 管理者権限チェックによる認可制御
- URLのスキーム制限（http/https）によるSSRF対策
- 署名シークレットの自動生成による改ざん防止

## 備考

許可されているイベントアクション（PERMITTED_ACTIONS）:
- card_assigned: カードアサイン時
- card_closed: カードクローズ時
- card_postponed: カード延期時
- card_auto_postponed: 自動延期時
- card_board_changed: ボード変更時
- card_published: カード公開時
- card_reopened: カード再オープン時
- card_sent_back_to_triage: トリアージ戻し時
- card_triaged: トリアージ時
- card_unassigned: アサイン解除時
- comment_created: コメント作成時

---

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

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

### 推奨読解順序

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

Webhookモデルの構造と許可されるアクションの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | webhook.rb | `app/models/webhook.rb` | Webhookモデルの属性、バリデーション、リレーション |
| 1-2 | schema.rb | `db/schema.rb` | webhooksテーブルの構造（830-842行目） |

**読解のコツ**: Webhookモデルは`has_secure_token :signing_secret`により署名シークレットを自動生成する。`PERMITTED_ACTIONS`定数で許可されるイベントアクションが定義されている。

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

コントローラーのcreateアクションが処理の起点となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | webhooks_controller.rb | `app/controllers/webhooks_controller.rb` | createアクションの処理フロー |
| 2-2 | board_scoped.rb | `app/controllers/concerns/board_scoped.rb` | ボード取得の共通ロジック |

**主要処理フロー**:
1. **4行目**: `before_action :ensure_admin` - 管理者権限チェック
2. **18-21行目**: `create`アクション - Webhook作成処理
3. **41-45行目**: `webhook_params` - パラメータの抽出とサニタイズ

#### Step 3: ビューテンプレートを理解する

フォームの構造と入力項目を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new.html.erb | `app/views/webhooks/new.html.erb` | 新規作成フォームの構造 |
| 3-2 | _actions.html.erb | `app/views/webhooks/form/_actions.html.erb` | イベント選択UIの実装 |
| 3-3 | webhooks_helper.rb | `app/helpers/webhooks_helper.rb` | アクションラベルの定義 |

**主要処理フロー**:
- **12-15行目**: name入力フィールド
- **22-28行目**: URL入力フィールド（パターン検証付き）
- **36行目**: アクション選択パーシャルの呼び出し

#### Step 4: 関連モデルを理解する

Webhook作成時に自動生成される関連レコードを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | triggerable.rb | `app/models/webhook/triggerable.rb` | トリガー機能の実装 |
| 4-2 | delivery.rb | `app/models/webhook/delivery.rb` | 配信処理の実装 |

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

```
WebhooksController#create
    │
    ├─ BoardScoped#set_board
    │      └─ Current.user.boards.find(params[:board_id])
    │
    ├─ ApplicationController#ensure_admin
    │      └─ Current.user.admin?
    │
    └─ @board.webhooks.create!(webhook_params)
           │
           ├─ Webhook.validate_url (バリデーション)
           │
           ├─ has_secure_token :signing_secret (シークレット生成)
           │
           └─ after_create :create_delinquency_tracker!
                  └─ Webhook::DelinquencyTracker.create!
```

### データフロー図

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

フォーム入力 ───▶ WebhooksController ───▶ webhooksテーブル
  - name                    │
  - url                     │
  - subscribed_actions      │
                            ▼
                    Webhookモデル ───▶ webhook_delinquency_trackersテーブル
                      - validate_url
                      - generate_signing_secret
                            │
                            ▼
                    リダイレクト ───▶ Webhook詳細画面
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| webhooks_controller.rb | `app/controllers/webhooks_controller.rb` | ソース | Webhook CRUDコントローラー |
| board_scoped.rb | `app/controllers/concerns/board_scoped.rb` | ソース | ボードスコープ共通処理 |
| webhook.rb | `app/models/webhook.rb` | ソース | Webhookモデル定義 |
| triggerable.rb | `app/models/webhook/triggerable.rb` | ソース | トリガー機能concern |
| delivery.rb | `app/models/webhook/delivery.rb` | ソース | 配信処理モデル |
| new.html.erb | `app/views/webhooks/new.html.erb` | テンプレート | 新規作成フォーム |
| _actions.html.erb | `app/views/webhooks/form/_actions.html.erb` | テンプレート | イベント選択UI |
| webhooks_helper.rb | `app/helpers/webhooks_helper.rb` | ソース | ビューヘルパー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（47-51行目） |
| schema.rb | `db/schema.rb` | 設定 | DBスキーマ定義 |
