# 機能設計書 44-サービスデスク

## 概要

本ドキュメントは、GitLabにおけるサービスデスク機能の設計仕様を定義する。サービスデスクは、メール経由でイシュー（チケット）を作成・管理する機能であり、外部ユーザー（GitLabアカウントを持たないカスタマーやエンドユーザー）からの問い合わせを効率的に処理するための仕組みである。

### 本機能の処理概要

**業務上の目的・背景**：ソフトウェアプロダクトの運用において、エンドユーザーからの問い合わせやサポートリクエストを受け付ける窓口が必要である。サービスデスク機能は、専用のメールアドレスに送られたメールを自動的にGitLabのイシューとして作成し、開発チームがGitLab上でサポート業務を完結できるようにする。これにより、外部ツールを使わずにサポートワークフローを統合し、チケット管理とコード管理を同一プラットフォームで行えるようになる。

**機能の利用シーン**：
- カスタマーがサポートメールアドレスに問い合わせを送信する場面
- サポートチームがGitLab上でチケットを確認し、対応を進める場面
- カスタマーへの返信がメールで自動送信される場面
- サポートテンプレートを使用してイシューの初期内容を設定する場面
- カスタムメールドメインを設定してブランディングを行う場面

**主要な処理内容**：
1. サービスデスクの有効化/無効化
2. 専用メールアドレスの生成と管理
3. 受信メールからのイシュー自動作成
4. イシューテンプレートの適用
5. カスタムメールアドレスの設定と検証
6. 返信メールの送信（thank youメール、通知）
7. CCからの外部参加者の自動追加
8. チケットの機密性設定

**関連システム・外部連携**：
- Incoming Email機能（GitLabのメール受信基盤）
- メールサーバー連携（SMTP送信）
- カスタムメールドメイン連携
- WorkItems/Issues システムとの連携

**権限による制御**：
- サービスデスク設定の変更：`admin_project`権限（Maintainer以上）
- サービスデスクが有効な場合、メール送信者は誰でもイシューを作成可能
- 作成されるイシューの作成者はSupport Bot（内部ユーザー）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | プロジェクト設定 > サービスデスク | 主機能 | サービスデスクの有効化・設定 |

## 機能種別

設定管理 / メール処理 / イシュー自動作成

## 入力仕様

### 入力パラメータ（設定）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| service_desk_enabled | Boolean | No | サービスデスクの有効/無効 | - |
| issue_template_key | String | No | 使用するイシューテンプレート名 | テンプレートが存在すること |
| outgoing_name | String | No | 送信メールの差出人名 | 最大255文字 |
| project_key | String | No | カスタムメールアドレス用のプロジェクトキー | 小文字英数字とアンダースコアのみ、最大255文字 |
| reopen_issue_on_external_participant_note | Boolean | No | 外部参加者からのノートでイシューを再オープン | - |
| add_external_participants_from_cc | Boolean | No | CCから外部参加者を自動追加 | - |
| tickets_confidential_by_default | Boolean | No | チケットをデフォルトで機密に | - |

### 入力データソース（メール）

- 受信メール（専用メールアドレス宛て）
  - From: 送信者のメールアドレス
  - Subject: イシューのタイトルになる
  - Body: イシューの説明になる
  - CC: 外部参加者として追加される（設定時）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| service_desk_address | String | サービスデスク用のメールアドレス |
| service_desk_enabled | Boolean | サービスデスクの有効状態 |
| issue_template_key | String | 設定されているテンプレート名 |
| template_file_missing | Boolean | テンプレートファイルが見つからない場合true |
| outgoing_name | String | 送信メールの差出人名 |
| project_key | String | プロジェクトキー |
| custom_email | String | カスタムメールアドレス |
| custom_email_enabled | Boolean | カスタムメールの有効状態 |

### 出力先

- 画面表示（設定画面）
- JSON レスポンス（API）
- 自動生成されるイシュー
- 送信メール（thank youメール、通知）

## 処理フロー

### 処理シーケンス（メール受信からイシュー作成）

```
1. メール受信
   └─ Incoming Email基盤でメールを受信
2. ハンドラー選択
   └─ ServiceDeskHandler がメールを処理
3. プロジェクト特定
   └─ メールアドレスからプロジェクトを特定
4. サービスデスク有効性チェック
   └─ プロジェクトでサービスデスクが有効か確認
5. 返信メールチェック
   └─ In-Reply-To ヘッダーで既存イシューへの返信か判定
6. イシュー作成/ノート作成
   ├─ 新規メール: WorkItems::CreateService でイシュー作成
   └─ 返信メール: Notes::CreateService でノート作成
7. テンプレート適用
   └─ 設定されたテンプレートをイシュー説明に追加
8. 外部参加者追加
   └─ 送信者とCC（設定時）を外部参加者として登録
9. Thank Youメール送信
   └─ 新規イシュー作成時に自動返信
```

### フローチャート

```mermaid
flowchart TD
    A[メール受信] --> B{サービスデスク有効?}
    B -->|No| C[処理終了]
    B -->|Yes| D{カスタムメール検証?}

    D -->|Yes| E[検証処理を実行]
    E --> C

    D -->|No| F{返信メール?}
    F -->|Yes| G[既存イシューにノート追加]
    F -->|No| H[新規イシュー作成]

    H --> I{テンプレート設定あり?}
    I -->|Yes| J[テンプレート内容を追加]
    I -->|No| K[メール本文のみ]

    J --> L[外部参加者追加]
    K --> L
    G --> M[外部参加者追加（設定時）]

    L --> N[Thank Youメール送信]
    M --> O[処理完了]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-44-001 | サービスデスク前提条件 | Incoming Emailが有効かつワイルドカードサポートが必要 | 機能有効化時 |
| BR-44-002 | 公開プロジェクト機密性 | 公開プロジェクトのチケットは常に機密 | イシュー作成時 |
| BR-44-003 | プロジェクトキー一意性 | 同じスラッグを持つプロジェクト間でプロジェクトキーは一意 | 設定保存時 |
| BR-44-004 | カスタムメール検証 | カスタムメールを有効にする前に検証プロセスを完了する必要がある | カスタムメール有効化時 |
| BR-44-005 | 作成者はSupport Bot | サービスデスク経由で作成されるイシューの作成者はSupport Bot | イシュー作成時 |
| BR-44-006 | 未来日時の検証メール除外 | カスタムメール検証用のメールはチケットを作成しない | メール受信時 |

### 計算ロジック

**サービスデスクアドレスの生成**：
- 形式: `incoming+{project_slug}-{project_id}-issue-@{incoming_email_domain}`
- カスタムキー使用時: `incoming+{project_slug}-{project_key}@{incoming_email_domain}`

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定更新 | service_desk_settings | INSERT/UPDATE | サービスデスク設定の保存 |
| イシュー作成 | issues | INSERT | メールからイシューを作成 |
| イシュー作成 | issue_emails | INSERT | メールIDとイシューの関連付け |
| 参加者追加 | issue_email_participants | INSERT | 外部参加者の登録 |

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

#### service_desk_settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | project_id | プロジェクトID | 必須 |
| INSERT/UPDATE | issue_template_key | テンプレート名 | 任意 |
| INSERT/UPDATE | outgoing_name | 差出人名 | 最大255文字 |
| INSERT/UPDATE | project_key | プロジェクトキー | 小文字英数字とアンダースコア |
| INSERT/UPDATE | custom_email | カスタムメールアドレス | ユニーク |
| INSERT/UPDATE | custom_email_enabled | カスタムメール有効フラグ | - |
| INSERT/UPDATE | tickets_confidential_by_default | 機密デフォルトフラグ | - |
| INSERT/UPDATE | reopen_issue_on_external_participant_note | 再オープンフラグ | - |
| INSERT/UPDATE | add_external_participants_from_cc | CC追加フラグ | - |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Project Not Found | メールアドレスからプロジェクトを特定できない | 正しいメールアドレスを使用 |
| 422 | Validation Error | 設定パラメータが不正 | エラーメッセージに従い修正 |
| - | Template Not Found | 指定されたテンプレートが存在しない | テンプレートを作成するか設定を変更 |
| - | InvalidIssueError | イシュー作成に失敗 | ログを確認 |

### リトライ仕様

- メール処理はバックグラウンドジョブ（ServiceDeskEmailReceiverWorker）で実行
- 失敗時はSidekiqのリトライ機構に依存

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

- 設定更新は単一レコード操作のため暗黙のトランザクション
- イシュー作成はWorkItems::CreateService内でトランザクション管理

## パフォーマンス要件

- メール処理はバックグラウンドジョブで非同期実行
- 設定画面の応答：500ms以内

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

- **認証・認可**：設定変更はadmin_project権限が必要
- **メール検証**：カスタムメール設定時は検証プロセスを経由
- **機密性制御**：公開プロジェクトのチケットは自動的に機密
- **スパム対策**：perform_spam_check: falseでスパムチェックをスキップ（Support Bot経由）

## 備考

- サービスデスクはIncoming Email機能が前提条件
- カスタムメール機能は検証プロセスを経て有効化される
- Support Botはorganization_idごとに存在する内部ユーザー

---

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

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

### 推奨読解順序

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

サービスデスクの設定モデルと有効性判定を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | service_desk.rb | `app/models/service_desk.rb` | サービスデスクの有効性判定（enabled?、supported?） |
| 1-2 | service_desk_setting.rb | `app/models/service_desk_setting.rb` | 設定モデルの属性、バリデーション |

**読解のコツ**:
- `service_desk.rb`の`enabled?`（8-12行目）でサービスデスク有効性を判定
- `supported?`（14-17行目）でIncoming Email基盤の前提条件をチェック
- `service_desk_setting.rb`の各validateでビジネスルールを実装

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

設定画面のコントローラーを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | service_desk_controller.rb | `app/controllers/projects/service_desk_controller.rb` | 設定の取得・更新 |

**主要処理フロー**:
1. **4行目**: before_action :authorize_admin_project! - 権限チェック
2. **9-11行目**: show - 現在の設定をJSON返却
3. **13-23行目**: update - 設定更新、UpdateService呼び出し
4. **42-56行目**: service_desk_attributes - 返却するJSON属性を構築

#### Step 3: メール処理を理解する

メール受信からイシュー作成までの流れを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | service_desk_handler.rb | `lib/gitlab/email/handler/service_desk_handler.rb` | メール処理のコアロジック |

**主要処理フロー**:
- **28-30行目**: can_handle? - このハンドラーで処理可能か判定
- **32-43行目**: execute - メイン処理（イシュー作成/ノート作成/thank youメール）
- **109-115行目**: create_work_item_or_note - 新規か返信かで分岐
- **126-156行目**: create_work_item! - WorkItems::CreateServiceでイシュー作成
- **180-189行目**: message_including_template - テンプレート内容を追加
- **237-246行目**: add_email_participants - 外部参加者追加
- **264-268行目**: ticket_confidential? - 機密性判定

#### Step 4: 設定更新サービスを理解する

設定更新のビジネスロジックを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | update_service.rb | `app/services/service_desk_settings/update_service.rb` | 設定更新ロジック |

**主要処理フロー**:
- **7-27行目**: execute - 設定の検索または作成、更新処理

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

```
メール受信 (Incoming Email基盤)
    │
    └─ ServiceDeskEmailReceiverWorker
           │
           └─ Gitlab::Email::Handler::ServiceDeskHandler#execute
                  │
                  ├─ can_handle? (サービスデスク有効性チェック)
                  │
                  ├─ create_work_item_or_note
                  │      │
                  │      ├─ 新規: create_work_item!
                  │      │      └─ WorkItems::CreateService#execute
                  │      │             └─ Issue作成
                  │      │
                  │      └─ 返信: create_note_from_reply_email
                  │             └─ Notes::CreateService#execute
                  │
                  ├─ add_email_participants
                  │      └─ IssueEmailParticipants::CreateService
                  │
                  └─ send_thank_you_email
                         └─ Notify.service_desk_thank_you_email

設定画面
    │
    └─ Projects::ServiceDeskController
           │
           ├─ #show → service_desk_attributes → JSON
           │
           └─ #update
                  ├─ Projects::UpdateService (service_desk_enabled)
                  └─ ServiceDeskSettings::UpdateService (その他設定)
```

### データフロー図

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

受信メール ─────────────▶ ServiceDeskHandler ────────────▶ Issue/WorkItem
                                  │
                                  ├─ template適用
                                  │
                                  ├─ 外部参加者登録
                                  │
                                  └─ thank youメール ─────▶ 送信者へメール

設定画面 ──────────────▶ ServiceDeskController ──────────▶ JSON レスポンス
                                  │
                                  └─ UpdateService
                                         │
                                         ▼
                                  service_desk_settings
                                  テーブル
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| service_desk.rb | `app/models/service_desk.rb` | モジュール | 有効性判定 |
| service_desk_setting.rb | `app/models/service_desk_setting.rb` | モデル | 設定データモデル |
| service_desk_controller.rb | `app/controllers/projects/service_desk_controller.rb` | コントローラー | 設定画面のAPI |
| service_desk_handler.rb | `lib/gitlab/email/handler/service_desk_handler.rb` | ハンドラー | メール処理のコアロジック |
| update_service.rb | `app/services/service_desk_settings/update_service.rb` | サービス | 設定更新ロジック |
| service_desk_email_receiver_worker.rb | `app/workers/service_desk_email_receiver_worker.rb` | ワーカー | メール受信の非同期処理 |
| service_desk.rb | `app/mailers/emails/service_desk.rb` | メーラー | メール送信テンプレート |
| custom_email_credential.rb | `app/models/service_desk/custom_email_credential.rb` | モデル | カスタムメール認証情報 |
| custom_email_verification.rb | `app/models/service_desk/custom_email_verification.rb` | モデル | カスタムメール検証状態 |
