# 通知設計書 12-rateLimited

## 概要

本ドキュメントは、Etherpadにおけるレート制限通知「rateLimited」の設計仕様を定義する。この通知は、クライアントがサーバーへ過剰なメッセージを送信した際に、レート制限によって接続が切断されたことをユーザーに通知するモーダルダイアログである。

### 本通知の処理概要

この通知はサーバーのレート制限機構によって接続が強制切断された際に、ユーザーにその原因を明確に伝えるためのアプリ内モーダル通知である。

**業務上の目的・背景**：共同編集環境において、サーバーリソースの保護とサービスの安定性維持は重要である。悪意のある攻撃や、バグによる過剰なメッセージ送信からサーバーを守るため、レート制限が実装されている。この通知により、ユーザーは接続切断の原因がレート制限であることを理解し、過剰な操作を控える、あるいはしばらく待ってから再接続するなどの適切な対応を取ることができる。

**通知の送信タイミング**：サーバー側の`handleMessage`関数内で、`RateLimiterMemory`によるレート制限チェックが行われる。production環境において、IPアドレスごとのメッセージ送信レートが設定値を超過した場合、`{disconnect: 'rateLimited'}`メッセージがクライアントに送信される。このチェックは各メッセージ受信時に行われる。

**通知の受信者**：レート制限に抵触した特定のクライアント（IPアドレス単位）。ブロードキャストではなく、該当するソケットに対してのみ送信される。

**通知内容の概要**：「Rate Limited.」というタイトルと「You sent too many messages to this pad so it disconnected you.」という説明文が表示される。これらのテキストは多言語対応しており、ローカライズファイルから取得される。

**期待されるアクション**：ユーザーはこの通知を確認し、過剰な操作を行ったことを認識する。しばらく時間をおいてからページをリロードして再接続することが推奨される。

## 通知種別

アプリ内通知（モーダルダイアログ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（WebSocket経由のリアルタイム通知） |
| 優先度 | 高 |
| リトライ | 無 |

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

レート制限に抵触した特定のソケットに対してのみ`socket.emit('message', {disconnect: 'rateLimited'})`で送信される。IPアドレス単位でのレート制限であるため、同一IPから複数のセッションがある場合、最初に制限に抵触したセッションが切断される。

## 通知テンプレート

### モーダル通知の場合

| 項目 | 内容 |
|-----|------|
| タイトル | pad.modals.rateLimited（ローカライズキー） |
| メッセージ | pad.modals.rateLimited.explanation（ローカライズキー） |
| 表示形式 | モーダルダイアログ + オーバーレイ |

### 本文テンプレート

```html
<div class="rateLimited">
  <h1 data-l10n-id="pad.modals.rateLimited"></h1>
  <p data-l10n-id="pad.modals.rateLimited.explanation"></p>
</div>
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| pad.modals.rateLimited | 通知タイトル「Rate Limited.」 | src/locales/*.json | Yes |
| pad.modals.rateLimited.explanation | 説明文「You sent too many messages to this pad so it disconnected you.」 | src/locales/*.json | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| メッセージ受信 | handleMessage実行 | production環境かつレート制限超過 | RateLimiterMemory.consumeが例外をスロー |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| development環境 | NODE_ENVがproduction以外の場合はレート制限チェックがスキップされる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[クライアントからメッセージ受信] --> B{NODE_ENV === production?}
    B -->|Yes| C[rateLimiter.consume実行]
    B -->|No| D[レート制限スキップ]
    C -->|成功| E[通常のメッセージ処理]
    C -->|失敗| F[レート制限超過]
    F --> G[disconnect:rateLimited送信]
    G --> H[stats.meter記録]
    H --> I[例外スロー]
    D --> E
```

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

### 参照テーブル一覧

なし（インメモリでのレート制限）

### 更新テーブル一覧

なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| RateLimiter例外 | レート制限超過 | クライアントに通知後、処理を中断 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 設定ファイル | settings.json |
| 設定キー | commitRateLimiting |
| デフォルト値 | settings.jsで定義 |

### 配信時間帯

制限なし（レート制限は即座に適用される）

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

- レート制限はIPアドレス単位で適用される
- 設定値（points, duration）はsettings.jsonで調整可能
- ログにはIPアドレスが記録される（disableIPloggingがfalseの場合）
- DDoS攻撃やスパム行為からサーバーを保護する重要な機構

## 備考

- この通知にはForce reconnectボタンは表示されない
- 自動再接続タイマーも適用されない
- レート制限の設定値はサーバー起動時にRateLimiterMemoryに渡される
- stats.meter('rateLimited').mark()で統計情報が記録される

---

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

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

### 推奨読解順序

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

まず、レート制限の設定構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Settings.ts | `src/node/utils/Settings.ts` | commitRateLimiting設定の構造を確認 |

**読解のコツ**: settings.jsonの設定がどのようにTypeScriptの型定義と対応しているかを確認する。

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

レート制限チェックの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | PadMessageHandler.ts | `src/node/handler/PadMessageHandler.ts` | handleMessage関数（273-286行目）でのレート制限チェック |
| 2-2 | PadMessageHandler.ts | `src/node/handler/PadMessageHandler.ts` | socketio関数（69-74行目）でRateLimiterMemory初期化 |

**主要処理フロー**:
1. **274行目**: `const env = process.env.NODE_ENV || 'development'`で環境判定
2. **276行目**: `if (env === 'production')`でproduction環境のみレート制限
3. **278行目**: `await rateLimiter.consume(socket.request.ip)`でレート消費
4. **280-283行目**: 例外発生時にログ出力とメッセージ送信
5. **283行目**: `socket.emit('message', {disconnect: 'rateLimited'})`で通知

#### Step 3: クライアント側の受信処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | disconnected関数でのメッセージ処理（72行目にrateLimited含む） |
| 3-2 | pad_modals.ts | `src/static/js/pad_modals.ts` | showModal関数でモーダル表示 |

#### Step 4: HTML構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pad.html | `src/templates/pad.html` | rateLimited用のdiv要素（295-298行目）を確認 |

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

```
handleMessage(socket, message)
    │
    ├─ [production環境のみ]
    │      │
    │      └─ rateLimiter.consume(socket.request.ip)
    │             │
    │             ├─ [成功] → 通常処理続行
    │             │
    │             └─ [失敗/例外]
    │                    │
    │                    ├─ messageLogger.warn()
    │                    ├─ stats.meter('rateLimited').mark()
    │                    ├─ socket.emit({disconnect: 'rateLimited'})
    │                    └─ throw err
    │
    └─ [クライアント側]
           │
           ├─ pad_connectionstatus.disconnected('rateLimited')
           │      │
           │      └─ padmodals.showModal('rateLimited')
           │
           └─ padmodals.showOverlay()
```

### データフロー図

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

クライアントメッセージ ───▶ handleMessage ───▶ rateLimiter.consume
                                                        │
                                              ┌─────────┴─────────┐
                                              │                   │
                                           [成功]              [失敗]
                                              │                   │
                                              ▼                   ▼
                                         通常処理         disconnect:rateLimited送信
                                                                  │
                                                                  ▼
                                                         クライアント受信
                                                                  │
                                                                  ▼
                                                         モーダル表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| PadMessageHandler.ts | `src/node/handler/PadMessageHandler.ts` | ソース | サーバー側メッセージ処理、レート制限実装 |
| pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | ソース | クライアント側接続状態管理 |
| pad_modals.ts | `src/static/js/pad_modals.ts` | ソース | モーダルダイアログ表示制御 |
| pad.html | `src/templates/pad.html` | テンプレート | モーダルHTML構造定義 |
| en.json | `src/locales/en.json` | 設定 | ローカライズ文字列 |
| Settings.ts | `src/node/utils/Settings.ts` | 設定 | レート制限設定の定義 |
