# 機能設計書 66-著者データ永続化

## 概要

本ドキュメントは、Etherpadの著者データ永続化機能の設計を記載する。この機能は、パッドに貢献した著者の情報（ID、名前、カラー、貢献パッド一覧）をueberDB2を介してデータベースに保存する。

### 本機能の処理概要

著者データ永続化機能は、Etherpadで編集を行うユーザー（著者）の情報を管理・保存する機能である。各著者には一意のIDが割り当てられ、名前、カラー（編集時の表示色）、貢献したパッドの一覧が保存される。

**業務上の目的・背景**：Etherpadの共同編集では、誰がどの部分を編集したかを識別する必要がある。著者情報を永続化することで、編集者ごとに異なる色で表示する機能や、タイムスライダーでの著者表示機能が実現される。また、トークンやマッパーとの関連付けにより、同一ユーザーの再訪問時に一貫した著者IDを維持できる。

**機能の利用シーン**：
- 新規ユーザーがパッドにアクセスした時（著者作成）
- ユーザーが編集を開始した時（著者とパッドの関連付け）
- ユーザー名を設定・変更した時
- 著者の色を変更した時
- 著者が貢献したパッドを一覧表示する時

**主要な処理内容**：
1. 著者の作成（createAuthor）
2. トークン/マッパーによる著者ID解決
3. 著者名・カラーの取得・設定
4. パッドへの貢献記録の追加・削除
5. 著者の貢献パッド一覧取得

**関連システム・外部連携**：
- ueberDB2（データベース抽象化層）
- セッション管理（著者IDとセッションの関連付け）
- パッド管理（パッドと著者の関連付け）

**権限による制御**：著者データへのアクセスはAPI経由または内部処理のみ。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | パッド編集画面 | 主画面 | 著者名・カラーの表示と設定 |
| 3 | タイムスライダー画面 | 参照画面 | 著者一覧の表示 |

## 機能種別

データ永続化 / CRUD操作

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| authorId | string | Yes（多くの操作で） | 著者の一意識別子 | a.で始まる文字列 |
| name | string | No | 著者名 | - |
| colorId | string/number | No | カラーID（パレット番号または16進カラー） | - |
| authorMapper | string | Yes（条件付き作成時） | 外部システムとの関連付けキー | - |
| token | string | Yes（トークン認証時） | セッショントークン | - |

### 入力データソース

- Socket.IO（リアルタイム編集セッション）
- REST API（著者管理API）
- 内部呼び出し（パッド操作時の著者記録）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| globalAuthor:{authorId} | object | 著者情報オブジェクト |
| token2author:{token} | string | トークンから著者IDへのマッピング |
| mapper2author:{mapper} | string | マッパーから著者IDへのマッピング |

### 出力先

- ueberDB2を介したデータベース

## 処理フロー

### 処理シーケンス

```
1. 著者ID解決リクエスト
   └─ getAuthorId(token, user) 呼び出し
2. トークン/マッパーからの検索
   └─ token2author または mapper2author から検索
3. 著者が存在しない場合
   └─ createAuthor() で新規作成
   └─ ランダムカラー割り当て
   └─ token2author/mapper2author 関連付け保存
4. 著者が存在する場合
   └─ タイムスタンプ更新
5. 著者情報の取得・更新
   └─ getSub/setSub で個別属性アクセス
```

### フローチャート

```mermaid
flowchart TD
    A[著者ID解決要求] --> B{フック結果あり?}
    B -->|Yes| C[フックからのauthorId使用]
    B -->|No| D[token2authorから検索]
    D --> E{著者存在?}
    E -->|Yes| F[タイムスタンプ更新]
    E -->|No| G[createAuthor]
    G --> H[ランダムカラー割り当て]
    H --> I[token2author保存]
    I --> J[globalAuthor保存]
    F --> K[authorId返却]
    C --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-01 | 著者ID形式 | 著者IDは"a."プレフィックス + 16文字のランダム文字列 | 著者作成時 |
| BR-66-02 | カラーパレット | 64色のカラーパレットからランダムに割り当て | 著者作成時 |
| BR-66-03 | タイムスタンプ更新 | 既存著者アクセス時にタイムスタンプを更新 | 著者ID解決時 |

### 計算ロジック

著者ID生成:
```typescript
const author = `a.${randomString(16)}`;
```

カラー割り当て:
```typescript
const colorId = Math.floor(Math.random() * (getColorPalette().length));
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 著者作成 | globalAuthor:{authorId} | INSERT | 著者情報の作成 |
| トークンマッピング | token2author:{token} | INSERT | トークンと著者の関連付け |
| マッパーマッピング | mapper2author:{mapper} | INSERT | マッパーと著者の関連付け |
| 著者更新 | globalAuthor:{authorId} | UPDATE | 名前・カラー等の更新 |
| パッド追加 | globalAuthor:{authorId} | UPDATE | padIDs配列の更新 |

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

#### globalAuthor:{authorId}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | colorId | number/string | パレット番号または16進カラー |
| INSERT/UPDATE | name | string | 著者表示名 |
| INSERT/UPDATE | timestamp | number | 最終アクセス時刻 |
| UPDATE | padIDs | object | 貢献パッドIDのマップ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| apierror | 著者不存在 | authorIDが存在しない | エラーメッセージを返却 |

### リトライ仕様

エラー時は自動リトライなし。

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

ueberDB2のトランザクション管理に依存。複数の書き込みは非同期で実行される。

## パフォーマンス要件

- 著者ID解決: リアルタイム編集開始時に遅延なく完了すること

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

- 著者IDはランダム生成で推測困難
- トークンとの関連付けはセッション管理と連携

## 備考

- 64色のカラーパレットが定義されている
- 16進カラーコードでのカスタムカラーも対応

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | カラーパレット定義（27-92行目） |

**読解のコツ**: カラーパレットは64色の配列で定義されている。

#### Step 2: 著者ID解決処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | getAuthorId関数（158-163行目） |
| 2-2 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | mapAuthorWithDBKey関数（117-138行目） |

**主要処理フロー**:
1. **158-163行目**: getAuthorId関数 - フック呼び出しとフォールバック
2. **117-138行目**: mapAuthorWithDBKey関数 - トークン/マッパーからの著者検索

#### Step 3: 著者作成・更新処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | createAuthor関数（198-213行目） |
| 3-2 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | setAuthorName/setAuthorColorId関数 |

**主要処理フロー**:
- **198-213行目**: createAuthor関数 - 著者作成とカラー割り当て
- **246-247行目**: setAuthorName関数
- **232-233行目**: setAuthorColorId関数

#### Step 4: パッド関連付け処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | addPad/removePad関数 |
| 4-2 | AuthorManager.ts | `src/node/db/AuthorManager.ts` | listPadsOfAuthor関数 |

**主要処理フロー**:
- **278-298行目**: addPad関数 - 著者にパッドを追加
- **305-315行目**: removePad関数 - 著者からパッドを削除
- **253-271行目**: listPadsOfAuthor関数 - 著者の貢献パッド一覧

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

```
PadMessageHandler（ユーザー参加時）
    │
    └─ authorManager.getAuthorId(token, user)
           │
           ├─ hooks.aCallFirst('getAuthorId')
           │
           └─ getAuthor4Token(token)
                  │
                  └─ mapAuthorWithDBKey('token2author', token)
                         │
                         ├─ db.get(`token2author:${token}`)
                         │
                         ├─ [存在しない場合] createAuthor()
                         │      │
                         │      ├─ randomString(16)
                         │      ├─ Math.random() * colorPalette.length
                         │      └─ db.set(`globalAuthor:${author}`)
                         │
                         └─ db.set(`token2author:${token}`, authorId)
```

### データフロー図

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

トークン ───▶ getAuthorId()
                  │
                  ▼
         token2author検索
                  │
         ┌───────┴───────┐
         │               │
         ▼               ▼
    著者存在        著者不存在
         │               │
         ▼               ▼
  タイムスタンプ更新   createAuthor
         │               │
         │               ▼
         │        globalAuthor保存
         │               │
         └───────┬───────┘
                  │
                  ▼
              authorId返却
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AuthorManager.ts | `src/node/db/AuthorManager.ts` | ソース | 著者管理本体 |
| DB.ts | `src/node/db/DB.ts` | ソース | DB抽象化 |
| Pad.ts | `src/node/db/Pad.ts` | ソース | パッドとの連携 |
| SessionManager.ts | `src/node/db/SessionManager.ts` | ソース | セッションとの連携 |
| API.ts | `src/node/db/API.ts` | ソース | API層 |
