# 機能設計書 55-レート制限

## 概要

本ドキュメントは、Actual Budget同期サーバーにおけるレート制限機能の設計を記述する。この機能は、APIリクエストの過負荷攻撃やサービス拒否攻撃（DoS）からサーバーを保護し、すべてのユーザーに公平なサービス提供を実現する。

### 本機能の処理概要

Actual Budget同期サーバーにおいて、クライアントからのAPIリクエストに対してレート制限を適用する機能である。express-rate-limitミドルウェアを使用し、一定時間内のリクエスト数を制限することで、サーバーリソースの保護と安定したサービス提供を実現する。

**業務上の目的・背景**：同期サーバーは複数のユーザーが同時にアクセスする可能性があり、特定のクライアントからの過剰なリクエストによってサーバーが過負荷状態になることを防ぐ必要がある。また、悪意のある攻撃（DDoS等）からサーバーを保護し、正当なユーザーへのサービス継続性を確保する。

**機能の利用シーン**：
- 通常の同期操作時のレート制限適用
- 大量のAPIリクエストからの保護
- サーバーリソースの公平な配分

**主要な処理内容**：
1. 各クライアントIPアドレスごとのリクエスト数追跡
2. 制限超過時のリクエスト拒否（429 Too Many Requests）
3. 標準ヘッダー（RateLimit-*）によるレート情報の通知
4. ウィンドウベースのリクエストカウント管理

**関連システム・外部連携**：特になし（サーバー内部機能）

**権限による制御**：すべてのリクエストに対して均等に適用。開発環境では無効化可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | なし | - | バックエンド機能のため直接関連する画面なし |

## 機能種別

サーバー機能 / セキュリティ・保護

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| リクエスト元IP | string | Yes | クライアントIPアドレス | 自動取得 |

### 入力データソース

HTTPリクエストメタデータ（IPアドレス）

## 出力仕様

### 出力データ（正常時）

通常のレスポンスに加えて以下のヘッダーを付与：

| 項目名 | 型 | 説明 |
|--------|-----|------|
| RateLimit-Limit | number | 最大リクエスト数 |
| RateLimit-Remaining | number | 残りリクエスト数 |
| RateLimit-Reset | number | リセットまでの時間（秒） |

### 出力データ（制限超過時）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| status | number | 429 |
| message | string | "Too many requests, please try again later." |

### 出力先

HTTPレスポンスヘッダーおよびボディ

## 処理フロー

### 処理シーケンス

```
1. HTTPリクエスト受信
   └─ Expressミドルウェアチェーン

2. クライアントIP識別
   └─ trust proxyに基づくIP抽出

3. リクエストカウント取得
   └─ メモリストアからの取得

4. 制限チェック
   ├─ 制限内: 次のミドルウェアへ
   └─ 制限超過: 429レスポンス

5. カウント更新
   └─ リクエストカウントをインクリメント

6. レスポンスヘッダー付与
   └─ RateLimit-* ヘッダーの設定
```

### フローチャート

```mermaid
flowchart TD
    A[HTTPリクエスト受信] --> B[開発環境?]
    B -->|Yes| C[レート制限スキップ]
    B -->|No| D[クライアントIP取得]
    D --> E[現在のカウント取得]
    E --> F{制限超過?}
    F -->|Yes| G[429 Too Many Requests]
    F -->|No| H[カウント更新]
    H --> I[RateLimitヘッダー付与]
    I --> J[次のミドルウェアへ]
    C --> J
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-55-1 | ウィンドウサイズ | 60秒（1分）のスライディングウィンドウ | 常時 |
| BR-55-2 | 最大リクエスト数 | 1分あたり500リクエストまで | 常時 |
| BR-55-3 | 開発環境除外 | NODE_ENV=developmentの場合は制限なし | 開発環境 |
| BR-55-4 | 標準ヘッダー使用 | RateLimit-*ヘッダーで情報通知 | 常時 |
| BR-55-5 | レガシーヘッダー無効 | X-RateLimit-*ヘッダーは使用しない | 常時 |

### 計算ロジック

- ウィンドウ開始からのリクエスト数をカウント
- カウントが最大値を超えた場合にリクエスト拒否

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

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

この機能はデータベース操作を行わない。メモリ内ストアを使用。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 429 | Too Many Requests | 1分間に500リクエスト超過 | 一定時間待機後に再試行 |

### リトライ仕様

クライアント側でRateLimit-Resetヘッダーを参照し、指定時間後にリトライ。

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

トランザクション処理なし

## パフォーマンス要件

- レート制限チェック処理：1ms以内
- メモリ使用量：クライアント数に比例

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

- 信頼できるプロキシの設定が必要（trustedProxies）
- プロキシ経由の場合、X-Forwarded-Forヘッダーを正しく解釈
- IPアドレススプーフィング対策としてプロキシ設定を適切に管理

## 備考

- express-rate-limitパッケージを使用
- 分散環境ではRedisストアへの変更を検討

---

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

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

### 推奨読解順序

#### Step 1: ミドルウェア設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app.ts | `packages/sync-server/src/app.ts` | レート制限ミドルウェアの設定 |

**読解のコツ**: express-rate-limitパッケージのオプション仕様を理解しておくと、設定の意味が把握しやすい。

**主要処理フロー**:
- **7行目**: rateLimit インポート
- **29行目**: trust proxy設定（プロキシ経由のIP取得用）
- **30-38行目**: レート制限ミドルウェア設定

#### Step 2: 設定パラメータを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | app.ts | `packages/sync-server/src/app.ts` | 32-37行目：rateLimit オプション |

**主要処理フロー**:
- **32行目**: windowMs: 60 * 1000（1分間のウィンドウ）
- **33行目**: max: 500（最大500リクエスト/分）
- **34行目**: legacyHeaders: false（レガシーヘッダー無効）
- **35行目**: standardHeaders: true（標準ヘッダー有効）

#### Step 3: プロキシ信頼設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | load-config.js | `packages/sync-server/src/load-config.js` | trustedProxies設定 |

**主要処理フロー**:
- **136-146行目**: trustedProxies設定（プライベートIPレンジ）
- **147-152行目**: trustedAuthProxies設定

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

```
HTTPリクエスト
    │
    └─ Express ミドルウェアチェーン
           │
           ├─ trust proxy (app.set)
           │
           ├─ rateLimit ミドルウェア
           │      │
           │      ├─ IP抽出
           │      ├─ カウント取得
           │      ├─ 制限チェック
           │      │      ├─ OK: next()
           │      │      └─ NG: 429 レスポンス
           │      └─ カウント更新
           │
           └─ 次のミドルウェア/ルートハンドラ
```

### データフロー図

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

クライアント ───▶ Express Server ───▶ レート制限チェック
     │                                       │
     ▼                                       ▼
  IPアドレス              ┌─────────────────────────────┐
                          │ リクエストカウント管理        │
                          │ (メモリストア)               │
                          └─────────────────────────────┘
                                       │
                          ┌────────────┴────────────┐
                          ▼                         ▼
                     [制限内]                   [制限超過]
                          │                         │
                          ▼                         ▼
                  次のミドルウェアへ          429 レスポンス
                  + RateLimit-* ヘッダー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| app.ts | `packages/sync-server/src/app.ts` | ソース | レート制限ミドルウェア設定 |
| load-config.js | `packages/sync-server/src/load-config.js` | ソース | trustedProxies設定 |
