# 機能設計書 43-セッション削除

## 概要

本ドキュメントは、Etherpadにおけるセッション削除機能の詳細設計を記載したものである。この機能は、既存のセッションを削除し、著者のグループパッドへのアクセス権を取り消すAPI機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：
セキュリティ管理とアクセス制御の観点から、不要になったセッションや不正アクセスの可能性があるセッションを即座に無効化する必要がある。この機能により、管理者はユーザーのアクセス権を明示的に取り消すことができ、セキュリティインシデント発生時の迅速な対応が可能となる。

**機能の利用シーン**：
- ユーザーが明示的にログアウトする場合
- 管理者がユーザーのアクセス権を取り消す場合
- セキュリティインシデント発生時に特定ユーザーのセッションを強制終了する場合
- 有効期限前にセッションを無効化する場合

**主要な処理内容**：
1. セッションIDの存在確認
2. セッションに関連するグループID・著者IDの取得
3. group2sessionsからセッションIDの関連を削除
4. author2sessionsからセッションIDの関連を削除
5. セッションレコード自体の削除

**関連システム・外部連携**：
- ueberDB2データベースによるデータ永続化
- クライアント側のセッションCookie管理と連携

**権限による制御**：
- APIキーまたはOAuth2トークンによる認証が必要
- 管理者権限での操作を想定

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は直接的な画面連携はなく、APIとして提供される |

## 機能種別

CRUD操作（DELETE）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sessionID | string | Yes | セッションID（形式: s.XXXXXXXXXXXXXXXX） | セッションが存在すること |

### 入力データソース

- REST API: `DELETE /api/2/sessions`
- リクエストボディ（JSON形式）でパラメータを受け取る

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| code | number | 処理結果コード（0: 成功、1: パラメータエラー） |
| message | string | 処理結果メッセージ |
| data | null | 削除成功時はnull |

### 出力先

- HTTP Response（JSON形式）
- Content-Type: application/json

## 処理フロー

### 処理シーケンス

```
1. APIリクエスト受信
   └─ RestAPI.ts で /api/2/sessions (DELETE) エンドポイントを処理

2. 認証・認可チェック
   └─ APIHandler.ts で APIキーまたはOAuth2トークンを検証

3. パラメータ抽出
   └─ リクエストボディから sessionID を取得

4. API関数呼び出し
   └─ API.ts 経由で SessionManager.deleteSession を呼び出し

5. セッション存在チェック
   └─ session:{sessionID} の存在確認

6. セッション情報取得
   └─ groupID と authorID を取得

7. 関連データ削除（並列実行）
   └─ group2sessions:{groupID} と author2sessions:{authorID} からセッションIDを削除

8. セッションレコード削除
   └─ session:{sessionID} を削除

9. レスポンス返却
   └─ 成功レスポンスを返却
```

### フローチャート

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B{認証チェック}
    B -->|失敗| C[401 Unauthorized]
    B -->|成功| D[sessionIDパラメータ取得]
    D --> E[DB: session取得]
    E --> F{セッション存在?}
    F -->|No| G[エラー: sessionID does not exist]
    F -->|Yes| H[groupID, authorID取得]
    H --> I[group2sessions更新]
    H --> J[author2sessions更新]
    I --> K[session削除]
    J --> K
    K --> L[レスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-43-01 | セッション存在必須 | 指定されたセッションIDが存在しない場合はエラー | 常時 |
| BR-43-02 | 関連削除先行 | セッションレコード削除前に関連データを削除 | 常時 |
| BR-43-03 | べき等性なし | 同一セッションの2回目以降の削除はエラー | 常時 |

### 計算ロジック

該当なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| セッション確認 | session:{sessionID} | SELECT | セッションの存在確認と情報取得 |
| グループ関連削除 | group2sessions:{groupID} | UPDATE | セッションIDの削除（undefined設定） |
| 著者関連削除 | author2sessions:{authorID} | UPDATE | セッションIDの削除（undefined設定） |
| セッション削除 | session:{sessionID} | DELETE | セッションレコードの削除 |

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

#### session:{sessionID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | groupID | 取得 | 関連削除用 |
| SELECT | authorID | 取得 | 関連削除用 |
| DELETE | - | レコード全体 | db.removeで削除 |

#### group2sessions:{groupID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sessionIDs.{sessionID} | undefined | setSubでundefined設定により削除 |

#### author2sessions:{authorID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | sessionIDs.{sessionID} | undefined | setSubでundefined設定により削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | apierror | sessionIDが存在しない | 正しいセッションIDを指定 |
| 4 | 認証エラー | APIキーまたはトークンが無効 | 正しい認証情報を設定 |

### リトライ仕様

リトライは推奨しない（べき等性がないため、2回目以降はエラー）

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

- group2sessionsとauthor2sessionsの更新はPromise.allで並列実行
- 関連データ削除完了後にセッションレコードを削除することで整合性を確保
- setSubでundefinedを設定することでプロパティを削除（JSON.stringifyで無視される）

## パフォーマンス要件

- レスポンス時間: 150ms以内（標準的な環境）
- 関連データ更新の並列実行により処理時間を最適化

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

- APIキー認証またはOAuth2認証による保護
- セッション削除後、該当セッションIDでのアクセスは即座に無効化
- 関連データとセッションレコードの両方を確実に削除

## 備考

- セッション削除後もクライアント側のCookieは残る可能性がある
- クライアントは次回アクセス時にセッション無効エラーを受け取る
- グループ削除時にはGroupManager経由で関連セッションも削除される

---

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

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

### 推奨読解順序

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

セッション削除時の関連データ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SessionManager.ts | `src/node/db/SessionManager.ts` | セッション削除時の関連テーブル操作を理解 |

**読解のコツ**:
- setSubでundefinedを設定するとプロパティが削除される仕組みを理解
- db.removeによるレコード削除を理解

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

REST APIエンドポイントの定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestAPI.ts | `src/node/handler/RestAPI.ts` | DELETE /sessions エンドポイントの定義 |

**主要処理フロー**:
1. **466-485行目**: DELETE /sessions エンドポイントの定義
2. **467行目**: functionName: 'deleteSession' の指定
3. **468-481行目**: sessionID パラメータの定義

#### Step 3: ビジネスロジック層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SessionManager.ts | `src/node/db/SessionManager.ts` | deleteSession関数の実装 |

**主要処理フロー**:
- **184-206行目**: deleteSession関数の実装
- **186-189行目**: セッション存在チェック
- **192-193行目**: groupID, authorID取得
- **195-201行目**: 関連データの並列削除（setSubでundefined設定）
- **205行目**: セッションレコードの削除

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

```
HTTP Request: DELETE /api/2/sessions
    │
    ├─ RestAPI.ts: expressCreateServer (エンドポイント定義)
    │      └─ mapping.get(DELETE)!["/sessions"]
    │
    ├─ APIHandler.ts: handle (認証・パラメータ処理)
    │      ├─ 認証チェック（APIキー or OAuth2）
    │      └─ api[functionName].apply() 呼び出し
    │
    └─ SessionManager.ts: deleteSession
           ├─ db.get(`session:${sessionID}`)
           ├─ Promise.all([
           │     db.setSub(`group2sessions:${groupID}`, ..., undefined),
           │     db.setSub(`author2sessions:${authorID}`, ..., undefined)
           │  ])
           └─ db.remove(`session:${sessionID}`)
```

### データフロー図

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

sessionID (string)  ───▶  SessionManager.deleteSession  ───▶  void (成功)
                               │
                               ├─▶ DB: session:{sessionID} → 削除
                               ├─▶ DB: group2sessions:{groupID} → 更新
                               └─▶ DB: author2sessions:{authorID} → 更新
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| API.ts | `src/node/db/API.ts` | ソース | API関数の集約・エクスポート |
| SessionManager.ts | `src/node/db/SessionManager.ts` | ソース | セッション管理のビジネスロジック |
| RestAPI.ts | `src/node/handler/RestAPI.ts` | ソース | RESTエンドポイント定義 |
| APIHandler.ts | `src/node/handler/APIHandler.ts` | ソース | API認証・パラメータ処理 |
| DB.ts | `src/node/db/DB.ts` | ソース | データベース接続・操作 |
| sessionsAndGroups.ts | `src/tests/backend/specs/api/sessionsAndGroups.ts` | テスト | APIのテストケース |
