# 機能設計書 44-Content API

## 概要

本ドキュメントは、Ghost CMSにおけるContent APIの設計仕様を記載したものである。

### 本機能の処理概要

Content APIは、Ghost CMSが提供する公開コンテンツ取得用のREST APIである。サイトの記事、ページ、タグ、著者などの公開情報を外部から取得するためのAPIで、Content APIキーによる認証を使用する。ヘッドレスCMSとしてGhostを利用する場合や、JAMstackサイトの構築において重要な役割を果たす。

**業務上の目的・背景**：Ghost CMSはヘッドレスCMSとしての利用も想定しており、フロントエンドフレームワーク（Next.js、Gatsby、Nuxt.js等）からコンテンツを取得する必要がある。Content APIにより、公開コンテンツを安全かつ効率的に外部アプリケーションに提供し、柔軟なサイト構築を可能にする。

**機能の利用シーン**：
- 静的サイトジェネレーターでのビルド時コンテンツ取得
- SPAフロントエンドからのコンテンツ取得
- モバイルアプリからの記事一覧・詳細取得
- 外部サービスへのコンテンツシンジケーション
- サイト内検索インデックスの構築

**主要な処理内容**：
1. 記事の一覧取得・個別取得（Posts）
2. ページの一覧取得・個別取得（Pages）
3. タグの一覧取得・個別取得（Tags）
4. 著者の一覧取得・個別取得（Authors）
5. 設定情報の取得（Settings）
6. ティア情報の取得（Tiers）
7. ニュースレター情報の取得（Newsletters）
8. 検索インデックスの取得（Search Index）
9. おすすめサイトの取得（Recommendations）
10. オファー情報の取得（Offers）

**関連システム・外部連携**：
- 外部フロントエンドアプリケーション
- 静的サイトジェネレーター
- CDNキャッシュシステム
- メンバーシップ機能との連携（コンテンツアクセス制御）

**権限による制御**：
- Content APIキーによる認証が必要
- 公開コンテンツのみアクセス可能
- メンバー限定コンテンツはメンバー認証と組み合わせて取得
- 著者のpassword、emailフィールドは常に除外

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 外部フロントエンド | 主機能 | Content API経由でのコンテンツ取得 |
| 100 | 検索モーダル | 補助機能 | 検索インデックスAPIの利用 |

## 機能種別

データ取得（Read Only）/ REST API

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | string | Yes | Content APIキー | 有効なAPIキー |
| include | string | No | 関連データの取得指定 | tags,authors,tiers等 |
| filter | string | No | フィルター条件 | NQL形式 |
| fields | string | No | 取得フィールド指定 | カンマ区切り |
| formats | string | No | コンテンツフォーマット | html,plaintext |
| limit | integer | No | 取得件数 | 1-15（デフォルト15） |
| page | integer | No | ページ番号 | 正の整数 |
| order | string | No | ソート順 | カラム名 ASC/DESC |
| id | string | No | 記事ID（個別取得） | 24文字のID |
| slug | string | No | スラッグ（個別取得） | 有効なスラッグ |
| uuid | string | No | UUID（プレビュー用） | 有効なUUID |

### 入力データソース

- HTTPリクエスト（GET メソッド）
- クエリパラメータまたはパスパラメータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| posts/pages | array | 記事/ページの配列 |
| tags | array | タグの配列 |
| authors | array | 著者の配列 |
| settings | object | サイト設定オブジェクト |
| tiers | array | ティアの配列 |
| meta | object | ページング情報 |

### 出力先

- HTTPレスポンス（JSON形式）
- Content-Type: application/json

## 処理フロー

### 処理シーケンス

```
1. APIリクエスト受信
   └─ GET /ghost/api/content/{resource}/?key={apiKey}
2. 認証チェック
   └─ Content APIキーの検証
3. パラメータバリデーション
   └─ include, filter, formats等の検証
4. データ取得
   ├─ フィルター条件の適用
   ├─ ページング処理
   └─ 関連データの取得
5. プライバシーフィルタリング
   └─ authors.password, authors.emailの除外
6. キャッシュキー生成
   └─ generateCacheKeyData()
7. レスポンス返却
   └─ JSON形式でデータを返却
```

### フローチャート

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B{APIキー検証}
    B -->|Invalid| C[401 Unauthorized]
    B -->|Valid| D[パラメータバリデーション]
    D -->|Invalid| E[422 Validation Error]
    D -->|Valid| F{キャッシュあり?}
    F -->|Yes| G[キャッシュ返却]
    F -->|No| H[DBクエリ実行]
    H --> I[プライバシーフィルタリング]
    I --> J[キャッシュ保存]
    J --> K[レスポンス返却]
    G --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-44-001 | 公開コンテンツのみ | status=publishedのコンテンツのみ取得可能 | 全リクエスト |
| BR-44-002 | プライバシー保護 | 著者のpassword, emailは除外 | authors関連取得時 |
| BR-44-003 | メンバーアクセス制御 | メンバー限定コンテンツはメンバー認証必須 | visibility制御時 |
| BR-44-004 | 取得件数制限 | デフォルト15件、最大取得件数あり | 一覧取得時 |
| BR-44-005 | キャッシュ活用 | リクエストパラメータに基づくキャッシュ | 全GET |

### 計算ロジック

キャッシュキー生成:
```javascript
generateCacheKeyData(frame) {
    return {
        options: generateOptionsData(frame, [
            'include', 'filter', 'fields', 'formats',
            'limit', 'order', 'page', 'absolute_urls'
        ]),
        auth: generateAuthData(frame), // メンバー認証情報
        method: 'browse'
    };
}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 記事取得 | posts | SELECT | 公開記事の取得 |
| タグ取得 | tags, posts_tags | SELECT | 関連タグの取得 |
| 著者取得 | users, posts_authors | SELECT | 関連著者の取得 |
| ティア取得 | products | SELECT | ティア情報の取得 |
| 設定取得 | settings | SELECT | サイト設定の取得 |

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

#### posts

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, uuid, title, slug, html, plaintext, excerpt, url, feature_image, visibility, published_at, ... | status='published' かつ type='post' | includeオプションに応じて関連取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | APIキーが無効または未指定 | 有効なContent APIキーを使用 |
| 404 | NotFoundError | 指定リソースが存在しない | 有効なID/slugを指定 |
| 422 | ValidationError | パラメータが無効 | パラメータ形式を確認 |

### リトライ仕様

- クライアント側でのリトライを推奨
- レートリミットに達した場合は適切な間隔で再試行

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

Read Onlyのため、トランザクション管理は不要。

## パフォーマンス要件

- 一覧取得: 200ms以内
- 個別取得: 100ms以内
- CDNキャッシュを活用した高速レスポンス
- cacheInvalidate: falseでデフォルトキャッシュ有効

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

- Content APIキーは公開しても比較的安全（読み取り専用）
- ただし不正利用防止のためレートリミットを設定
- 著者のpassword, emailフィールドは必ず除外
- メンバー限定コンテンツはメンバートークンと組み合わせ

## 備考

- Content APIキーはインテグレーション設定で取得
- メンバー認証にはJWTトークンを使用
- SDKライブラリ（@tryghost/content-api）の使用を推奨

---

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

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

### 推奨読解順序

#### Step 1: APIエンドポイントの構造を理解する

まず、Content APIのエンドポイント定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | posts-public.js | `ghost/core/core/server/api/endpoints/posts-public.js` | 記事取得APIの定義 |
| 1-2 | pages-public.js | `ghost/core/core/server/api/endpoints/pages-public.js` | ページ取得APIの定義 |
| 1-3 | tags-public.js | `ghost/core/core/server/api/endpoints/tags-public.js` | タグ取得APIの定義 |
| 1-4 | authors-public.js | `ghost/core/core/server/api/endpoints/authors-public.js` | 著者取得APIの定義 |

**読解のコツ**: 各ファイルの構造は統一されており、browse（一覧）とread（個別）のアクションを定義している。

#### Step 2: 記事取得APIの詳細を理解する

posts-public.jsを詳細に読み解く。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | posts-public.js | `ghost/core/core/server/api/endpoints/posts-public.js` | 完全な実装 |

**主要処理フロー**:
1. **9行目**: allowedIncludes: tags, authors, tiers, sentiment
2. **15-24行目**: rejectPrivateFieldsTransformer - password/email除外
3. **32-49行目**: generateOptionsData - キャッシュキー生成用データ
4. **51-60行目**: generateAuthData - メンバー認証情報
5. **66-118行目**: browseアクション定義
6. **70-86行目**: generateCacheKeyData - キャッシュキー生成
7. **88-99行目**: オプション定義（include, filter, formats, limit, order, page等）
8. **110-117行目**: postsService.browsePostsでデータ取得
9. **120-179行目**: readアクション定義

#### Step 3: プライバシーフィルタリングを理解する

著者の機密情報除外ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | posts-public.js | `ghost/core/core/server/api/endpoints/posts-public.js` | rejectPrivateFieldsTransformer |

**主要処理フロー**:
- **15-24行目**: mapQueryで各フィルタを処理
- **17-18行目**: authors.passwordまたはauthors.emailで始まるキーを除外
- **20-23行目**: 許可されたキーのみ通過

#### Step 4: キャッシュ機構を理解する

キャッシュキー生成とキャッシュ制御を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | posts-public.js | `ghost/core/core/server/api/endpoints/posts-public.js` | cache, generateCacheKeyData |

**主要処理フロー**:
- **70行目**: cache: postsPublicService.api?.cache
- **71-86行目**: generateCacheKeyData関数
- **51-60行目**: generateAuthData - メンバー情報を含むキャッシュキー

#### Step 5: 他のContent APIエンドポイントを理解する

他のpublicエンドポイントの構造を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | search-index-public.js | `ghost/core/core/server/api/endpoints/search-index-public.js` | 検索インデックスAPI |
| 5-2 | settings-public.js | `ghost/core/core/server/api/endpoints/settings-public.js` | 設定取得API |
| 5-3 | tiers-public.js | `ghost/core/core/server/api/endpoints/tiers-public.js` | ティア取得API |

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

```
API Request (GET /ghost/api/content/posts/)
    │
    ├─ posts-public.js (controller)
    │      │
    │      ├─ authentication (Content API Key)
    │      │
    │      ├─ validation
    │      │      └─ include, formats options
    │      │
    │      ├─ cache check
    │      │      └─ generateCacheKeyData()
    │      │
    │      └─ postsService.browsePosts(options)
    │             │
    │             ├─ mongoTransformer (privacy filter)
    │             │
    │             └─ Post.findPage() / Post.findOne()
    │                    └─ Database SELECT
    │
    └─ Response (JSON)
```

### データフロー図

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

key (APIキー) ───────────▶ ┌──────────────────────────┐
include ─────────────────▶ │   API Authentication    │
filter ──────────────────▶ │          │              │
fields ──────────────────▶ │          ▼              │
formats ─────────────────▶ │   Validation            │
limit ───────────────────▶ │          │              │
page ────────────────────▶ │          ▼              │
                           │   Cache Check            │
                           │          │              │
                           │          ▼              │
                           │   Database Query        │
                           │          │              │
                           │          ▼              │
                           │   Privacy Filter        │
                           │   (password, email除外)  │
                           └──────────────────────────┘
                                       │
                                       ▼
                           ┌──────────────────────────┐
                           │  JSON Response           │
                           │  {                       │
                           │    posts: [...],         │
                           │    meta: { pagination }  │
                           │  }                       │
                           └──────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| posts-public.js | `ghost/core/core/server/api/endpoints/posts-public.js` | ソース | 記事取得API |
| pages-public.js | `ghost/core/core/server/api/endpoints/pages-public.js` | ソース | ページ取得API |
| tags-public.js | `ghost/core/core/server/api/endpoints/tags-public.js` | ソース | タグ取得API |
| authors-public.js | `ghost/core/core/server/api/endpoints/authors-public.js` | ソース | 著者取得API |
| settings-public.js | `ghost/core/core/server/api/endpoints/settings-public.js` | ソース | 設定取得API |
| tiers-public.js | `ghost/core/core/server/api/endpoints/tiers-public.js` | ソース | ティア取得API |
| newsletters-public.js | `ghost/core/core/server/api/endpoints/newsletters-public.js` | ソース | ニュースレター取得API |
| recommendations-public.js | `ghost/core/core/server/api/endpoints/recommendations-public.js` | ソース | おすすめ取得API |
| offers-public.js | `ghost/core/core/server/api/endpoints/offers-public.js` | ソース | オファー取得API |
| search-index-public.js | `ghost/core/core/server/api/endpoints/search-index-public.js` | ソース | 検索インデックスAPI |
