# 機能設計書 61-アプリ取得

## 概要

本ドキュメントは、Giselleシステムにおける「アプリ取得」機能の設計仕様を定義する。

### 本機能の処理概要

アプリ取得機能は、指定されたアプリIDに基づいてストレージからアプリ情報を取得する機能である。アプリとは、ワークフローを公開・実行可能な形式で保存したエンティティであり、パラメータ定義やエントリーポイント情報を含む。

**業務上の目的・背景**：ワークフローをアプリとして公開することで、エンドユーザーは複雑なワークフロー構造を意識することなく、シンプルなパラメータ入力のみでAIワークフローを実行できる。本機能は、保存されたアプリ情報を取得し、実行やプレビュー、編集画面での表示に利用するために必要不可欠である。

**機能の利用シーン**：
- ロビー画面でのアプリ一覧表示時
- プレイグラウンド画面でのアプリ実行前の情報取得
- ショーケース画面での公開アプリ詳細表示
- アプリ詳細画面での実行統計や設定情報の取得

**主要な処理内容**：
1. 入力としてアプリID（`AppId`）を受け取る
2. アプリIDからストレージパスを生成（`apps/{appId}.json`）
3. ストレージからJSONデータを取得し、Appスキーマでバリデーション
4. バリデーション済みのアプリオブジェクトを返却

**関連システム・外部連携**：
- `@giselles-ai/storage`パッケージによるストレージ抽象化レイヤー
- Vercel Blob Storage（本番環境）またはローカルファイルシステム（開発環境）

**権限による制御**：本機能自体には認証・認可チェックは含まれない。呼び出し元のAPIレイヤーにて適切な認可制御が行われることを前提とする。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 14 | ロビー画面 | API連携 | アプリ一覧の非同期取得 |
| 15 | ロビー画面（V2） | 補助機能 | テンプレートアプリの取得と表示 |
| 18 | プレイグラウンド画面 | 補助機能 | 実行可能なアプリ一覧の取得 |
| 22 | ショーケース画面 | 主機能 | 公開アプリのショーケース一覧取得と表示 |
| 23 | アプリ詳細画面 | 主機能 | アプリの詳細情報、実行統計の取得と表示 |
| 24 | プレイリスト詳細画面 | 主機能 | プレイリスト内のアプリ詳細の取得と表示 |

## 機能種別

データ取得（READ）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| appId | `AppId` | Yes | 取得対象のアプリID | `app_`プレフィックスで始まる文字列 |

### 入力データソース

- APIリクエストのパラメータとして受け取る
- AppIdは`createIdGenerator("app")`で生成されたユニークID形式

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | `AppId` | アプリの一意識別子 |
| version | `"v1"` | アプリスキーマバージョン |
| state | `"disconnected" \| "connected"` | アプリの接続状態 |
| description | `string` | アプリの説明 |
| parameters | `AppParameter[]` | アプリ実行時の入力パラメータ定義 |
| entryNodeId | `NodeId` | ワークフロー開始ノードのID |
| endNodeId | `NodeId` | （connectedの場合のみ）終了ノードのID |
| workspaceId | `WorkspaceId` | 関連するワークスペースのID |

### 出力先

- API呼び出し元へのレスポンスとして返却
- React Queryのキャッシュ（クライアント側）

## 処理フロー

### 処理シーケンス

```
1. 入力バリデーション
   └─ Zodスキーマによるappidの検証

2. ストレージパス生成
   └─ appPath関数でapps/{appId}.jsonパスを生成

3. JSONデータ取得
   └─ storage.getJson()でストレージからデータ取得
   └─ Appスキーマでのパース・バリデーション

4. 結果返却
   └─ バリデーション済みAppオブジェクトを返却
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[appIdを受け取る]
    B --> C[appPath関数でパス生成]
    C --> D[storage.getJson呼び出し]
    D --> E{データ取得成功?}
    E -->|Yes| F[Appスキーマでパース]
    F --> G{パース成功?}
    G -->|Yes| H[Appオブジェクト返却]
    G -->|No| I[ZodError発生]
    E -->|No| J[エラー発生]
    H --> K[終了]
    I --> K
    J --> K
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-61-01 | アプリID形式 | AppIdは`app_`プレフィックスで始まる必要がある | 常時 |
| BR-61-02 | スキーマ互換性 | 旧形式（DeprecatedApp）は自動的に新形式に変換される | 旧データ読み込み時 |
| BR-61-03 | 状態管理 | アプリは`disconnected`または`connected`のいずれかの状態を持つ | 常時 |

### 計算ロジック

本機能に特別な計算ロジックは存在しない。

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

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

本機能はBlobストレージのみを使用し、リレーショナルデータベースへの直接アクセスは行わない。

| 操作 | 対象ストレージ | 操作種別 | 概要 |
|-----|-------------|---------|------|
| アプリ取得 | Blob Storage | GET | apps/{appId}.jsonからJSONデータを読み取り |

### ストレージ操作詳細

#### Blobストレージ

| 操作 | パス | データ形式 | 備考 |
|-----|------|----------|------|
| GET | apps/{appId}.json | JSON | Appスキーマに準拠 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ZodError | AppIdのバリデーション失敗 | 正しい形式のAppIdを指定する |
| - | StorageError | ストレージからのデータ取得失敗 | ストレージ接続を確認、存在するアプリIDを指定 |
| - | ZodError | Appスキーマのパース失敗 | データ整合性を確認、必要に応じてデータ修復 |

### リトライ仕様

ストレージアクセス失敗時のリトライは、ストレージドライバ層で実装される。アプリケーション層でのリトライは行わない。

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

読み取り専用操作のため、トランザクション管理は不要。

## パフォーマンス要件

- レスポンス時間: 100ms以内（ストレージレイテンシを含む）
- 同時リクエスト: ストレージの制限に依存

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

- 認証・認可: API呼び出し元で実装（本機能では未実装）
- データ保護: ストレージレベルでの暗号化に依存
- 監査ログ: ストレージアクセスログによる追跡

## 備考

- `DeprecatedApp`形式からの自動マイグレーションをサポート
- アプリとワークスペースは1:1の関係

---

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

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

### 推奨読解順序

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

まず、Appエンティティの型定義を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | app-id.ts | `packages/protocol/src/app/app-id.ts` | AppIdの生成方法（`app_`プレフィックス）を理解 |
| 1-2 | app.ts | `packages/protocol/src/app/app.ts` | App, ConnectedApp, DisconnectedAppの型定義と判別共用体の理解 |

**読解のコツ**:
- `createIdGenerator`関数がプレフィックス付きIDを生成するユーティリティ
- `z.discriminatedUnion`による型安全な状態管理パターンに注目
- **7-17行目**: AppParameterType、AppParameterId、AppParameterの定義
- **26-35行目**: DisconnectedAppスキーマ定義
- **37-47行目**: ConnectedAppスキーマ定義（endNodeIdを持つ）
- **61-71行目**: App型のpreprocess処理（旧形式の自動変換）

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | get-app.ts | `packages/giselle/src/apps/get-app.ts` | getApp関数の実装 |

**主要処理フロー**:
1. **6行目**: `createGiselleFunction`でラップされた関数定義
2. **7行目**: 入力スキーマとして`AppId.schema`を使用
3. **8-13行目**: handler内でstorage.getJsonを呼び出し、Appスキーマでバリデーション

#### Step 3: ユーティリティ関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | path.ts | `packages/giselle/src/path.ts` | appPath関数によるストレージパス生成ロジック |
| 3-2 | create-giselle-function.ts | `packages/giselle/src/utils/create-giselle-function.ts` | Giselle関数のラッパーパターン |

**主要処理フロー**:
- **16-18行目（path.ts）**: `apps/${appId}.json`形式でパスを生成
- **19-43行目（create-giselle-function.ts）**: 入力バリデーションとハンドラ実行のラッピング

#### Step 4: ストレージ抽象化を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | types.ts | `packages/storage/src/types.ts` | GiselleStorageインターフェースの定義 |

**主要処理フロー**:
- **5-8行目**: GetJsonParamsの型定義（path, schemaを受け取る）
- **65-75行目**: GiselleStorageインターフェース（getJson, setJson, remove等のメソッド）

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

```
Giselle.getApp (giselle.ts:433)
    │
    └─ bindGiselleFunction(getApp, context)
           │
           └─ getApp (get-app.ts:6-14)
                  │
                  ├─ appPath(input.appId) (path.ts:16-18)
                  │
                  └─ context.storage.getJson({path, schema: App})
                         │
                         └─ ストレージドライバ (fs-storage-driver.ts or memory-storage-driver.ts)
```

### データフロー図

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

AppId (string)  ───▶ appPath() ───▶ Storage Path
     "app_xxx"       generates      "apps/app_xxx.json"
                          │
                          ▼
                   storage.getJson()
                          │
                          ▼
                   Zod Validation ───▶ App Object
                   (App schema)        {id, version, state, ...}
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| get-app.ts | `packages/giselle/src/apps/get-app.ts` | ソース | メイン処理の実装 |
| app.ts | `packages/protocol/src/app/app.ts` | ソース | Appエンティティの型定義 |
| app-id.ts | `packages/protocol/src/app/app-id.ts` | ソース | AppId型の定義 |
| path.ts | `packages/giselle/src/path.ts` | ソース | ストレージパス生成ユーティリティ |
| create-giselle-function.ts | `packages/giselle/src/utils/create-giselle-function.ts` | ソース | 関数ラッパーユーティリティ |
| types.ts | `packages/storage/src/types.ts` | ソース | ストレージインターフェース定義 |
| giselle.ts | `packages/giselle/src/giselle.ts` | ソース | Giselleクラスのエントリーポイント |
