# アーキテクチャ設計書

## 概要

本ドキュメントは、Chatwootプロジェクトのアプリケーションアーキテクチャを記述する設計書である。Chatwootは、オープンソースのカスタマーエンゲージメントプラットフォームであり、Ruby on Rails 7.1をバックエンドに、Vue.js 3をフロントエンドに採用したモノリシックアプリケーションである。Enterprise Editionによる機能拡張もサポートしている。

## システム全体構成

### アーキテクチャ概要図

[アーキテクチャ構成図.md](./アーキテクチャ構成図.md) を参照

### システム境界と外部連携

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| Facebook/Meta | REST API (Koala gem) | Facebook Messengerチャネル連携 |
| WhatsApp | REST API (Webhook) | WhatsApp Business連携 |
| Twitter/X | REST API (Twitty gem) | Twitterチャネル連携 |
| Instagram | REST API (Webhook) | Instagramチャネル連携 |
| TikTok | REST API (Webhook) | TikTokチャネル連携 |
| Telegram | REST API | Telegramボット連携 |
| Line | REST API (line-bot-api gem) | LINEチャネル連携 |
| Twilio | REST API (twilio-ruby gem) | SMS/Voice通話連携 |
| Slack | REST API (slack-ruby-client gem) | Slack連携・通知 |
| Google Cloud (Dialogflow) | gRPC/REST API | AI対話フロー連携 |
| Google Cloud (Translate) | REST API | 翻訳機能 |
| OpenSearch/Elasticsearch | REST API (searchkick gem) | 全文検索 |
| OpenAI | REST API (ruby-openai gem) | AI機能（Response Bot等） |
| Stripe | REST API (stripe gem) | 決済・サブスクリプション管理 |
| Sentry | REST API | エラー監視・トラッキング |
| AWS S3/GCS/Azure Blob | REST API | ファイルストレージ |
| SMTP/Mailbox | SMTP/IMAP | メール送受信 |
| FCM/WebPush | REST API | プッシュ通知 |
| Linear | REST API | 課題管理連携 |
| Shopify | REST API | Eコマース連携 |
| Notion | REST API | ドキュメント連携 |

## レイヤー構成

### アーキテクチャスタイル

**レイヤードアーキテクチャ + イベント駆動アーキテクチャ**

Chatwootは、Ruby on Railsの標準的なMVCアーキテクチャをベースに、以下の特徴を持つ:
- サービス層（Services）によるビジネスロジックの分離
- Wisperによるイベント駆動（Pub/Sub）パターンの採用
- Sidekiqによる非同期ジョブ処理
- Enterprise Editionによるモジュール拡張（prepend_mod_with/include_mod_with）

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| Presentation | HTTPリクエスト/レスポンス処理、認証、APIエンドポイント | Controllers, Views, Policies, ActionCable Channels |
| Application | ビジネスロジックの調整、ユースケース実装 | Services, Builders, Finders, Actions |
| Domain | ドメインモデル、バリデーション、ドメインイベント | Models, Concerns, Drops (Liquid), Dispatchers, Listeners |
| Infrastructure | データ永続化、外部サービス連携、メッセージング | ActiveRecord, Redis, Sidekiq Jobs, Mailers, Mailboxes |
| Frontend | ユーザーインターフェース | Vue.js Components, Vuex Store, API Client |

### レイヤー間の依存関係ルール

- **Presentation層** は Application層とDomain層を参照可能
- **Application層** は Domain層とInfrastructure層を参照可能
- **Domain層** は他のレイヤーへの依存を最小限にする（ActiveRecordを除く）
- **Infrastructure層** は外部サービスへの依存をカプセル化
- **Frontend層** は API経由でバックエンドと通信

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| Conversation | 会話管理、メッセージング | Conversation, Message, Contact, ContactInbox |
| Account | アカウント・ユーザー管理 | Account, User, AccountUser, Team, TeamMember |
| Inbox | チャネル管理、受信箱設定 | Inbox, InboxMember, Channel::* |
| Automation | 自動化ルール、マクロ | AutomationRule, Macro, Campaign |
| Reporting | レポート、分析 | ReportingEvent, CsatSurveyResponse |
| Knowledge Base | ヘルプセンター、記事管理 | Portal, Article, Category |
| Integration | 外部サービス連携 | Integrations::*, Webhook |
| Notification | 通知管理 | Notification, NotificationSetting, NotificationSubscription |
| Captain (AI) | AI機能、レスポンスボット | lib/captain/*, AI Agents |

### パッケージ構造

```
chatwoot-develop/
├── app/
│   ├── actions/          # アクションクラス
│   ├── builders/         # ビルダーパターン実装
│   ├── channels/         # ActionCable チャネル
│   ├── controllers/      # Rails コントローラー
│   │   ├── api/v1/       # API v1 エンドポイント
│   │   ├── api/v2/       # API v2 エンドポイント
│   │   ├── platform/     # Platform API
│   │   ├── public/       # Public API
│   │   ├── webhooks/     # Webhook エンドポイント
│   │   └── super_admin/  # 管理画面
│   ├── dispatchers/      # イベントディスパッチャー
│   ├── drops/            # Liquid テンプレート用
│   ├── finders/          # 検索クエリ実装
│   ├── helpers/          # ビューヘルパー
│   ├── javascript/       # フロントエンド
│   │   ├── dashboard/    # ダッシュボードアプリ (Vue.js)
│   │   ├── portal/       # ヘルプセンター
│   │   ├── survey/       # アンケート
│   │   └── widget/       # チャットウィジェット
│   ├── jobs/             # Sidekiq ジョブ
│   ├── listeners/        # イベントリスナー (Wisper)
│   ├── mailboxes/        # ActionMailbox 受信
│   ├── mailers/          # メール送信
│   ├── models/           # ActiveRecord モデル
│   │   ├── channel/      # チャネル実装
│   │   ├── concerns/     # モデル共通ロジック
│   │   └── integrations/ # 外部連携モデル
│   ├── policies/         # Pundit 認可ポリシー
│   ├── presenters/       # プレゼンター
│   ├── services/         # サービスクラス
│   │   ├── auto_assignment/
│   │   ├── automation_rules/
│   │   ├── contacts/
│   │   ├── conversations/
│   │   ├── messages/
│   │   ├── notification/
│   │   ├── whatsapp/
│   │   └── ...
│   └── views/            # ERB テンプレート
├── config/
│   ├── initializers/     # Rails 初期化
│   ├── locales/          # i18n
│   └── routes.rb         # ルーティング
├── enterprise/           # Enterprise Edition
│   ├── app/              # Enterprise 専用機能
│   ├── config/           # Enterprise 設定
│   └── lib/              # Enterprise ライブラリ
├── lib/
│   ├── captain/          # AI 機能
│   ├── custom_exceptions/# カスタム例外
│   ├── integrations/     # 外部連携ライブラリ
│   ├── redis/            # Redis ユーティリティ
│   └── tasks/            # Rake タスク
└── spec/                 # RSpec テスト
```

### コンポーネント依存関係

**主要コンポーネント間の依存**

1. **Controller → Service → Model**
   - コントローラーはサービスクラスを呼び出し、ビジネスロジックを実行
   - サービスはモデルを通じてデータを操作

2. **Model → Dispatcher → Listener → Job**
   - モデルのコールバックがDispatcherにイベントを発行
   - リスナーがイベントを購読し、非同期ジョブを起動

3. **Controller → Policy**
   - Punditによる認可チェック

4. **Frontend (Vue.js) → API Client → REST API**
   - Vue.jsアプリがAPIクライアントを通じてバックエンドと通信

## ミドルウェア構成

### データベース

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| RDB | PostgreSQL | 16.x (with pgvector) | メインデータストア、ベクトル検索 |

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| Redis | Alpine版 | セッション、キャッシュ、ActionCable、Sidekiq、Rack::Attack | 用途により可変 |

### メッセージキュー

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Sidekiq | >= 7.3.1 | バックグラウンドジョブ処理 |
| Sidekiq-cron | >= 1.12.0 | 定期実行ジョブ |

**Sidekiq キュー優先度**

| 優先度 | キュー名 | 用途 |
| --- | --- | --- |
| 最高 | critical | 重要な処理 |
| 高 | high | 優先処理 |
| 中 | medium | 通常処理 |
| 通常 | default | デフォルト処理 |
| 通常 | mailers | メール送信 |
| 低 | low | 低優先処理 |
| 低 | scheduled_jobs | スケジュール処理 |
| 最低 | housekeeping | メンテナンス処理 |

### 検索エンジン

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| OpenSearch | - | 全文検索（Enterprise機能として利用可能時） |
| pg_search | - | PostgreSQL ベースの全文検索（ヘルプセンター記事） |

### その他ミドルウェア

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Puma | - | アプリケーションサーバー |
| Vite | 5.4.x | フロントエンドビルドツール |
| ActionCable (Redis) | - | WebSocket リアルタイム通信 |
| Active Storage | - | ファイルアップロード管理 |
| MailHog | - | 開発環境メールテスト |

## データフロー

### リクエスト処理の流れ

**同期リクエスト（API呼び出し）**

1. **リクエスト受信**: Puma → Rack → Rails Router
2. **認証**: DeviseTokenAuth による トークン認証
3. **認可**: Pundit Policy による権限チェック
4. **コントローラー処理**: パラメータバリデーション
5. **サービス呼び出し**: ビジネスロジック実行
6. **モデル操作**: ActiveRecord によるDB操作
7. **イベント発行**: Dispatcher.dispatch によるイベント発行
8. **レスポンス生成**: Jbuilder または JSON レンダリング
9. **レスポンス送信**: クライアントへ返却

### 非同期処理の流れ

**イベント駆動処理**

1. **イベント発行**: モデルコールバック → Dispatcher.dispatch
2. **同期リスナー実行**: SyncDispatcher → ActionCableListener
3. **非同期ジョブ登録**: AsyncDispatcher → EventDispatcherJob.perform_later
4. **ジョブ実行**: Sidekiq Worker → AsyncDispatcher.publish_event
5. **リスナー処理**: 各Listener（AutomationRuleListener, WebhookListener等）

**リスナー一覧**

| リスナー | 責務 |
| --- | --- |
| ActionCableListener | WebSocket 経由のリアルタイム通知 |
| AgentBotListener | ボット応答処理 |
| AutomationRuleListener | 自動化ルール実行 |
| CampaignListener | キャンペーン処理 |
| CsatSurveyListener | 顧客満足度調査送信 |
| HookListener | インテグレーションフック実行 |
| NotificationListener | 通知生成 |
| WebhookListener | 外部Webhook送信 |

### データ永続化の流れ

1. **入力データ検証**: Strong Parameters + Model Validations
2. **トランザクション開始**: ActiveRecord Transaction
3. **データ保存**: PostgreSQL への INSERT/UPDATE
4. **コールバック実行**: after_save, after_commit
5. **イベント発行**: 関連イベントのディスパッチ
6. **トランザクション終了**: COMMIT

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| Token認証 | DeviseTokenAuth | API アクセス |
| Session認証 | Devise | Web ダッシュボード |
| JWT | jwt gem | Platform API、SSO |
| OAuth2 | OmniAuth | Google/SAML SSO |
| 2FA/MFA | devise-two-factor | ユーザー認証強化 |
| 認可 | Pundit | リソースアクセス制御 |
| Rate Limiting | Rack::Attack | APIスロットリング |

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| アプリケーションログ | Rails.logger + Lograge | stdout/ファイル |
| 監査ログ | Audited gem | PostgreSQL (audits テーブル) |
| アクセスログ | Rack ミドルウェア | stdout |
| エラートラッキング | Sentry | Sentry サービス |
| APM | Datadog/NewRelic/Scout/ElasticAPM | 各APMサービス |
| LLM Observability | OpenTelemetry (Langfuse) | Langfuse サービス |

### エラーハンドリング

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| ActiveRecord::RecordNotFound | handle_with_exception | 404 Not Found |
| Pundit::NotAuthorizedError | handle_with_exception | 401 Unauthorized |
| ActionController::ParameterMissing | handle_with_exception | 422 Unprocessable Entity |
| ActiveRecord::RecordInvalid | render_record_invalid | 422 Unprocessable Entity |
| カスタム例外 | CustomExceptions | 各種HTTPステータス |

**例外ハンドリング実装場所**: `app/controllers/concerns/request_exception_handler.rb`

### トランザクション管理

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| モデル単位 | ActiveRecord Transaction | PostgreSQL デフォルト (Read Committed) |
| サービス単位 | ActiveRecord::Base.transaction | Read Committed |
| ジョブ単位 | Sidekiq 単体 | N/A（各ジョブは独立） |

## 設計原則・コーディング規約

### 適用している設計原則

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| Single Responsibility | Services, Listeners | 各サービスクラスは単一責務 |
| Open/Closed | Enterprise Edition | prepend_mod_with によるモジュール拡張 |
| Dependency Injection | Services | コンストラクタでの依存注入 |
| Event-Driven Architecture | Dispatchers/Listeners | Wisper による Pub/Sub |
| Repository Pattern | Finders | 検索ロジックのカプセル化 |
| Builder Pattern | Builders | オブジェクト生成の複雑さ隠蔽 |
| Policy Pattern | Pundit Policies | 認可ロジックの分離 |

### コーディング規約

**Ruby**
- RuboCop による静的解析
- 最大行長: 150文字
- コンパクトなモジュール/クラス定義を使用
- bundle exec での Gem コマンド実行

**JavaScript/Vue.js**
- ESLint (Airbnb base + Vue 3 recommended)
- Prettier によるフォーマット
- Composition API + `<script setup>` 構文
- PascalCase（コンポーネント）、camelCase（イベント）

**スタイリング**
- Tailwind CSS のみ使用（カスタムCSS禁止）
- インラインスタイル禁止
- スコープ付きCSS禁止

**i18n**
- バックエンド: en.yml
- フロントエンド: en.json
- テンプレート内の直接文字列禁止

## 備考

### Enterprise Edition

Chatwootは、OSSコアに加えてEnterprise Editionを提供している。Enterprise機能は `enterprise/` ディレクトリ配下に配置され、以下の仕組みで拡張される:

- `prepend_mod_with`: 既存クラスのメソッドをオーバーライド
- `include_mod_with`: 既存クラスにモジュールを追加
- `ChatwootApp.enterprise?`: Enterprise機能の有効化チェック

### 主要な外部Gem

| Gem | 用途 |
| --- | --- |
| devise, devise_token_auth | 認証 |
| pundit | 認可 |
| sidekiq, sidekiq-cron | バックグラウンドジョブ |
| wisper | イベント駆動 |
| searchkick | 検索 |
| rack-attack | レート制限 |
| audited | 監査ログ |
| liquid | テンプレート処理 |
| ai-agents, ruby_llm | AI機能 |

### バージョン情報

- Ruby: 3.4.4
- Rails: ~> 7.1
- Node.js: 24.x
- pnpm: 10.x
- PostgreSQL: 16 (with pgvector)
