# 機能設計書 23-セッション共有

## 概要

本ドキュメントは、OpenCodeにおけるセッション共有機能の設計を定義する。セッション共有は、AIアシスタントとの会話履歴を外部URLで公開し、他のユーザーと共有可能にする機能である。

### 本機能の処理概要

セッション共有機能は、ローカルのセッションデータを外部サービス（opncd.ai）にアップロードし、公開URLを生成する機能である。リアルタイム同期により、セッションの更新が自動的に共有先に反映される。

**業務上の目的・背景**：開発者がAIとの対話内容をチームメンバーやコミュニティと共有し、知識の共有やデバッグ支援を促進する。コードレビューや問題解決のコンテキストを共有する際に有用。

**機能の利用シーン**：ユーザーが「この会話を同僚に見せたい」「この解決策をブログに掲載したい」という場合に利用される。共有URLをコピーして他者に送信することで、セッション内容を閲覧可能にする。

**主要な処理内容**：
1. 共有APIへのセッション作成リクエスト
2. 共有ID・シークレット・URLの取得とローカル保存
3. セッション・メッセージ・パーツのフル同期
4. イベントベースのリアルタイム同期（継続的）
5. 共有解除（削除）機能

**関連システム・外部連携**：opncd.ai（共有サービス）へのHTTP API呼び出し。エンタープライズ環境では設定されたカスタムURLを使用。

**権限による制御**：設定ファイルでshare: "disabled"が設定されている場合、共有機能は無効化される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 22 | シェアレイアウト | 主画面 | セッション共有機能のレイアウト提供 |
| 23 | シェア詳細 | 主画面 | 共有されたセッションの詳細表示 |
| 26 | セッション | 補助機能 | コマンドからのセッション共有機能 |

## 機能種別

データ連携処理 / 外部API呼び出し

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sessionID | string | Yes | 共有対象セッションのID | session_で始まるIdentifier形式 |

### 入力データソース

- SessionTable: セッション情報
- MessageTable: メッセージ情報
- PartTable: パーツ情報
- Config: 共有設定（share: "auto" | "disabled"、enterprise.url）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | 共有ID |
| url | string | 公開URL（例: https://opncd.ai/share/xxx） |
| secret | string | 更新・削除用シークレットトークン |

### 出力先

- opncd.ai API（外部サービス）
- SQLiteデータベース（SessionShareTable）- ローカルキャッシュ
- SessionTable.share_url - セッション情報の更新

## 処理フロー

### 処理シーケンス

```
1. 共有設定の確認
   └─ config.share === "disabled"の場合はエラー

2. 共有API呼び出し（POST /api/share）
   └─ sessionIDを送信、共有ID・URL・シークレットを取得

3. ローカルDBへの保存
   └─ SessionShareTableにレコード挿入（onConflictDoUpdate）

4. フル同期の実行
   └─ セッション、メッセージ、パーツ、差分情報を一括送信

5. セッション情報の更新
   └─ SessionTable.share_urlを更新

6. イベントリスナーの登録（init時）
   └─ session.updated、message.updated、message.part.updated、session.diffを監視
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B{共有無効?}
    B -->|Yes| C[エラー: Sharing is disabled]
    B -->|No| D[共有API呼び出し]
    D --> E{APIレスポンス成功?}
    E -->|No| F[エラー処理]
    E -->|Yes| G[ローカルDBに保存]
    G --> H[フル同期実行]
    H --> I[share_url更新]
    I --> J[イベント発行]
    J --> K[結果返却]
    K --> L[終了]

    M[イベント発生] --> N{共有有効?}
    N -->|Yes| O[同期キューに追加]
    O --> P{1秒タイムアウト?}
    P -->|Yes| Q[バッチ同期送信]
    N -->|No| R[スキップ]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-23-01 | 共有無効化 | config.share === "disabled"の場合、共有機能は使用不可 | 設定で無効化されている場合 |
| BR-23-02 | 環境変数による無効化 | OPENCODE_DISABLE_SHARE=true/1で共有機能を無効化 | 環境変数が設定されている場合 |
| BR-23-03 | バッチ同期 | 同期リクエストは1秒間バッファリングされ、まとめて送信 | イベント駆動の同期時 |
| BR-23-04 | エンタープライズURL | enterprise.urlが設定されている場合、そのURLを共有サービスのベースURLとして使用 | エンタープライズ環境 |

### 計算ロジック

共有URLの構築:
```typescript
// デフォルト
const baseUrl = config.enterprise?.url ?? "https://opncd.ai"
// 共有URL例: https://opncd.ai/share/{shareId}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 共有作成 | session_share | INSERT/UPDATE | 共有情報のローカル保存 |
| 共有URL設定 | session | UPDATE | share_urlカラムの更新 |
| 共有解除 | session_share | DELETE | 共有情報の削除 |
| 共有解除 | session | UPDATE | share_urlをnullに更新 |

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

#### SessionShareTable

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | session_id | 共有対象セッションID | 主キー |
| INSERT | id | 共有サービスから取得したID | 外部ID |
| INSERT | secret | 共有サービスから取得したシークレット | 更新・削除用 |
| INSERT | url | 共有URL | 公開URL |

#### SessionTable

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | share_url | 共有URL | 共有作成時 |
| UPDATE | share_url | null | 共有解除時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | 共有が無効化されている | "Sharing is disabled in configuration"エラー |
| - | ネットワークエラー | API呼び出し失敗 | 自動共有時は静かに無視、手動時はエラー伝播 |

### リトライ仕様

リトライ機構は実装されていない。API呼び出し失敗時は処理を中断する。

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

共有作成と同期は非同期で実行される。フル同期は共有作成直後にバックグラウンドで実行される（awaitなし）。

## パフォーマンス要件

- 共有作成のAPI呼び出しは5秒以内に完了すること
- バッチ同期は1秒間のバッファリング後に実行
- 大規模セッションのフル同期は数秒かかる可能性あり

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

- シークレットトークンはローカルDBにのみ保存
- シークレットがないと共有内容の更新・削除は不可
- 共有URLは予測困難な形式
- 共有コンテンツは公開される点をユーザーに明示すべき

## 備考

- 共有はセッション単位で行われる
- 子セッションの自動共有は親セッションと独立
- モデル情報も共有データに含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | share.sql.ts | `packages/opencode/src/share/share.sql.ts` | SessionShareTableの定義 |
| 1-2 | index.ts | `packages/opencode/src/session/index.ts` | Session.Info.shareの定義（131-135行目） |

**読解のコツ**: 共有情報はSessionShareTableにローカル保存され、share_urlはSessionTableに格納される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.ts | `packages/opencode/src/session/index.ts` | Session.share関数（341-355行目） |
| 2-2 | index.ts | `packages/opencode/src/session/index.ts` | Session.unshare関数（357-367行目） |

**主要処理フロー**:
1. **341-345行目**: 設定チェック（share === "disabled"でエラー）
2. **346行目**: ShareNext.create呼び出し（動的import）
3. **348-354行目**: DB更新とイベント発行

#### Step 3: 共有サービス連携を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | share-next.ts | `packages/opencode/src/share/share-next.ts` | ShareNext.create関数（69-93行目） |
| 3-2 | share-next.ts | `packages/opencode/src/share/share-next.ts` | ShareNext.init関数（21-67行目） |
| 3-3 | share-next.ts | `packages/opencode/src/share/share-next.ts` | sync関数（126-160行目） |
| 3-4 | share-next.ts | `packages/opencode/src/share/share-next.ts` | fullSync関数（179-209行目） |

**主要処理フロー**:
- **69-93行目**: 外部API呼び出しと結果のローカル保存
- **21-67行目**: イベントリスナー登録（session.updated等）
- **126-160行目**: バッチ同期（1秒バッファリング）
- **179-209行目**: 全データの一括同期

#### Step 4: 共有解除を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | share-next.ts | `packages/opencode/src/share/share-next.ts` | ShareNext.remove関数（162-177行目） |

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

```
Session.share (public API)
    │
    ├─ Config.get()
    │      └─ 共有設定確認
    │
    └─ ShareNext.create(sessionID)
           │
           ├─ fetch (POST /api/share)
           │      └─ 共有ID・URL・シークレット取得
           │
           ├─ Database.use()
           │      └─ SessionShareTableに保存
           │
           └─ fullSync(sessionID) [非同期]
                  │
                  ├─ Session.get()
                  ├─ Session.diff()
                  ├─ MessageV2.stream()
                  ├─ Provider.getModel()
                  │
                  └─ sync() [バッチ送信]
                         └─ fetch (POST /api/share/{id}/sync)

ShareNext.init() [起動時]
    │
    ├─ Bus.subscribe(Session.Event.Updated)
    ├─ Bus.subscribe(MessageV2.Event.Updated)
    ├─ Bus.subscribe(MessageV2.Event.PartUpdated)
    └─ Bus.subscribe(Session.Event.Diff)
           │
           └─ sync() [各イベントで呼び出し]
```

### データフロー図

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

sessionID ──────▶ Session.share() ───────────────────▶ {id, url, secret}
                        │
                        ├─ 設定確認
                        │
                        └─ ShareNext.create()
                               │
                               ├─ API呼び出し ───────▶ opncd.ai
                               │
                               ├─ ローカル保存 ──────▶ SessionShareTable
                               │
                               └─ fullSync()
                                      │
Session ────────┐                     │
Messages ───────┼────────────────────▶├──────────────▶ 同期API
Parts ──────────┤                     │
Diffs ──────────┤                     │
Models ─────────┘                     │
                                      │
[イベント]                            │
session.updated ────────────────────▶ sync() ────────▶ opncd.ai
message.updated ────────────────────▶
message.part.updated ───────────────▶
session.diff ───────────────────────▶
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| share-next.ts | `packages/opencode/src/share/share-next.ts` | ソース | 共有機能のメイン実装 |
| share.sql.ts | `packages/opencode/src/share/share.sql.ts` | ソース | SessionShareTableの定義 |
| index.ts | `packages/opencode/src/session/index.ts` | ソース | Session.share、Session.unshare関数 |
| config.ts | `packages/opencode/src/config/config.ts` | ソース | 共有設定の読み込み |
| bus.ts | `packages/opencode/src/bus/index.ts` | ソース | イベント購読 |
