# 通知設計書 73-repository_rewrite_history_success_email

## 概要

本ドキュメントは、GitLabのリポジトリ履歴書き換え処理が正常に完了した際に送信されるメール通知 `repository_rewrite_history_success_email` の設計仕様を定義する。

### 本通知の処理概要

本通知は、プロジェクトのリポジトリ履歴書き換え処理（RewriteHistory RPC経由でのBLOB削除やテキスト置換）が正常に完了したことをユーザーに通知するメール機能を提供する。

**業務上の目的・背景**：リポジトリ履歴の書き換えは、誤ってコミットされたセンシティブなデータ（パスワード、APIキー等）の削除や、大きなファイルの履歴からの完全削除に使用される重要なセキュリティ・保守操作である。この処理は非同期で実行され、完了までに時間がかかる可能性があるため、処理完了をユーザーに通知することで、ユーザーは次のアクション（リポジトリサイズの確認、チームへのクローン再取得依頼など）を取ることができる。

**通知の送信タイミング**：リポジトリ履歴書き換えワーカー（`Repositories::RewriteHistoryWorker`）が処理を正常に完了した直後に送信される。具体的には、RewriteHistory RPCの実行が成功し、監査ログが記録された後にトリガーされる。

**通知の受信者**：履歴書き換え処理を開始したユーザー（current_user）に送信される。ユーザーはプロジェクトに対するオーナー権限を持っている必要がある。

**通知内容の概要**：履歴書き換えが正常に完了したこと、対象プロジェクトのURL、および現在のリポジトリサイズを含む成功通知メールである。

**期待されるアクション**：受信者はリポジトリの履歴が正常に書き換えられたことを確認し、リポジトリサイズの変化を確認する。また、チームメンバーに対して、ローカルクローンの再取得（git clone --mirror等）を依頼することが推奨される。

## 通知種別

メール通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later） |
| 優先度 | 中 |
| リトライ | Sidekiqのデフォルトリトライ機構に従う |

### 送信先決定ロジック

履歴書き換え処理を開始したユーザー（`user`パラメータ）の通知用メールアドレスに送信される。メールアドレスは `user.notification_email_for(project.group)` メソッドで決定される。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | GitLabのデフォルト送信元アドレス |
| 送信元名称 | GitLab |
| 件名 | `[Project Name] Project history rewrite has completed` |
| 形式 | HTML/テキスト |

### 本文テンプレート

```html
<p>
  Repository history rewrite succeeded on {project_web_url}.
</p>
<p>
  Repository size is now {repository_size} MiB.
</p>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @project | 対象プロジェクト | パラメータから取得 | Yes |
| @project.web_url | プロジェクトURL | プロジェクトモデルから取得 | Yes |
| @project.repository.size | リポジトリサイズ（MiB） | リポジトリから取得 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| バックグラウンドジョブ | RewriteHistoryWorker完了 | 履歴書き換え処理が正常終了 | Sidekiqワーカーによる非同期処理完了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| プロジェクトのメール無効化 | `project.emails_disabled?` がtrueの場合、通知は送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ユーザーが履歴書き換えをリクエスト] --> B[RewriteHistoryService.async_execute実行]
    B --> C[RewriteHistoryWorkerをキューに追加]
    C --> D[ワーカーがRewriteHistoryService.execute実行]
    D --> E[リポジトリを読み取り専用に設定]
    E --> F[RewriteHistory RPC実行]
    F --> G{処理成功?}
    G -->|Yes| H[監査ログ記録]
    H --> I[リポジトリを書き込み可能に戻す]
    I --> J[NotificationService.repository_rewrite_history_success呼び出し]
    J --> K{プロジェクトのメール有効?}
    K -->|Yes| L[成功通知メール送信]
    K -->|No| M[送信スキップ]
    L --> N[終了]
    M --> N
    G -->|No| O[失敗通知処理へ]
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| projects | プロジェクト情報取得 | メール無効化フラグ確認、リポジトリサイズ取得 |
| users | ユーザー情報取得 | 通知先メールアドレス取得 |
| namespaces | グループ情報取得 | 通知メールアドレス決定用 |

### テーブル別参照項目詳細

#### projects

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | プロジェクト識別 | パラメータで指定されたproject_id |
| name | プロジェクト名表示 | - |
| emails_disabled | メール送信可否判定 | - |
| namespace_id | グループ情報取得 | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| audit_events | INSERT | 履歴書き換え操作の監査ログ |

#### 監査イベントテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | name | 'project_blobs_removal' または 'project_text_replacement' | 操作種別に応じて |
| INSERT | author | current_user | 操作実行者 |
| INSERT | target | project | 対象プロジェクト |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー | Sidekiqによるリトライ |
| 宛先不正 | ユーザーのメールアドレスが無効 | エラーログ記録、送信スキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト（25回） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | 一時的なネットワークエラー等 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | GitLabのデフォルト設定に従う |
| 1日あたり上限 | GitLabのデフォルト設定に従う |

### 配信時間帯

特に制限なし。履歴書き換え完了時に即時送信される。

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

- 通知は履歴書き換えを実行したユーザー本人にのみ送信される
- 削除されたBLOBのOID等のセンシティブな情報は含まれない
- プロジェクトURLとサイズのみを通知
- 操作は監査ログに記録される

## 備考

- 履歴書き換えにはオーナー権限が必要
- 処理中はリポジトリが読み取り専用モードになる
- 履歴書き換え後、全てのクローンは無効になるため、再取得が必要
- 書き換え失敗時は別途 `repository_rewrite_history_failure_email` が送信される

---

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

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

### 推奨読解順序

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

まず、通知に必要なデータモデルを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | project.rb | `app/models/project.rb` | プロジェクトモデルの構造、repositoryメソッド |
| 1-2 | user.rb | `app/models/user.rb` | ユーザーモデル、notification_email_for メソッド |

**読解のコツ**: Railsのモデルクラスを理解し、リポジトリサイズの取得方法を確認する。

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

処理の起点となるワーカークラスを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rewrite_history_worker.rb | `app/workers/repositories/rewrite_history_worker.rb` | ワーカーのperformメソッドがエントリーポイント |

**主要処理フロー**:
1. **13-30行目**: performメソッドでRewriteHistoryServiceを実行
2. **27行目**: 成功時にnotification_service.repository_rewrite_history_successを呼び出す
3. **29行目**: 失敗時にnotification_service.repository_rewrite_history_failureを呼び出す

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

履歴書き換えの実際の処理を行うサービスクラス。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | rewrite_history_service.rb | `app/services/repositories/rewrite_history_service.rb` | RewriteHistory RPCの呼び出しロジック |

**主要処理フロー**:
- **8-16行目**: executeメソッドで入力検証、読み取り専用設定、履歴書き換え実行
- **18-30行目**: async_executeメソッドでワーカーをキューに追加
- **52-64行目**: rewrite_historyメソッドで実際のGitaly RPC呼び出し
- **66-89行目**: 監査ログの記録

#### Step 4: 通知サービスを理解する

通知の送信ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | notification_service.rb | `app/services/notification_service.rb` | repository_rewrite_history_successメソッド（656-660行目） |

**主要処理フロー**:
- **656-660行目**: プロジェクトのメール無効化チェック後、メーラーを呼び出す

#### Step 5: メーラーを理解する

実際のメール生成処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | projects.rb | `app/mailers/emails/projects.rb` | repository_rewrite_history_success_emailメソッド（65-72行目） |

**主要処理フロー**:
- **65-72行目**: メールの送信先、件名を設定してemail_with_layoutで送信

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

メール本文のテンプレートを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 6-1 | repository_rewrite_history_success_email.html.haml | `app/views/notify/repository_rewrite_history_success_email.html.haml` | メール本文のテンプレート |

**テンプレート内容**:
- **1-2行目**: プロジェクトURLを含む成功メッセージ
- **3-4行目**: 現在のリポジトリサイズをMiB単位で表示

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

```
Repositories::RewriteHistoryWorker#perform
    │
    ├─ Repositories::RewriteHistoryService#execute
    │      ├─ validate_input
    │      ├─ mark_repository_read_only
    │      ├─ rewrite_history (Gitaly RPC)
    │      ├─ audit_removals / audit_replacements
    │      └─ set_repository_writable!
    │
    └─ NotificationService#repository_rewrite_history_success
           └─ Notify#repository_rewrite_history_success_email
                  └─ email_with_layout
```

### データフロー図

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

project_id, user_id ──▶ RewriteHistoryWorker ──────────▶ メール送信
blob_oids, redactions          │
                               ├─ RewriteHistoryService
                               │      ├─ Gitaly RPC
                               │      └─ 監査ログ
                               │
                               └─ NotificationService
                                      └─ Notify (Mailer)
                                             └─ プロジェクトURL
                                                リポジトリサイズ
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| rewrite_history_worker.rb | `app/workers/repositories/rewrite_history_worker.rb` | ソース | バックグラウンドジョブ処理 |
| rewrite_history_service.rb | `app/services/repositories/rewrite_history_service.rb` | ソース | 履歴書き換え実行サービス |
| notification_service.rb | `app/services/notification_service.rb` | ソース | 通知送信サービス |
| projects.rb | `app/mailers/emails/projects.rb` | ソース | メール生成メーラー |
| repository_rewrite_history_success_email.html.haml | `app/views/notify/repository_rewrite_history_success_email.html.haml` | テンプレート | メール本文テンプレート |
