# 機能設計書 7-APIトークン管理

## 概要

本ドキュメントは、Chatwootシステムにおけるアクセストークン管理機能の設計を記載する。ユーザーおよびエージェントボット用のAPIアクセストークンの生成・管理を実現する。

### 本機能の処理概要

本機能は、API認証に使用するアクセストークンを生成・管理し、外部システムやスクリプトからのAPI呼び出しを安全に認証する機能を提供する。

**業務上の目的・背景**：外部システム連携やAPIベースの自動化において、セッションベースの認証ではなくトークンベースの認証が必要となる。本機能により、ユーザーやボットが永続的なアクセストークンを取得でき、CI/CDパイプライン、外部ツール、カスタムスクリプトからのAPI呼び出しが可能となる。

**機能の利用シーン**：
- 外部システムからのAPI連携（CRM、チケットシステム等）
- エージェントボットによる自動応答
- CI/CDパイプラインでの自動化スクリプト
- サードパーティアプリケーションからのデータ取得

**主要な処理内容**：
1. ユーザー作成時のアクセストークン自動生成
2. アクセストークンのリセット（再生成）
3. トークンを使用したAPI認証
4. エージェントボット用トークンの管理

**関連システム・外部連携**：
- Platform API（外部システム連携）
- Agent Bot API（ボット連携）

**権限による制御**：アクセストークンは所有者（User、AgentBot）に紐付けられ、所有者の権限に基づいたAPI操作が可能。トークンリセットは所有者本人のみ実行可能。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 89 | プロフィール設定画面 | 主画面 | アクセストークンのリセット |

## 機能種別

認証処理 / トークン管理

## 入力仕様

### 入力パラメータ

#### トークンリセット

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| なし | - | - | ユーザー認証済みリクエストのみ | 認証必須 |

### 入力データソース

- 認証済みHTTPリクエスト（ヘッダー認証またはトークン認証）

## 出力仕様

### 出力データ

#### トークン情報

| 項目名 | 型 | 説明 |
|--------|-----|------|
| access_token | String | APIアクセストークン |

### 出力先

- データベース（access_tokensテーブル）
- HTTPレスポンスボディ（JSON形式）

## 処理フロー

### 処理シーケンス

```
【トークン自動生成フロー】
1. ユーザー作成
   └─ User.create! 実行
   └─ after_create :create_access_token コールバック

2. トークン生成
   └─ AccessToken.create!(owner: self)
   └─ has_secure_token :token でトークン自動生成

【トークンリセットフロー】
3. リセット要求
   └─ ProfilesController#reset_access_token または
   └─ AgentBotsController#reset_access_token

4. 既存トークン削除・再生成
   └─ access_token.destroy
   └─ create_access_token（新しいトークン生成）

【API認証フロー】
5. APIリクエスト受信
   └─ api_access_token パラメータまたはヘッダー

6. トークン検証
   └─ AccessToken.find_by(token: token)
   └─ owner（User/AgentBot）取得
```

### フローチャート

```mermaid
flowchart TD
    A[ユーザー作成] --> B[after_create コールバック]
    B --> C[create_access_token]
    C --> D[AccessToken.create!]
    D --> E[has_secure_token :token]
    E --> F[トークン自動生成・保存]

    G[トークンリセット要求] --> H[既存トークン削除]
    H --> I[access_token.destroy]
    I --> J[create_access_token]
    J --> K[新しいトークン生成]

    L[API認証] --> M[api_access_tokenパラメータ]
    M --> N[AccessToken.find_by token]
    N --> O{トークン存在?}
    O -->|No| P[認証失敗]
    O -->|Yes| Q[owner取得]
    Q --> R[API処理実行]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 自動生成 | ユーザー作成時にアクセストークンを自動生成 | ユーザー作成時 |
| BR-002 | 一意性 | トークンは一意でなければならない | トークン生成時 |
| BR-003 | ポリモーフィック | トークンはUser、AgentBot等複数の所有者タイプに対応 | トークン作成時 |
| BR-004 | リセット | リセット時は既存トークンを削除して新規生成 | トークンリセット時 |
| BR-005 | 永続性 | トークンは明示的にリセットされるまで有効 | 常時 |

### 計算ロジック

- **トークン生成**: `has_secure_token :token` による自動生成（24文字のURL-safe base64）

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| トークン生成 | access_tokens | INSERT | 新規トークンレコード作成 |
| トークン検索 | access_tokens | SELECT | token条件でトークン取得 |
| トークン削除 | access_tokens | DELETE | リセット時の既存トークン削除 |

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

#### access_tokens

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | token | SecureRandom.base58(24) | has_secure_token |
| INSERT | owner_type | 'User' / 'AgentBot' | ポリモーフィック |
| INSERT | owner_id | 所有者ID | ポリモーフィック |
| SELECT | * | WHERE token = :token | API認証時 |
| DELETE | * | WHERE owner_type = :type AND owner_id = :id | リセット時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 無効なアクセストークン | 正しいトークンで再試行 |
| 401 | Unauthorized | トークン未指定 | トークンを指定 |

### リトライ仕様

- トークン認証失敗時のリトライは制限なし
- トークンリセット後は新しいトークンで再試行

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

- トークン生成は単一トランザクション
- リセット時の削除・作成は非トランザクション（destroy_async使用）

## パフォーマンス要件

- トークン検証: 10ms以内
- tokenカラムにユニークインデックスあり

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

- トークンは24文字のURL-safe base64（has_secure_token）
- トークンはデータベースに平文保存（内部用のため）
- API認証ではトークンのみで認証可能（外部露出に注意）
- リセット機能により漏洩時の無効化が可能

## 備考

- AccessTokenableはconcernとしてUser、AgentBot等で共有
- Platform APIではプラットフォームトークンが別途存在
- Webhook認証には別の仕組み（署名検証）を使用

---

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

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

### 推奨読解順序

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

アクセストークンのテーブル構造とモデル定義を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | access_token.rb | `app/models/access_token.rb` | AccessTokenモデルの構造 |

**読解のコツ**:
- 1-16行目: スキーマ定義（id, owner_type, token, owner_id）
- 18行目: AccessToken本体クラス定義
- 19行目: has_secure_token :token（トークン自動生成）
- 20行目: belongs_to :owner, polymorphic: true（ポリモーフィック関連）

#### Step 2: トークン生成concernを理解する

AccessTokenableモジュールでのトークン自動生成を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | access_tokenable.rb | `app/models/concerns/access_tokenable.rb` | トークン自動生成concern |

**主要処理フロー**:
1. **3行目**: included ブロックでconcern定義
2. **4行目**: has_one :access_token でアソシエーション定義
3. **5行目**: after_create :create_access_token でコールバック定義
4. **8-10行目**: create_access_tokenメソッドでトークン作成

#### Step 3: Userモデルでの使用を理解する

UserモデルでのAccessTokenableの使用を把握。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | user.rb | `app/models/user.rb` | AccessTokenable include |

**主要処理フロー**:
- **49行目**: include AccessTokenable でconcern適用

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

```
User.create! / AgentBot.create!
    │
    └─ after_create コールバック
           │
           └─ create_access_token (AccessTokenable)
                  │
                  └─ AccessToken.create!(owner: self)
                         │
                         └─ has_secure_token :token
                                │
                                └─ SecureRandom.base58(24)

ProfilesController#reset_access_token
    │
    ├─ current_user.access_token.destroy
    │
    └─ current_user.create_access_token
           │
           └─ AccessToken.create!(owner: current_user)
```

### データフロー図

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

【トークン生成】
User.create! ─────────▶ after_create コールバック
                              │
                              ▼
                       AccessTokenable#create_access_token
                              │
                              ▼
                       AccessToken.create! ───────────▶ access_tokens (DB)
                              │
                              └─ has_secure_token ────▶ token (24文字)

【トークンリセット】
リセット要求 ─────────▶ access_token.destroy ─────────▶ access_tokens (DELETE)
                              │
                              ▼
                       create_access_token ───────────▶ access_tokens (INSERT)
                              │
                              ▼
                       新しいtoken ────────────────────▶ JSON Response

【API認証】
api_access_token ────▶ AccessToken.find_by(token) ───▶ owner (User/AgentBot)
                              │
                              ▼
                       [認証成功] ────────────────────▶ API処理実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| access_token.rb | `app/models/access_token.rb` | モデル | アクセストークンエンティティ |
| access_tokenable.rb | `app/models/concerns/access_tokenable.rb` | concern | トークン自動生成機能 |
| user.rb | `app/models/user.rb` | モデル | AccessTokenable使用元 |
| profiles_controller.rb | `app/controllers/api/v1/profiles_controller.rb` | コントローラー | トークンリセットAPI |
| agent_bots_controller.rb | `app/controllers/api/v1/accounts/agent_bots_controller.rb` | コントローラー | ボットトークンリセット |
