# アーキテクチャ設計書

## 概要

本ドキュメントは、Ghost（オープンソースパブリッシングプラットフォーム）のアーキテクチャ設計を記載したものである。GhostはNode.js/Expressベースのモノレポ構造を持ち、コンテンツ管理、メンバーシップ管理、メール配信などの機能を提供するヘッドレスCMSプラットフォームである。

## システム全体構成

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

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

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

| 外部システム | 連携方式 | 用途 |
| --- | --- | --- |
| Stripe | REST API / Webhook | 決済・サブスクリプション管理 |
| Mailgun | REST API | メール配信（ニュースレター、トランザクションメール） |
| MySQL | MySQL Protocol (3306) | プライマリデータベース |
| Redis | Redis Protocol (6379) | キャッシュ、セッション管理 |
| S3互換ストレージ | S3 API | メディアファイル保存（オプション） |
| Tinybird | REST API | アナリティクスデータ処理（オプション） |
| SMTP (Mailpit) | SMTP (1025) | 開発環境メールテスト |

## レイヤー構成

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

**サービス指向レイヤードアーキテクチャ + マイクロフロントエンド**

- バックエンドはExpress.jsベースのレイヤードアーキテクチャを採用
- フロントエンドはEmber.js管理画面にReact製マイクロフロントエンドを埋め込む構成
- サービス層は機能ごとに独立したモジュールとして分離
- イベント駆動アーキテクチャを部分的に採用（ドメインイベント）

### レイヤー定義

| レイヤー | 責務 | 主なコンポーネント |
| --- | --- | --- |
| Web Layer | HTTPリクエスト/レスポンス処理、ルーティング | `ghost/core/core/server/web/` (Express Router, Middleware) |
| API Layer | APIエンドポイント定義、入出力バリデーション | `ghost/core/core/server/api/endpoints/` |
| Service Layer | ビジネスロジック、ドメイン操作 | `ghost/core/core/server/services/` (66以上のサービス) |
| Model Layer | データアクセス、ORM操作 | `ghost/core/core/server/models/` (Bookshelf.js ORM) |
| Data Layer | DB接続、マイグレーション、スキーマ定義 | `ghost/core/core/server/data/` |
| Frontend Layer | テーマレンダリング、ヘルパー | `ghost/core/core/frontend/` |
| Shared Layer | 共通ユーティリティ、設定、イベント | `ghost/core/core/shared/` |

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

```
Web Layer → API Layer → Service Layer → Model Layer → Data Layer
              ↑              ↓
        Shared Layer ←→ Frontend Layer
```

**許可される参照:**
- 上位レイヤーから下位レイヤーへの参照
- 同一レイヤー内のモジュール間参照
- Sharedレイヤーは全レイヤーから参照可能

**禁止される参照:**
- 下位レイヤーから上位レイヤーへの直接参照
- Model LayerからWeb Layerへの参照
- 循環依存

## モジュール構成

### ドメイン分割

| ドメイン | 責務 | 関連モジュール |
| --- | --- | --- |
| Content | 投稿、ページ、タグの管理 | `posts`, `pages`, `tags`, `collections` |
| Members | メンバー管理、認証、サブスクリプション | `members`, `tiers`, `offers`, `stripe` |
| Email | ニュースレター、メール配信 | `email-service`, `email-analytics`, `newsletters` |
| Media | 画像、ファイル管理 | `adapters/storage`, `images` |
| Themes | テーマ管理、レンダリング | `themes`, `custom-theme-settings` |
| Auth | 認証・認可 | `auth`, `permissions`, `sessions` |
| ActivityPub | フェデレーション対応 | `activitypub`, `mentions`, `webmentions` |
| Analytics | アクセス解析、統計 | `stats`, `tinybird`, `member-attribution` |

### パッケージ構造

```
Ghost-main/
├── ghost/                         # コアパッケージ群
│   ├── core/                      # メインGhostアプリケーション
│   │   ├── core/
│   │   │   ├── app.js            # ルートExpressアプリ
│   │   │   ├── boot.js           # ブートシーケンス
│   │   │   ├── bridge.js         # フロントエンド-バックエンド連携
│   │   │   ├── server/           # バックエンド
│   │   │   │   ├── api/          # APIエンドポイント
│   │   │   │   ├── services/     # ビジネスロジック (66+サービス)
│   │   │   │   ├── models/       # データモデル (70+モデル)
│   │   │   │   ├── data/         # DB・スキーマ
│   │   │   │   ├── web/          # Expressルーティング
│   │   │   │   ├── adapters/     # ストレージ・スケジューリング
│   │   │   │   └── lib/          # 共通ライブラリ
│   │   │   ├── frontend/         # フロントエンドレンダリング
│   │   │   │   ├── helpers/      # Handlebarsヘルパー
│   │   │   │   ├── services/     # ルーティング・プロキシ
│   │   │   │   └── meta/         # SEOメタデータ
│   │   │   └── shared/           # 共有モジュール
│   │   │       ├── config/       # 設定管理
│   │   │       ├── events/       # ドメインイベント
│   │   │       └── settings-cache/ # 設定キャッシュ
│   │   ├── content/              # ユーザーコンテンツ
│   │   └── test/                 # テスト
│   ├── admin/                    # Ember.js管理画面
│   │   ├── app/                  # Emberアプリケーション
│   │   └── lib/asset-delivery/   # React appアセット配信
│   ├── i18n/                     # 国際化
│   └── parse-email-address/      # メールアドレスパーサー
├── apps/                          # React製UIアプリケーション
│   ├── admin/                     # 新Admin UI
│   ├── admin-x-settings/          # 設定画面
│   ├── admin-x-design-system/     # レガシーデザインシステム
│   ├── admin-x-framework/         # 共有フレームワーク
│   ├── shade/                     # 新デザインシステム (shadcn/ui)
│   ├── portal/                    # メンバーポータル (UMD)
│   ├── comments-ui/               # コメントUI (UMD)
│   ├── signup-form/               # サインアップフォーム (UMD)
│   ├── sodo-search/               # 検索UI (UMD)
│   ├── announcement-bar/          # アナウンスバー (UMD)
│   ├── posts/                     # 投稿管理
│   ├── stats/                     # 統計ダッシュボード
│   └── activitypub/               # ActivityPub連携
└── e2e/                           # E2Eテスト (Playwright)
```

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

**バックエンド主要依存関係:**
- `boot.js` → 全サービス初期化
- `ghost-server.js` → Express HTTP Server
- `services/members` → `services/stripe`, `services/tiers`
- `services/email-service` → `services/members`, `models/email`
- `api/endpoints` → `services/*`, `models/*`

**フロントエンド統合:**
- `ghost/admin` (Ember) → `apps/admin-x-*` (React)
- テーマ → `apps/portal`, `apps/comments-ui` (UMD)

## ミドルウェア構成

### データベース

| 種類 | ミドルウェア | バージョン | 用途 |
| --- | --- | --- | --- |
| RDB | MySQL | 8.4.5 | プライマリデータストア（投稿、メンバー、設定等） |
| RDB | SQLite3 | 5.1.7 | 開発・テスト用（オプション） |

**ORM:** Bookshelf.js + Knex.js
- `knex-migrator`によるマイグレーション管理
- カスタムプラグイン（`@tryghost/bookshelf-plugins`）

### キャッシュ

| ミドルウェア | バージョン | 用途 | TTL |
| --- | --- | --- | --- |
| Redis | 7.0 | セッションキャッシュ、設定キャッシュ | 設定依存 |
| In-Memory (cache-manager) | 4.1.0 | ローカルキャッシュ | アプリケーション依存 |
| TTLCache (@isaacs/ttlcache) | 1.4.1 | 短期キャッシュ | 設定依存 |

### メッセージキュー

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| @tryghost/job-manager | 1.0.3 | バックグラウンドジョブ管理（インプロセス） |

**注:** 外部メッセージキューは使用せず、インプロセスのジョブマネージャーで非同期処理を管理

### 検索エンジン

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| FlexSearch | 0.7.43 | フロントエンド全文検索（Admin UI） |

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

| ミドルウェア | バージョン | 用途 |
| --- | --- | --- |
| Express | 4.21.2 | HTTPサーバーフレームワーク |
| Handlebars | 4.7.8 | テーマテンプレートエンジン |
| Sentry | 7.120.4 | エラートラッキング |
| Prometheus | 1.0.2 | メトリクス収集 |
| Caddy | - | 開発環境リバースプロキシ |

## データフロー

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

**Admin API リクエスト（認証済み）:**

1. クライアント → Caddy (Gateway) → Ghost HTTP Server
2. Express Middleware Chain:
   - `sentry.requestHandler` - エラートラッキング開始
   - `maintenanceMiddleware` - メンテナンスモードチェック
   - `vhost` - バックエンド/フロントエンド振り分け
3. `web/api` → 認証ミドルウェア（`session.createSessionFromToken`）
4. `api/endpoints/*` → バリデーション → サービス呼び出し
5. `services/*` → ビジネスロジック実行
6. `models/*` → Bookshelf ORM → MySQL
7. レスポンス返却

**公開サイト リクエスト（テーマレンダリング）:**

1. クライアント → Ghost HTTP Server
2. `web/parent/frontend` → URLサービスでルート解決
3. `frontend/services/routing` → 動的ルーティング
4. `frontend/services/proxy` → データ取得
5. Handlebars テーマレンダリング
6. HTML レスポンス返却

### 非同期処理の流れ

**メール配信（ニュースレター）:**

1. `posts.publish()` → ドメインイベント発火
2. `email-service` → メール生成・バッチ分割
3. `job-manager` → バックグラウンドジョブ登録
4. Mailgun API呼び出し（バッチ送信）
5. `email-analytics` → Webhook受信 → 統計更新

**Stripe Webhook処理:**

1. Stripe → `/members/webhooks/stripe/` エンドポイント
2. `services/stripe` → 署名検証
3. イベントタイプに応じたハンドラー実行
4. `services/members` → メンバーステータス更新
5. ドメインイベント発火 → 関連サービス通知

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

**投稿保存:**

1. API → `services/posts` → バリデーション
2. Lexical/Mobiledoc → HTML変換
3. `models/post.js` → Bookshelf `save()`
4. Knex → MySQL トランザクション
5. ドメインイベント発火（`post.published` 等）
6. URLサービスキャッシュ更新
7. Webhook通知（設定時）

## 横断的関心事

### 認証・認可

| 方式 | 実装箇所 | 対象 |
| --- | --- | --- |
| Session-based Auth | `services/auth/session` | Staff (管理画面) |
| JWT Bearer Token | `services/identity-tokens` | Admin API |
| Magic Link | `services/members` | Members (フロント) |
| API Key | `services/auth/api-key-auth` | Content/Admin API |
| Cookie Session | `cookie-session`, `express-session` | セッション管理 |

**ロールベースアクセス制御（RBAC）:**
- Owner, Administrator, Editor, Author, Contributor の5ロール
- `services/permissions` によるアクション単位の権限チェック

### ロギング・監査

| 種類 | 実装方式 | 保存先 |
| --- | --- | --- |
| アプリケーションログ | `@tryghost/logging` | stdout/ファイル |
| 監査ログ | `models/action.js` | MySQL (actions テーブル) |
| アクセスログ | Express middleware | stdout |
| エラーログ | `@tryghost/errors` + Sentry | Sentry/ファイル |
| デバッグログ | `@tryghost/debug` | stdout (DEBUG環境変数) |

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

| エラー種別 | ハンドリング方式 | レスポンス |
| --- | --- | --- |
| ValidationError | `@tryghost/errors` | 422 Unprocessable Entity |
| NotFoundError | `@tryghost/errors` | 404 Not Found |
| UnauthorizedError | `@tryghost/errors` | 401 Unauthorized |
| InternalServerError | `@tryghost/errors` + Sentry | 500 Internal Server Error |
| MaintenanceError | `maintenanceMiddleware` | 503 Service Unavailable |

**エラーハンドリングフロー:**
1. 例外発生 → `@tryghost/errors` でラップ
2. Express error middleware → `@tryghost/mw-error-handler`
3. 開発環境: スタックトレース付きレスポンス
4. 本番環境: ユーザーフレンドリーメッセージ + Sentry通知

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

| 範囲 | 管理方式 | 分離レベル |
| --- | --- | --- |
| 単一モデル操作 | Bookshelf暗黙的トランザクション | MySQL デフォルト |
| 複数モデル操作 | Knex明示的トランザクション | REPEATABLE READ |
| バッチ処理 | ジョブ単位でのコミット | READ COMMITTED |

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

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

| 原則 | 適用箇所 | 実装例 |
| --- | --- | --- |
| DRY (Don't Repeat Yourself) | Shared Layer | `@tryghost/*` 共通パッケージ |
| SRP (Single Responsibility) | Services | 各サービスは単一ドメイン責務 |
| DI (Dependency Injection) | Boot Sequence | サービス初期化時の依存注入 |
| Event-Driven | Domain Events | `shared/events/` でのイベント発火 |
| Repository Pattern | Models | Bookshelf モデルによるデータアクセス抽象化 |
| Adapter Pattern | Storage/Cache | `adapters/` による外部システム抽象化 |

### コーディング規約

**JavaScript/TypeScript:**
- ESLint設定: `eslint-plugin-ghost`
- Node.js 22.13.1+
- ES Modules + CommonJS混在（移行中）
- TypeScript導入中（`.ts` ファイルの段階的追加）

**コミットメッセージ:**
- 1行目: 80文字以内、過去形、ユーザー向け変更は絵文字付き
- 3行目: `ref`, `fixes`, `closes` + Issue リンク
- 4行目以降: 変更理由・背景

**絵文字規約:**
- ✨ 新機能
- 🎨 改善・変更
- 🐛 バグ修正
- 🌐 国際化
- 💡 その他ユーザー向け

## 備考

### 技術的負債・移行計画

1. **Ember.js → React移行:** `ghost/admin` から `apps/admin-x-*` への段階的移行中
2. **Design System統合:** `admin-x-design-system` から `shade` (shadcn/ui) への移行
3. **TypeScript化:** 段階的に `.ts` ファイルを追加中
4. **モノレポツーリング:** Yarn Workspaces + Nx による依存管理

### 開発環境

- Docker Compose による統合開発環境
- ホットリロード対応（Ghost Core + フロントエンドアプリ）
- Mailpit によるメールテスト
- Stripe CLI によるWebhookテスト
