# 機能設計書 101-GraphQL API

## 概要

本ドキュメントは、GitLabのGraphQL APIによる機能アクセスについての機能設計書である。

### 本機能の処理概要

GraphQL APIは、GitLabの全機能に対してGraphQLプロトコルを使用したプログラマティックなアクセスを提供する機能である。REST APIに代わる柔軟なデータ取得手段として、クライアントが必要なデータのみを効率的に取得できる。

**業務上の目的・背景**：GitLabの機能を外部アプリケーション、CI/CDツール、IDE拡張機能、自動化スクリプトから利用するためのAPIアクセス手段を提供する。REST APIと比較して、オーバーフェッチやアンダーフェッチを防ぎ、単一リクエストで複数のリソースを取得できるため、パフォーマンスとネットワーク効率の向上が期待できる。

**機能の利用シーン**：
- IDE拡張機能（VS Code、JetBrains、Neovim）からのGitLabデータ取得
- 自動化スクリプトによるプロジェクト、イシュー、マージリクエストの操作
- カスタムダッシュボードやレポートツールからのデータ取得
- CI/CDパイプラインからのGitLabリソース操作
- GraphQL Explorerを使用したAPI探索とテスト

**主要な処理内容**：
1. GraphQLクエリの受付とパース
2. 認証・認可の検証（セッション、アクセストークン、OAuth）
3. クエリ複雑度・深度の制限チェック
4. リゾルバによるデータ取得
5. レスポンスのJSON形成と返却
6. マルチプレックス（複数クエリ同時実行）対応
7. サブスクリプション（リアルタイム更新）対応

**関連システム・外部連携**：
- GitLab REST API（一部機能の代替）
- ActionCable（WebSocketによるサブスクリプション）
- Sidekiq（バックグラウンドジョブ）
- Redis（キャッシュ、セッション管理）

**権限による制御**：
- 認証なしユーザー：公開データのみアクセス可能
- 認証ユーザー：権限に応じたリソースアクセス
- 管理者：全リソースアクセス、高いクエリ複雑度上限

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 319 | GraphQL Explorer | 主画面 | GraphQL APIエクスプローラ |

## 機能種別

データ取得（Query）/ データ操作（Mutation）/ リアルタイム通知（Subscription）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| query | String | Yes | GraphQLクエリ文字列 | 最大10,000文字 |
| variables | Hash | No | クエリ変数 | JSON形式 |
| operationName | String | No | 実行するオペレーション名 | マルチオペレーション時に必須 |
| _json | Array | No | マルチプレックス用クエリ配列 | Apollo形式 |
| remove_deprecated | Boolean | No | 非推奨フィールド除外フラグ | true/false |

### 入力データソース

- HTTPリクエストボディ（POST /api/graphql）
- GraphQL Explorer UI入力
- IDE拡張機能からのリクエスト
- 自動化スクリプトからのリクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| data | Object | クエリ結果データ |
| errors | Array | エラー情報配列 |
| extensions | Object | 追加メタデータ（オプション） |

### 出力先

- HTTPレスポンス（JSON形式）
- WebSocket（サブスクリプション時）

## 処理フロー

### 処理シーケンス

```
1. リクエスト受付
   └─ GraphqlController#execute がリクエストを受け付け
2. 認証処理
   └─ authenticate_sessionless_user! でアクセストークン検証
3. 認可チェック
   └─ authorize_access_api! でAPIアクセス権限確認
4. クエリサイズ制限
   └─ limit_query_size でクエリ文字数チェック（10,000文字上限）
5. ミューテーション制限
   └─ disallow_mutations_for_get でGET時のミューテーション禁止
6. クエリ実行
   └─ GitlabSchema.execute でクエリ解析・実行
7. レスポンス返却
   └─ JSON形式でレスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受付] --> B{認証トークン存在?}
    B -->|Yes| C[トークン検証]
    B -->|No| D{公開データ?}
    C -->|Valid| E[認可チェック]
    C -->|Invalid| F[401 Unauthorized]
    D -->|Yes| E
    D -->|No| G[403 Forbidden]
    E -->|Allowed| H[クエリサイズチェック]
    E -->|Denied| G
    H -->|OK| I{マルチプレックス?}
    H -->|Over| J[422 Query too large]
    I -->|Yes| K[multiplex実行]
    I -->|No| L{イントロスペクション?}
    L -->|Yes| M[キャッシュチェック]
    L -->|No| N[execute_query]
    M -->|Hit| O[キャッシュ返却]
    M -->|Miss| N
    K --> P[レスポンス返却]
    N --> P
    O --> P
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-101 | クエリ複雑度制限 | 未認証200、認証250、管理者300 | 全クエリ |
| BR-102 | クエリ深度制限 | 未認証15、認証20 | 全クエリ |
| BR-103 | クエリサイズ制限 | 最大10,000文字 | 全クエリ |
| BR-104 | GETミューテーション禁止 | GETリクエストでMutation禁止 | HTTPメソッドがGET |
| BR-105 | イントロスペクションキャッシュ | 標準イントロスペクションクエリは1日キャッシュ | 本番環境 |

### 計算ロジック

クエリ複雑度の計算:
- 各フィールドにcomplexity値が設定される
- 接続タイプ（配列）はページサイズ倍の複雑度
- 総複雑度が上限を超えると実行拒否

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| Query | 各種テーブル | SELECT | リゾルバ経由のデータ取得 |
| Mutation | 各種テーブル | INSERT/UPDATE/DELETE | リゾルバ経由のデータ操作 |

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

GraphQL APIは汎用的なインターフェースであり、実行されるクエリ・ミューテーションによって操作対象テーブルが異なる。各リゾルバにて具体的なDB操作が実装されている。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 401 | Unauthorized | 無効な認証トークン | 有効なトークン再発行 |
| 403 | Forbidden | API アクセス権限なし | 権限付与を依頼 |
| 422 | Unprocessable Entity | 不正なクエリ構文 | クエリ修正 |
| 429 | Too Many Requests | レート制限超過 | 待機後リトライ |
| 500 | Internal Server Error | サーバー内部エラー | 管理者に連絡 |
| 503 | Service Unavailable | タイムアウト・リソース枯渇 | 待機後リトライ |

### リトライ仕様

- 429エラー: `Retry-After`ヘッダに従って待機
- 503エラー: 指数バックオフで最大3回リトライ推奨

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

- Query: 読み取り専用、トランザクション不要
- Mutation: 個別ミューテーション単位でトランザクション管理
- マルチプレックス: 各クエリは独立したトランザクション

## パフォーマンス要件

- クエリタイムアウト: gitlab.yml の graphql_timeout で設定
- BatchLoaderによるN+1クエリ防止
- ページネーション: デフォルト最大100件/ページ
- イントロスペクションクエリ: 1日キャッシュ

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

- DPoP認証対応（オプション）
- Language Server制限
- CSRF保護（認証セッション時のみ）
- クエリ複雑度・深度制限によるDoS防止
- スコープベースの認可（read_api, api, ai_workflows）

## 備考

- GraphQL-Ruby gemを使用
- イントロスペクション結果はGitLab.revisionをキャッシュキーに含む
- VS Code、JetBrains、Neovim等のIDE拡張の利用状況を追跡

---

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

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

### 推奨読解順序

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

GraphQLスキーマの構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | gitlab_schema.rb | `app/graphql/gitlab_schema.rb` | GraphQLスキーマのルート定義、複雑度制限、型解決 |
| 1-2 | query_type.rb | `app/graphql/types/query_type.rb` | Queryルートの全フィールド定義 |
| 1-3 | mutation_type.rb | `app/graphql/types/mutation_type.rb` | Mutationルートの全ミューテーション定義 |

**読解のコツ**: `field`メソッドでクエリフィールド、`mount_mutation`メソッドでミューテーションが登録される。`resolver:`オプションで実際のデータ取得クラスが指定される。

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

HTTPリクエストの受付処理を確認。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | graphql_controller.rb | `app/controllers/graphql_controller.rb` | HTTPリクエスト処理、認証、クエリ実行 |

**主要処理フロー**:
1. **59行目**: `authenticate_sessionless_user!(:graphql_api)` でアクセストークン認証
2. **61行目**: `authorize_access_api!` でAPIアクセス権限確認
3. **71行目**: `limit_query_size` でクエリサイズ制限（10,000文字）
4. **74行目**: `disallow_mutations_for_get` でGETリクエストのMutation禁止
5. **93-101行目**: `execute`メソッドでクエリ実行
6. **253-260行目**: `execute_multiplex`でマルチプレックス処理
7. **257-260行目**: `execute_query`で単一クエリ処理

#### Step 3: スキーマ定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | gitlab_schema.rb | `app/graphql/gitlab_schema.rb` | スキーマ設定と複雑度計算 |

**主要処理フロー**:
- **4-12行目**: 複雑度上限定義（DEFAULT_MAX_COMPLEXITY等）
- **27-29行目**: Query/Mutation/Subscriptionタイプ登録
- **40-49行目**: `multiplex`メソッドで複数クエリ同時実行
- **166-191行目**: `max_query_complexity`と`max_query_depth`で制限計算

#### Step 4: 認証・認可を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | graphql_controller.rb | `app/controllers/graphql_controller.rb` | 認証フロー |

**主要処理フロー**:
- **307-316行目**: `authorize_access_api!`でAPIアクセス権限確認
- **135-146行目**: `check_dpop!`でDPoP認証（オプション）
- **284-295行目**: `context`メソッドで認証情報をGraphQLコンテキストに設定

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

```
GraphqlController#execute
    │
    ├─ authenticate_sessionless_user!(:graphql_api)
    │      └─ Gitlab::Auth::AuthFinders
    │
    ├─ authorize_access_api!
    │      └─ Ability.allowed?
    │
    ├─ limit_query_size
    │
    ├─ disallow_mutations_for_get
    │      └─ GraphQL::Query#mutation?
    │
    └─ execute_query / execute_multiplex
           │
           └─ GitlabSchema.execute / GitlabSchema.multiplex
                  │
                  ├─ Types::QueryType (Query実行時)
                  │      └─ Resolvers::* (各リゾルバ)
                  │
                  └─ Types::MutationType (Mutation実行時)
                         └─ Mutations::* (各ミューテーション)
```

### データフロー図

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

HTTP POST /api/graphql ───▶ GraphqlController#execute ───▶ JSON Response
    │                              │
    │ query                        ├─ 認証・認可
    │ variables                    ├─ クエリパース
    │ operationName                ├─ 複雑度チェック
    │                              ├─ リゾルバ実行
    │                              │      │
    │                              │      ├─ DB Query
    │                              │      └─ BatchLoader
    │                              │
    └──────────────────────────────┴─────────────────────▶ { data, errors }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| graphql_controller.rb | `app/controllers/graphql_controller.rb` | ソース | HTTPエンドポイント処理 |
| gitlab_schema.rb | `app/graphql/gitlab_schema.rb` | ソース | GraphQLスキーマ定義 |
| query_type.rb | `app/graphql/types/query_type.rb` | ソース | Queryルートタイプ |
| mutation_type.rb | `app/graphql/types/mutation_type.rb` | ソース | Mutationルートタイプ |
| subscription_type.rb | `app/graphql/types/subscription_type.rb` | ソース | Subscriptionルートタイプ |
| base_field.rb | `app/graphql/types/base_field.rb` | ソース | フィールド基底クラス |
| types/ | `app/graphql/types/` | ディレクトリ | 各種GraphQL型定義 |
| resolvers/ | `app/graphql/resolvers/` | ディレクトリ | データ取得リゾルバ |
| mutations/ | `app/graphql/mutations/` | ディレクトリ | データ操作ミューテーション |
