# 機能設計書 45-インシデント管理

## 概要

本ドキュメントは、GitLabにおけるインシデント管理機能の設計仕様を定義する。インシデント管理は、サービス障害やシステム異常が発生した際に、問題の追跡、対応状況の管理、タイムライン記録を行い、迅速な解決と再発防止を支援する機能である。

### 本機能の処理概要

**業務上の目的・背景**：本番システムの運用において、サービス障害やパフォーマンス問題が発生した場合、迅速な対応と正確な記録が必要である。インシデント管理機能は、障害発生から解決までの一連のプロセスをGitLab上で管理し、関係者間の情報共有を促進する。また、インシデント対応のタイムライン記録により、事後分析（ポストモーテム）や改善活動に活用できる。

**機能の利用シーン**：
- モニタリングシステムからアラートを受け、インシデントを作成する場面
- SREチームがインシデントの状態（Triggered/Acknowledged/Resolved）を更新する場面
- 対応者がタイムラインにイベントを記録しながら障害対応を進める場面
- インシデント解決後にタイムラインを確認し、ポストモーテムを作成する場面
- PagerDutyなど外部サービスと連携してインシデントを管理する場面

**主要な処理内容**：
1. インシデント（issue_type: incident）の作成
2. エスカレーションステータスの管理（Triggered/Acknowledged/Resolved/Ignored）
3. タイムラインイベントの作成・編集・削除
4. インシデント重大度（Severity）の設定
5. アラートとインシデントの紐付け
6. タイムラインイベントタグの管理
7. 自動タイムラインイベント生成（作成、再オープン、解決、ステータス変更時）

**関連システム・外部連携**：
- アラート管理（AlertManagement）との連携
- PagerDuty連携
- Slack連携（インシデントモーダル）
- GraphQL APIによる操作

**権限による制御**：
- インシデントの閲覧：`read_issue`権限
- インシデントの作成：`create_issue`権限
- タイムラインイベントの操作：`admin_incident_management_timeline_event`権限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 98 | インシデント一覧 | 主機能 | インシデントの一覧表示 |
| 99 | インシデント詳細 | 主機能 | インシデントの詳細表示 |

## 機能種別

CRUD操作 / 状態管理 / タイムライン管理

## 入力仕様

### 入力パラメータ（インシデント作成）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| title | String | Yes | インシデントのタイトル | 必須 |
| description | Text | No | インシデントの説明 | - |
| severity | String | No | 重大度 | critical/high/medium/low/unknown |
| alert | Alert | No | 関連するアラート | - |

### 入力パラメータ（タイムラインイベント）

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| note | String | Yes | イベントのノート内容 | 最大280文字（ユーザー入力時）、最大10,000文字（自動生成時） |
| occurred_at | DateTime | Yes | イベント発生日時 | 必須 |
| action | String | No | イベントの種類 | 最大128文字、デフォルト'comment' |
| timeline_event_tag_names | Array[String] | No | イベントタグ名 | 存在するタグまたは定義済みタグ |

### 入力データソース

- 画面入力
- GraphQL API
- アラート連携（自動作成）
- PagerDuty Webhook
- Slack連携

## 出力仕様

### 出力データ（インシデント）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | インシデント（イシュー）のID |
| iid | Integer | プロジェクト内でのインシデント番号 |
| title | String | タイトル |
| description | Text | 説明 |
| state | String | 状態（opened/closed） |
| severity | String | 重大度 |
| escalation_status | String | エスカレーションステータス |

### 出力データ（タイムラインイベント）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | タイムラインイベントID |
| note | String | ノート内容 |
| note_html | String | HTML形式のノート |
| occurred_at | DateTime | イベント発生日時 |
| action | String | イベントの種類 |
| author_id | Integer | 作成者ID |
| editable | Boolean | 編集可能フラグ |

### 出力先

- 画面表示（インシデント詳細、タイムライン）
- JSON/GraphQL レスポンス
- システムノート

## 処理フロー

### 処理シーケンス

```
1. インシデント作成
   └─ Issues::CreateService に issue_type: 'incident' で委譲
2. エスカレーションステータス初期化
   └─ IssuableEscalationStatus 作成（status: triggered）
3. 自動タイムラインイベント作成
   └─ 「@user created the incident」イベント追加
4. アラート紐付け（ある場合）
   └─ AlertManagement::Alert との関連付け
5. ステータス変更時
   ├─ 状態遷移（trigger/acknowledge/resolve/ignore）
   └─ 自動タイムラインイベント作成
6. タイムラインイベント追加
   ├─ ノート内容の保存
   ├─ タグの紐付け
   └─ システムノート作成
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{操作種別}
    B -->|インシデント作成| C[CreateService実行]
    B -->|ステータス変更| D[状態遷移]
    B -->|タイムライン追加| E[TimelineEvents::CreateService]

    C --> F[Issues::CreateService]
    F --> G[EscalationStatus作成]
    G --> H[自動タイムラインイベント]

    D --> I{新ステータス}
    I -->|Acknowledged| J[acknowledge イベント]
    I -->|Resolved| K[resolve イベント]
    I -->|Ignored| L[ignore イベント]

    J --> M[自動タイムラインイベント]
    K --> M
    L --> M

    E --> N{バリデーション}
    N -->|成功| O[TimelineEvent保存]
    N -->|失敗| P[エラー返却]

    O --> Q[タグリンク作成]
    Q --> R[システムノート]
    R --> S[終了]

    H --> S
    M --> S
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-45-001 | インシデントタイプ | インシデントは issue_type = 'incident' のイシューとして作成される | 作成時 |
| BR-45-002 | ステータス遷移 | Triggered -> Acknowledged -> Resolved のフローが推奨されるが、任意のステータスへ遷移可能 | ステータス変更時 |
| BR-45-003 | 解決時刻 | Resolved ステータスへ遷移時、resolved_at が設定される | Resolve時 |
| BR-45-004 | 自動タイムラインイベント | インシデント作成、再オープン、解決、ステータス変更、重大度変更時に自動でタイムラインイベントが作成される | 各イベント発生時 |
| BR-45-005 | ユーザー入力ノート長 | ユーザーが入力するタイムラインイベントのノートは280文字以内 | タイムライン作成時 |
| BR-45-006 | 定義済みタグ | 定義済みタグ（PREDEFINED_TAGS）は存在しなくても自動作成される | タグ指定時 |

### 計算ロジック

**エスカレーションステータス値**：
- triggered: 0 - 調査開始前
- acknowledged: 1 - 誰かが積極的に調査中
- resolved: 2 - 問題が解決済み
- ignored: 3 - アクション不要

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インシデント作成 | issues | INSERT | issue_type = 'incident' でイシュー作成 |
| インシデント作成 | incident_management_issuable_escalation_statuses | INSERT | エスカレーションステータス初期化 |
| タイムライン追加 | incident_management_timeline_events | INSERT | タイムラインイベント作成 |
| タグ紐付け | incident_management_timeline_event_tag_links | INSERT | タイムラインイベントとタグの紐付け |
| ステータス変更 | incident_management_issuable_escalation_statuses | UPDATE | ステータス更新 |

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

#### incident_management_timeline_events

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | project_id | プロジェクトID | 必須 |
| INSERT | issue_id | インシデント（イシュー）ID | 必須 |
| INSERT | author_id | 作成者ユーザーID | 必須 |
| INSERT | note | ノート内容 | 必須、最大10,000文字 |
| INSERT | note_html | HTML形式のノート | 最大10,000文字 |
| INSERT | occurred_at | イベント発生日時 | 必須 |
| INSERT | action | イベント種別 | デフォルト'comment'、最大128文字 |
| INSERT | editable | 編集可能フラグ | デフォルトfalse |

#### incident_management_issuable_escalation_statuses

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | issue_id | インシデント（イシュー）ID | 必須、ユニーク |
| INSERT | status | 0 (triggered) | 初期値 |
| UPDATE | status | 0/1/2/3 | 状態遷移時 |
| UPDATE | resolved_at | 現在日時 | Resolvedへ遷移時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 404 | Not Found | インシデントが存在しない | インシデントIDを確認 |
| 403 | Forbidden | 操作権限がない | 適切な権限を持つユーザーで操作 |
| 422 | Validation Error | バリデーションエラー | エラーメッセージに従い修正 |
| - | Tags Not Found | 指定されたタグが存在しない | タグ名を確認するか定義済みタグを使用 |

### リトライ仕様

- 特別なリトライ処理は実装されていない

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

- インシデント作成はIssues::CreateService内でトランザクション管理
- タイムラインイベント作成は単一レコード操作後にタグリンクを一括挿入

## パフォーマンス要件

- インシデント一覧取得：1秒以内
- タイムラインイベント取得：500ms以内

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

- **認証・認可**：すべての操作で認証必須、権限チェック実施
- **自動生成イベント**：auto_created フラグで権限チェックをスキップ可能（内部処理のみ）
- **スパムチェック**：インシデント作成時はperform_spam_check: falseでスキップ

## 備考

- インシデントはイシューの特殊タイプ（issue_type = 'incident'）として実装
- EE版ではエスカレーションポリシー機能が追加される
- WorkItemsへの移行が進行中

---

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

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

### 推奨読解順序

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

インシデント関連のモデルを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | escalatable.rb | `app/models/concerns/incident_management/escalatable.rb` | エスカレーションステータスの状態遷移を理解 |
| 1-2 | issuable_escalation_status.rb | `app/models/incident_management/issuable_escalation_status.rb` | インシデントのエスカレーションステータスモデル |
| 1-3 | timeline_event.rb | `app/models/incident_management/timeline_event.rb` | タイムラインイベントモデル |

**読解のコツ**:
- `escalatable.rb`の`STATUSES`（16-21行目）で4つのステータス値を定義
- `state_machine :status`（41-80行目）で状態遷移を定義
- `timeline_event.rb`の`validates :note`（22-24行目）で文字数制限

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

コントローラーの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | incidents_controller.rb | `app/controllers/projects/incidents_controller.rb` | インシデント一覧・詳細表示 |

**主要処理フロー**:
1. **8行目**: before_action :authorize_read_issue! - 閲覧権限チェック
2. **43-45行目**: incident_finder - IssuesFinderにissue_types: :incidentを指定
3. **22-31行目**: incident - イシューをインシデントとして取得

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

ビジネスロジックを担当するサービスクラスを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | create_service.rb (incidents) | `app/services/incident_management/incidents/create_service.rb` | インシデント作成ロジック |
| 3-2 | create_service.rb (timeline_events) | `app/services/incident_management/timeline_events/create_service.rb` | タイムラインイベント作成 |

**主要処理フロー**:
- **incidents/create_service.rb 17-36行目**: execute - Issues::CreateServiceに委譲、issue_type: 'incident'を指定
- **timeline_events/create_service.rb 18-79行目**: クラスメソッドで自動タイムラインイベント生成（create_incident、resolve_incident等）
- **timeline_events/create_service.rb 82-114行目**: execute - タイムラインイベント作成、タグリンク、システムノート

#### Step 4: 自動タイムラインイベントを理解する

インシデントライフサイクルに応じた自動イベント生成を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | create_service.rb | `app/services/incident_management/timeline_events/create_service.rb` | 各種クラスメソッド |

**主要処理フロー**:
- **19-25行目**: create_incident - インシデント作成時の自動イベント
- **27-33行目**: reopen_incident - 再オープン時の自動イベント
- **35-41行目**: resolve_incident - 解決時の自動イベント
- **43-50行目**: change_incident_status - ステータス変更時の自動イベント
- **52-59行目**: change_severity - 重大度変更時の自動イベント

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

```
Projects::IncidentsController
    │
    ├─ #index
    │      └─ incident_finder (IssuesFinder with issue_types: :incident)
    │
    └─ #show
           └─ load_incident
                  └─ incident (IssuesFinder.execute)

IncidentManagement::Incidents::CreateService
    │
    └─ #execute
           └─ Issues::CreateService
                  └─ issue_type: 'incident'
                         │
                         └─ 自動: TimelineEvents::CreateService.create_incident

IncidentManagement::TimelineEvents::CreateService
    │
    ├─ .create_incident (クラスメソッド)
    ├─ .reopen_incident (クラスメソッド)
    ├─ .resolve_incident (クラスメソッド)
    ├─ .change_incident_status (クラスメソッド)
    ├─ .change_severity (クラスメソッド)
    │
    └─ #execute
           ├─ TimelineEvent.save
           ├─ create_timeline_event_tag_links
           └─ SystemNoteService.add_timeline_event
```

### データフロー図

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

アラート ──────────────▶ Incidents::CreateService ──────▶ Issue (incident)
                                  │
GraphQL ──────────────────▶      │
                                  ▼
PagerDuty ────────────────▶ Issues::CreateService
                                  │
                                  ├─ issue_type: 'incident'
                                  │
                                  └─ EscalationStatus
                                         │
                                         ▼
                                  TimelineEvents::CreateService
                                         │
                                         ▼
                                  incident_management_timeline_events
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| escalatable.rb | `app/models/concerns/incident_management/escalatable.rb` | Concern | エスカレーションステータス状態管理 |
| issuable_escalation_status.rb | `app/models/incident_management/issuable_escalation_status.rb` | モデル | インシデントのエスカレーションステータス |
| timeline_event.rb | `app/models/incident_management/timeline_event.rb` | モデル | タイムラインイベント |
| timeline_event_tag.rb | `app/models/incident_management/timeline_event_tag.rb` | モデル | タイムラインイベントタグ |
| incidents_controller.rb | `app/controllers/projects/incidents_controller.rb` | コントローラー | インシデント一覧・詳細 |
| create_service.rb | `app/services/incident_management/incidents/create_service.rb` | サービス | インシデント作成 |
| create_service.rb | `app/services/incident_management/timeline_events/create_service.rb` | サービス | タイムラインイベント作成 |
| update_service.rb | `app/services/incident_management/timeline_events/update_service.rb` | サービス | タイムラインイベント更新 |
| destroy_service.rb | `app/services/incident_management/timeline_events/destroy_service.rb` | サービス | タイムラインイベント削除 |
| close_incident_worker.rb | `app/workers/incident_management/close_incident_worker.rb` | ワーカー | インシデントクローズの非同期処理 |
| timeline_event_type.rb | `app/graphql/types/incident_management/timeline_event_type.rb` | GraphQL | タイムラインイベント型定義 |
