# 画面設計書 62-履歴・監査ログ

## 概要

本ドキュメントは、Ghost管理画面における「履歴・監査ログ（History）」画面の設計仕様を記述したものである。この画面では、サイト上で行われたすべてのユーザーアクション（投稿の作成・編集・削除、設定変更など）の履歴を時系列で確認できる。

### 本画面の処理概要

履歴・監査ログ画面は、Ghost管理画面で行われたすべてのアクションを記録・表示するシステムイベントログビューアである。管理者がサイトで何が起きたかを追跡し、問題のトラブルシューティングや監査目的に使用できる。

**業務上の目的・背景**：複数のスタッフが管理画面を操作するサイトでは、誰がいつ何を変更したかを追跡することが重要である。この画面により、意図しない変更の検出、問題発生時の原因特定、セキュリティ監査などが可能になる。また、コンテンツの変更履歴を確認することで、編集ミスの発見や復元の判断材料にもなる。

**画面へのアクセス方法**：設定画面（Settings）から「Advanced」セクション内の「History」を選択し、「View history」ボタンをクリックしてモーダルを開く。URL は `/ghost/#/settings/history/view` でモーダルが表示される。

**主要な操作・処理内容**：
1. アクション履歴一覧の表示（無限スクロール対応）
2. イベントタイプによるフィルタリング（追加/編集/削除）
3. リソースタイプによるフィルタリング（投稿/ページ/タグ/ティア・オファー/設定・スタッフ）
4. スタッフ（ユーザー）によるフィルタリング
5. リソースへの直接リンク（編集画面への遷移）

**画面遷移**：設定画面のAdvancedセクションから「History」エントリポイントにアクセス。履歴モーダル内から各リソース（投稿、ページ、タグ等）の編集画面へ遷移可能。

**権限による表示制御**：管理者権限を持つユーザーのみがこの画面にアクセスできる。一般のエディターやコントリビューターには表示されない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 35 | 一般設定 | 主機能 | ユーザーアクションの履歴表示 |

## 画面種別

一覧画面（モーダル形式）

## URL/ルーティング

- エントリポイント: `/ghost/#/settings`（History セクション）
- モーダル: `/ghost/#/settings/history/view`
- ユーザーフィルタ付き: `/ghost/#/settings/history/view/{userId}`
- ナビゲーションID: `history`

## 入出力項目

### フィルター入力

| 項目名 | データ型 | 入力/出力 | 説明 |
|--------|----------|----------|------|
| イベントタイプフィルター | string[] | 入力 | 除外するイベントタイプ（added/edited/deleted） |
| リソースタイプフィルター | string[] | 入力 | 除外するリソースタイプ |
| スタッフ検索 | string | 入力 | スタッフ名での検索（非同期セレクト） |

## 表示項目

### 履歴一覧項目

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| アバター | 画像/イニシャル | アクション実行者のアバター |
| アクションアイコン | アイコン | イベントタイプを示すアイコン（追加:add、編集:pen、削除:trash） |
| アクションタイトル | テキスト | リソースタイプ + イベント名（例：Post edited） |
| リソース名 | テキスト/リンク | 対象リソースの名前またはタイトル（リンク可能な場合はクリック可能） |
| 実行者名 | テキスト | アクションを実行したスタッフ名 |
| 日時 | テキスト | アクション実行日時（日付 | 時刻 形式） |
| 繰り返し回数 | テキスト | 同一アクションの連続回数（x times） |

### フィルターパネル

| 項目名 | 表示形式 | 説明 |
|--------|----------|------|
| Added トグル | Toggle | 追加イベントの表示/非表示 |
| Edited トグル | Toggle | 編集イベントの表示/非表示 |
| Deleted トグル | Toggle | 削除イベントの表示/非表示 |
| Posts トグル | Toggle | 投稿の表示/非表示 |
| Pages トグル | Toggle | ページの表示/非表示 |
| Tags トグル | Toggle | タグの表示/非表示 |
| Tiers & offers トグル | Toggle | ティア・オファーの表示/非表示 |
| Settings & staff トグル | Toggle | 設定・スタッフの表示/非表示 |
| スタッフ検索 | Select | スタッフでの絞り込み |

## イベント仕様

### 1-View history ボタン押下

1. エントリポイントで「View history」ボタンをクリック
2. `updateRoute('history/view')` を実行
3. HistoryModal が開く
4. 初期データ（最新200件）を取得開始

### 2-無限スクロールによる追加読み込み

1. スクロールがリスト下部（250px手前）に到達
2. `InfiniteScrollListener` がトリガー
3. `fetchNextPage` を呼び出し
4. 次の200件を取得
5. 既存リストに追加表示
6. ページ終端に達した場合は「End of history log」を表示

### 3-イベントタイプフィルター変更

1. Filter ボタンをクリックしてポップオーバーを開く
2. イベントタイプ（Added/Edited/Deleted）のトグルを操作
3. `excludedEvents` 状態を更新
4. フィルター条件を含む新しいクエリでデータを再取得
5. フィルタリングされた結果を表示

### 4-リソースタイプフィルター変更

1. Filter ポップオーバー内でリソースタイプのトグルを操作
2. `excludedResources` 状態を更新
3. フィルター条件を含む新しいクエリでデータを再取得

### 5-スタッフ検索・選択

1. スタッフ検索セレクトに入力
2. 500msデバウンス後、`/users/` APIで検索
3. 候補リストを表示
4. スタッフを選択すると `updateRoute('history/view/{userId}')` を実行
5. 選択したスタッフのアクションのみ表示

### 6-リソースリンククリック

1. リソース名（リンク）をクリック
2. `getLinkTarget` でリンク先を判定
3. 投稿/ページ: `editor/{type}/{id}` へ遷移（外部ルート）
4. タグ: `tag/{slug}` へ遷移
5. インテグレーション: `integrations/{id}` へ遷移
6. ユーザー: `staff/{slug}` へ遷移

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 履歴表示 | actions | SELECT | アクション履歴の取得 |

この画面は参照専用であり、データの更新は行わない。

### テーブル別更新項目詳細

この画面からのデータベース更新はなし。actions テーブルからの SELECT のみ。

#### actions テーブル（参照）

| 項目（カラム名） | 説明 |
|-----------------|------|
| id | アクションID |
| resource_id | 対象リソースのID |
| resource_type | リソースタイプ（post/page/tag/user/setting等） |
| actor_id | 実行者のID |
| actor_type | 実行者タイプ（user/integration） |
| event | イベントタイプ（added/edited/deleted） |
| context | アクションのコンテキスト情報（JSON） |
| created_at | 作成日時 |

## メッセージ仕様

| メッセージ種別 | メッセージ内容 | 表示条件 |
|---------------|---------------|----------|
| 情報 | End of history log | 履歴の終端に到達時 |
| 情報 | No entries match your current filters. | フィルター適用時に該当なし |
| 情報 | No history entries found. | 履歴データなし（フィルターなし） |

## 例外処理

| 例外条件 | 処理内容 |
|---------|---------|
| データ取得失敗 | ローディング表示のまま、またはエラー表示 |
| 権限不足 | 画面自体にアクセス不可（設定画面レベルで制御） |
| リソース削除済み | リンクなしのテキスト表示、または「(unknown)」表示 |

## 備考

- 履歴データは時系列の逆順（新しい順）で表示
- 同一リソースへの連続した同一イベントはグループ化され、回数が表示される
- 1ページあたり200件ずつ取得（PAGE_SIZE = 200）
- labelリソースタイプはデフォルトで非表示（excludedResources初期値に含まれる）
- 設定変更の履歴では、変更された設定グループとキーが表示される

---

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

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

### 推奨読解順序

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

ActionsはGhostバックエンドで記録されるシステムイベントログである。各アクションには実行者（actor）、対象（resource）、イベントタイプ（event）、コンテキスト情報が含まれる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | actions.ts | `apps/admin-x-framework/src/api/actions.ts` | Action型定義（8-32行目）、API呼び出し（49-89行目） |

**読解のコツ**: `context` フィールドは文字列として保存されているため、取得時に `JSON.parse` で変換される（58-59行目）。グループ化ロジック（62-79行目）で連続した同一アクションをまとめている。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | history.tsx | `apps/admin-x-settings/src/components/settings/advanced/history.tsx` | エントリポイントコンポーネント（6-24行目） |

**主要処理フロー**:
1. **8-9行目**: `updateRoute` フック取得
2. **14行目**: 「View history」ボタン、クリックで `updateRoute('history/view')` 実行

#### Step 3: モーダルコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | history-modal.tsx | `apps/admin-x-settings/src/components/settings/advanced/history-modal.tsx` | メインモーダル（163-273行目） |

**主要処理フロー**:
- **167-168行目**: フィルター状態の初期化
- **170-185行目**: `useBrowseActions` による無限スクロールデータ取得
- **193行目**: アクティブフィルターの判定
- **225-259行目**: アクション一覧のレンダリング

#### Step 4: フィルターコンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | history-modal.tsx (HistoryFilter) | `apps/admin-x-settings/src/components/settings/advanced/history-modal.tsx` | フィルターコンポーネント（57-117行目） |

**主要処理フロー**:
- **65-69行目**: ユーザー検索API（`useFilterableApi`）
- **80-94行目**: イベント・リソースタイプのトグル
- **96-113行目**: スタッフ検索セレクト

#### Step 5: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | actions.ts | `apps/admin-x-framework/src/api/actions.ts` | ヘルパー関数（93-224行目） |

**主要関数**:
- **93-114行目**: `getActorLinkTarget` - 実行者へのリンク生成
- **116-176行目**: `getLinkTarget` - リソースへのリンク生成
- **178-210行目**: `getActionTitle` - アクションタイトル生成
- **212-221行目**: `getContextResource` - 設定変更のコンテキスト取得

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

```
History (history.tsx)
    │
    └─ TopLevelGroup
           └─ Button ("View history")
                  │
                  └─ updateRoute('history/view')
                         │
                         └─ HistoryModal (history-modal.tsx)
                                │
                                ├─ HistoryFilter
                                │      ├─ Popover (Filter button)
                                │      │      ├─ HistoryFilterToggle (Added)
                                │      │      ├─ HistoryFilterToggle (Edited)
                                │      │      ├─ HistoryFilterToggle (Deleted)
                                │      │      ├─ HistoryFilterToggle (Posts)
                                │      │      ├─ HistoryFilterToggle (Pages)
                                │      │      ├─ HistoryFilterToggle (Tags)
                                │      │      ├─ HistoryFilterToggle (Tiers & offers)
                                │      │      └─ HistoryFilterToggle (Settings & staff)
                                │      │
                                │      └─ Select (Staff search)
                                │
                                ├─ InfiniteScrollListener
                                │      └─ fetchNextPage
                                │
                                └─ List
                                       └─ ListItem (各アクション)
                                              ├─ HistoryAvatar
                                              │      └─ HistoryIcon
                                              └─ HistoryActionDescription
```

### データフロー図

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

ページロード ────────▶ useBrowseActions
                            │
                            ├─ GET /actions/
                            │   ?include=actor,resource
                            │   &limit=200
                            │   &filter=...
                            │
                            ├─ JSON.parse(context) ───────▶ Action[]
                            │
                            └─ グループ化処理 ─────────────▶ 表示用データ
                                  │
                                  ├─ skip=true (連続イベント)
                                  └─ count=n (回数)

フィルター変更 ─────▶ excludedEvents/excludedResources更新
                            │
                            └─ 新しいfilterパラメータで再取得

スクロール ──────────▶ InfiniteScrollListener
                            │
                            └─ fetchNextPage ─────────────▶ 追加データ取得
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| history.tsx | `apps/admin-x-settings/src/components/settings/advanced/history.tsx` | ソース | エントリポイントコンポーネント |
| history-modal.tsx | `apps/admin-x-settings/src/components/settings/advanced/history-modal.tsx` | ソース | 履歴モーダルコンポーネント |
| actions.ts | `apps/admin-x-framework/src/api/actions.ts` | ソース | Actions API・型定義・ヘルパー |
| hooks.ts | `apps/admin-x-framework/src/utils/api/hooks.ts` | ソース | createInfiniteQuery等のAPIフック |
