# アーキテクチャ設計書

## 概要

本ドキュメントは、Fizzyプロジェクトのアーキテクチャ設計について記載する。FizzyはRuby on Rails 8.1をベースとしたマルチテナント対応のカード管理・コラボレーションアプリケーションである。SQLite3とMySQL（Trilogy）の両方をサポートし、Solid Queue/Solid Cable/Solid Cacheを活用したモダンなRailsアーキテクチャを採用している。

## システム全体構成

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

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

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

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| Slack | Webhook (HTTP POST) | カード操作時の通知連携 |
| Campfire | Webhook (HTTP POST) | カード操作時の通知連携 |
| Basecamp | Webhook (HTTP POST) | カード操作時の通知連携 |
| S3互換ストレージ | AWS SDK / REST API | ファイルストレージ（Active Storage） |
| SMTP | SMTP | メール送信（Magic Link認証、通知等） |
| Web Push | Web Push Protocol | プッシュ通知 |

## レイヤー構成

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

**標準的なRails MVC + Concerns による機能分割**

Fizzyは伝統的なRails MVCアーキテクチャを採用しつつ、以下の特徴を持つ：

- **Concernsによる責務分離**: モデル・コントローラーの機能をConcernsとして分割
- **名前空間による機能グループ化**: 関連するコントローラー・モデルを名前空間で整理
- **Current Attributesパターン**: リクエストスコープの状態管理
- **マルチテナント対応**: Account単位でのデータ分離

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| Presentation | HTTPリクエスト/レスポンス処理、認証・認可、ビュー描画 | ApplicationController, 各種Controller, Views (ERB), Turbo Streams |
| Application | ビジネスロジックの調整、ジョブ処理、通知 | Jobs, Mailers, Notifiers |
| Domain | ビジネスルール、ドメインモデル | Models, Concerns |
| Infrastructure | データ永続化、外部サービス連携、キャッシュ | Active Record, Active Storage, Solid Queue/Cable/Cache |

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

- **Presentation -> Application**: コントローラーはジョブ・メーラーを呼び出し可能
- **Presentation -> Domain**: コントローラーはモデルに直接アクセス可能
- **Application -> Domain**: ジョブ・メーラーはモデルを利用
- **Domain -> Infrastructure**: モデルはActive Recordを通じてデータ永続化
- **禁止**: Infrastructure層から上位層への直接参照

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| Account | アカウント管理、マルチテナント | Account, Account::*, User, Identity |
| Board | ボード管理、カラム管理 | Board, Board::*, Column, Column::* |
| Card | カード管理、タスク管理 | Card, Card::*, Step, Closure, Tag, Tagging |
| Collaboration | コメント、リアクション、メンション | Comment, Comment::*, Reaction, Mention |
| Notification | 通知管理、プッシュ通知 | Notification, Notification::*, Notifier, NotificationPusher |
| Event | イベント追跡、監査ログ | Event, Event::* |
| Webhook | 外部連携 | Webhook, Webhook::* |
| Search | 検索機能 | Search, Search::* |
| Authentication | 認証・認可 | Identity, Session, MagicLink, Identity::AccessToken |

### パッケージ構造

```
app/
├── assets/          # アセット管理
├── channels/        # Action Cable チャンネル
│   └── application_cable/
├── controllers/     # コントローラー
│   ├── concerns/    # コントローラー共通処理
│   │   ├── authentication.rb
│   │   ├── authorization.rb
│   │   └── ...
│   ├── account/     # アカウント関連
│   ├── boards/      # ボード関連
│   ├── cards/       # カード関連
│   ├── my/          # ユーザー個人設定
│   ├── notifications/
│   ├── public/      # 公開ページ
│   └── ...
├── helpers/         # ビューヘルパー
├── javascript/      # フロントエンドJS (Stimulus)
├── jobs/            # バックグラウンドジョブ
│   ├── account/
│   ├── card/
│   ├── notification/
│   ├── webhook/
│   └── ...
├── mailers/         # メーラー
├── models/          # モデル
│   ├── concerns/    # モデル共通処理
│   ├── account/
│   ├── board/
│   ├── card/
│   ├── user/
│   └── ...
└── views/           # ビュー (ERB, Turbo)
lib/
├── fizzy.rb         # アプリケーション設定
├── rails_ext/       # Rails拡張
└── web_push/        # Web Push実装
config/
├── initializers/    # 初期化処理
└── ...
saas/                # SaaS版固有機能（gem）
```

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

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

1. **Controller -> Model**: 直接的なデータアクセス
2. **Controller -> Job**: 非同期処理の委譲
3. **Job -> Model**: データ操作
4. **Job -> Mailer**: メール送信
5. **Model -> Model (Concerns)**: 機能の共有
6. **Model -> Active Storage**: ファイル管理
7. **Model -> Action Text**: リッチテキスト管理

## ミドルウェア構成

### データベース

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| RDB | SQLite3 | >= 2.0 | OSS版メインDB（開発・本番） |
| RDB | MySQL (Trilogy) | ~2.10 | SaaS版メインDB |

**マルチデータベース構成**:
- `primary`: メインアプリケーションデータ
- `cable`: Action Cable用メッセージストア
- `cache`: Solid Cache用キャッシュストア（本番環境）
- `queue`: Solid Queue用ジョブストア（本番環境）

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| Solid Cache | ~1.0 | HTTPキャッシュ、アプリケーションキャッシュ | 60日（デフォルト） |

### メッセージキュー

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Solid Queue | ~1.3 | バックグラウンドジョブ処理 |

**キュー構成**:
- `default`: 一般的なジョブ
- `solid_queue_recurring`: 定期実行ジョブ
- `backend`: バックエンド処理
- `webhooks`: Webhook配信

### 検索エンジン

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| 内蔵検索（SQL LIKE/FTS） | - | カード・コメント検索 |

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

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Solid Cable | >= 3.0 | WebSocket（Action Cable）バックエンド |
| Puma | >= 5.0 | アプリケーションサーバー |
| Thruster | - | HTTPプロキシ・静的ファイル配信 |
| Mission Control Jobs | - | ジョブ管理UI |

## データフロー

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

1. **HTTPリクエスト受信**: Puma/Thruster がリクエストを受信
2. **ミドルウェアチェーン**: Rack ミドルウェアを通過（CSP、認証等）
3. **ルーティング**: routes.rb でコントローラー・アクションを決定
4. **認証チェック**: `require_authentication` でセッション/トークン検証
5. **認可チェック**: `ensure_can_access_account` でアクセス権確認
6. **アクション実行**: コントローラーアクションでビジネスロジック実行
7. **レスポンス生成**: HTML/JSON/Turbo Stream を生成
8. **イベント発行**: 必要に応じてイベント作成・Webhook配信

### 非同期処理の流れ

1. **ジョブのエンキュー**: `perform_later` でSolid Queueにジョブ登録
2. **ワーカーによるポーリング**: 0.1秒間隔でジョブを取得
3. **ジョブ実行**: ActiveJob経由でジョブ処理
4. **完了/リトライ**: 成功時は完了、失敗時は設定に基づきリトライ

**定期実行ジョブ（Recurring Jobs）**:
- `deliver_bundled_notifications`: 30分ごと - 通知バンドル配信
- `auto_postpone_all_due`: 毎時50分 - カード自動延期
- `delete_unused_tags`: 毎日4:02 - 未使用タグ削除
- `cleanup_webhook_deliveries`: 15分ごと - Webhook配信履歴クリーンアップ
- `cleanup_magic_links`: 4時間ごと - Magic Linkクリーンアップ

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

1. **トランザクション開始**: `transaction` ブロックでラップ
2. **バリデーション**: モデルバリデーション実行
3. **コールバック実行**: before/after コールバック
4. **SQL実行**: Active RecordがSQLを生成・実行
5. **インデックス更新**: 関連テーブルのインデックス更新
6. **コミット/ロールバック**: 成功時コミット、失敗時ロールバック
7. **ブロードキャスト**: Turbo Streamで変更を配信（after_commit）

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| セッション認証 | `Authentication` concern | 通常Webアクセス |
| Magic Link認証 | `MagicLink`, `MagicLinkMailer` | パスワードレスログイン |
| Bearer Token認証 | `Identity::AccessToken` | API/モバイルアクセス |
| Account/User権限 | `Authorization` concern | リソースアクセス制御 |

**認証フロー**:
1. `require_account`: アカウントスコープの確認
2. `require_authentication`: 認証済みかチェック
3. `resume_session`: セッションCookieから復元
4. `authenticate_by_bearer_token`: APIトークン認証（フォールバック）

**権限モデル**:
- `system`: システムユーザー（自動処理用）
- `owner`: アカウントオーナー
- `admin`: 管理者
- `member`: 一般メンバー

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| アプリケーションログ | Rails Logger | 標準出力/ファイル |
| 監査ログ | Event モデル | データベース |
| アクセスログ | Webサーバー | 標準出力/ファイル |
| SQLクエリログ | Rails Event Debug Mode | 標準出力 |

**Event（監査ログ）で追跡される操作**:
- カードの作成・更新・削除
- カードの状態変更（公開、クローズ、延期等）
- コメントの作成
- アサインメントの変更

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

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| 認証エラー | `request_authentication` | ログインページへリダイレクト |
| 認可エラー | `head :forbidden` | 403 Forbidden |
| レコード未発見 | Rails標準 | 404 Not Found |
| バリデーションエラー | フォーム再表示 | 422 Unprocessable Entity |
| 内部エラー | Rails標準 | 500 Internal Server Error |

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

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| 単一操作 | Active Record自動トランザクション | READ COMMITTED（デフォルト） |
| 複数操作 | `transaction` ブロック | READ COMMITTED |
| マルチDB | 各DB個別トランザクション | READ COMMITTED |

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

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

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| Single Responsibility | Model Concerns | `Card::Closeable`, `Card::Taggable` 等、機能ごとに分離 |
| Open/Closed | Concerns | 既存モデルを変更せず機能追加可能 |
| Convention over Configuration | 全体 | Railsの規約に従った命名・構成 |
| Don't Repeat Yourself | Concerns, Helpers | 共通処理の抽出 |
| Current Attributes | `Current` モデル | リクエストスコープの状態管理 |

### コーディング規約

- **Rubyスタイル**: rubocop-rails-omakase に準拠
- **命名規則**:
  - モデル: 単数形、キャメルケース (`Card`, `BoardColumn`)
  - コントローラー: 複数形、スネークケース (`cards_controller.rb`)
  - テーブル: 複数形、スネークケース (`cards`, `board_columns`)
- **主キー**: UUID（`config.generators.orm :active_record, primary_key_type: :uuid`）
- **認証/認可**: Concernsとして実装、コントローラーでinclude
- **非同期処理**: Active Job + Solid Queueを使用
- **リアルタイム更新**: Turbo Streams + Action Cable

## 備考

### OSS版とSaaS版の違い

Fizzyはオープンソース版とSaaS版の2つの構成をサポートする：

| 観点 | OSS版 | SaaS版 |
| --- | --- | --- |
| データベース | SQLite3 | MySQL (Trilogy) |
| ストレージ | ローカルディスク / S3 | クラウドストレージ（S3等） |
| マルチテナント | オプション | 有効 |
| 追加機能 | 基本機能のみ | メトリクス、追加連携等 |

`Fizzy.saas?` メソッドで実行モードを判定し、設定ファイルやGemfileを切り替える。

### フロントエンドアーキテクチャ

- **Hotwire**: Turbo + Stimulus による SPA風UIの実現
- **Importmap**: ES Modulesベースのアセット管理
- **Propshaft**: アセットパイプライン
- **Progressive Web App**: Service Worker、Web Manifest対応
