# 画面設計書 83-フィーチャーフラグ新規作成

## 概要

本ドキュメントは、GitLabのフィーチャーフラグ新規作成画面の設計仕様を定義するものである。

### 本画面の処理概要

フィーチャーフラグ新規作成画面は、プロジェクトに新しいフィーチャーフラグを登録するための画面である。フィーチャーフラグの名前、説明、およびロールアウト戦略を設定して作成を行う。

**業務上の目的・背景**：新機能のリリースを制御するためのフィーチャーフラグを作成する。フィーチャーフラグを活用することで、コードのデプロイとは独立して機能の有効/無効を切り替えられるようになり、段階的リリース、A/Bテスト、緊急時の機能無効化などが可能になる。作成時にロールアウト戦略（全ユーザー、特定ユーザーID、パーセント割合など）を設定することで、どのユーザーに機能を提供するかを細かく制御できる。

**画面へのアクセス方法**：フィーチャーフラグ一覧画面から「New feature flag」ボタンをクリック、またはURL直接アクセス。URLパターンは `/:namespace/:project/-/feature_flags/new` となる。

**主要な操作・処理内容**：
1. フィーチャーフラグ名の入力（必須、2-63文字）
2. 説明の入力（オプション、最大255文字）
3. ロールアウト戦略の追加・設定
4. 戦略の種類選択（All Users、Percent rollout、User IDs、User List）
5. 環境スコープの設定
6. 関連Issueのリンク（オプション）
7. フィーチャーフラグの作成実行

**画面遷移**：
- 遷移元：フィーチャーフラグ一覧画面
- 遷移先：フィーチャーフラグ一覧画面（作成成功時）、同一画面（エラー時）

**権限による表示制御**：
- `create_feature_flag`権限がない場合はアクセス不可
- 関連Issueのリンク機能は`featureFlagIssuesEndpoint`が設定されている場合のみ表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 59 | フィーチャーフラグ | 主機能 | 新規フィーチャーフラグの作成 |

## 画面種別

登録

## URL/ルーティング

```
GET /:namespace/:project/-/feature_flags/new
POST /:namespace/:project/-/feature_flags.json (API)
```

## 入出力項目

### 入力項目

| 項目名 | データ型 | 必須 | バリデーション | 説明 |
|--------|----------|------|----------------|------|
| Name | String | 必須 | 2-63文字、`/^[a-z][a-z0-9_-]*[a-z0-9]$/`形式 | フィーチャーフラグの識別名 |
| Description | String | - | 最大255文字 | フィーチャーフラグの説明 |
| Strategies | Array<Strategy> | - | - | ロールアウト戦略の配列 |

### 戦略（Strategy）項目

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| name | String | 必須 | 戦略タイプ（default/gradualRolloutUserId/userWithId/gitlabUserList） |
| parameters | Object | - | 戦略パラメータ（percentage、userIds、groupId、stickiness等） |
| scopes | Array<Scope> | - | 適用環境スコープ |
| user_list_id | Integer | - | ユーザーリストID（gitlabUserList戦略時） |

### 環境スコープ（Scope）項目

| 項目名 | データ型 | 必須 | 説明 |
|--------|----------|------|------|
| environment_scope | String | 必須 | 環境名のパターン（例: `*`, `production`, `staging/*`） |

## 表示項目

本画面は登録フォームのため、表示専用項目は限定的。

| 項目名 | データ型 | 説明 |
|--------|----------|------|
| タイトル | String | "New feature flag" |
| ヘルプテキスト | String | 戦略設定に関する説明文 |
| エラーメッセージ | Array<String> | バリデーションエラーメッセージ |

## イベント仕様

### 1-フィーチャーフラグ作成

**トリガー**: 「Create feature flag」ボタン押下

**前提条件**:
- Name項目が入力されている
- 入力値がバリデーションを満たしている

**処理フロー**:
1. フォームデータを収集（name, description, active, version, strategies）
2. Vuexアクション`createFeatureFlag`を実行
3. POSTリクエストを`/:namespace/:project/-/feature_flags.json`に送信
4. 成功時：フィーチャーフラグ一覧画面へリダイレクト
5. 失敗時：エラーメッセージを表示

**送信データ形式**:
```json
{
  "operations_feature_flag": {
    "name": "flag_name",
    "description": "description",
    "active": true,
    "version": "new_version_flag",
    "strategies_attributes": [
      {
        "name": "default",
        "parameters": {},
        "scopes_attributes": [
          { "environment_scope": "*" }
        ]
      }
    ]
  }
}
```

**遷移先**: フィーチャーフラグ一覧画面 または 同一画面（エラー時）

### 2-戦略追加

**トリガー**: 「Add strategy」ボタン押下

**処理フロー**:
1. 新しい戦略オブジェクト`{ name: 'default', parameters: {}, scopes: [] }`を追加
2. Strategyコンポーネントが追加表示される

**遷移先**: 画面内更新

### 3-戦略削除

**トリガー**: 戦略の削除ボタン押下

**処理フロー**:
1. 対象の戦略を配列から削除
2. 表示から削除

**遷移先**: 画面内更新

### 4-キャンセル

**トリガー**: 「Cancel」ボタン押下

**処理フロー**: フィーチャーフラグ一覧画面へ遷移

**遷移先**: `/:namespace/:project/-/feature_flags`

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 作成 | operations_feature_flags | INSERT | フィーチャーフラグの作成 |
| 作成 | operations_feature_flags_strategies | INSERT | 戦略の作成 |
| 作成 | operations_scopes | INSERT | スコープの作成 |

### テーブル別更新項目詳細

#### operations_feature_flags

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | project_id | 現在のプロジェクトID | |
| INSERT | name | フォーム入力値 | |
| INSERT | description | フォーム入力値（NULL可） | |
| INSERT | active | true（デフォルト） | |
| INSERT | version | 2（new_version_flag） | |
| INSERT | iid | プロジェクト内での自動採番 | AtomicInternalId |

#### operations_feature_flags_strategies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | feature_flag_id | 作成されたフラグのID | |
| INSERT | name | 戦略タイプ名 | default, gradualRolloutUserId等 |
| INSERT | parameters | JSON形式のパラメータ | |
| INSERT | user_list_id | ユーザーリストID（該当する場合） | |

#### operations_scopes

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | strategy_id | 作成された戦略のID | |
| INSERT | environment_scope | 環境スコープパターン | |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-001 | エラー | Name is too short (minimum is 2 characters) | 名前が短すぎる場合 |
| MSG-002 | エラー | Name is too long (maximum is 63 characters) | 名前が長すぎる場合 |
| MSG-003 | エラー | Name can contain only lowercase letters, digits, '_' and '-'. Must start with a letter, and cannot end with '-' or '_' | 名前のフォーマット不正 |
| MSG-004 | エラー | Name has already been taken | 重複する名前 |
| MSG-005 | 情報 | Enable features for specific users and environments by configuring feature flag strategies. | 戦略設定のヘルプテキスト |
| MSG-006 | 情報 | Feature Flag has no strategies | 戦略が0件の場合 |

## 例外処理

| 例外 | 原因 | 対処 |
|------|------|------|
| 403 Forbidden | create_feature_flag権限がない | アクセス拒否画面へリダイレクト |
| 422 Unprocessable Entity | バリデーションエラー | エラーメッセージを表示 |
| 400 Bad Request | リクエスト形式エラー | エラーメッセージを表示 |

## 備考

- 作成時にactive属性はデフォルトでtrueに設定される
- version属性は`new_version_flag`（値: 2）のみがサポートされる（旧バージョンは廃止済み）
- 初期状態では1つの`default`（All Users）戦略がデフォルトで設定される
- 環境スコープには`*`（全環境）やワイルドカードパターン（例: `staging/*`）が使用可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | feature_flag.rb | `app/models/operations/feature_flag.rb` | モデル定義、バリデーション、accepts_nested_attributes |
| 1-2 | constants.js | `app/assets/javascripts/feature_flags/constants.js` | 戦略タイプ定数の定義 |

**読解のコツ**: `accepts_nested_attributes_for :strategies`によりストラテジーが一括で作成される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | feature_flags_controller.rb | `app/controllers/projects/feature_flags_controller.rb` | newアクション、createアクション |
| 2-2 | new.html.haml | `app/views/projects/feature_flags/new.html.haml` | Vueマウントポイントとdata属性 |

**主要処理フロー**:
1. **7行目**: `authorize_create_feature_flag!`で作成権限チェック
2. **33行目**: `new`アクションは空（Vueでハンドリング）
3. **45-56行目**: `create`アクションで`FeatureFlags::CreateService`を呼び出し

#### Step 3: フロントエンド（Vue.js）を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | new_feature_flag.vue | `app/assets/javascripts/feature_flags/components/new_feature_flag.vue` | 新規作成画面メインコンポーネント |
| 3-2 | form.vue | `app/assets/javascripts/feature_flags/components/form.vue` | フォームコンポーネント |
| 3-3 | strategy.vue | `app/assets/javascripts/feature_flags/components/strategy.vue` | 戦略設定コンポーネント |

**主要処理フロー**:
- **17-19行目** (new_feature_flag.vue): デフォルト戦略`ROLLOUT_STRATEGY_ALL_USERS`を設定
- **38行目** (new_feature_flag.vue): `createFeatureFlag`をVuexアクションとして呼び出し
- **123-133行目** (form.vue): `handleSubmit`でフォームデータを収集してemit

#### Step 4: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | create_service.rb | `app/services/feature_flags/create_service.rb` | 作成処理のビジネスロジック |

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

```
[ブラウザ]
    │
    ├─ GET /feature_flags/new (HTML)
    │      └─ FeatureFlagsController#new
    │             └─ HTML response (Vue mount point)
    │
    └─ POST /feature_flags.json (create)
           └─ FeatureFlagsController#create
                  └─ FeatureFlags::CreateService#execute
                         └─ Operations::FeatureFlag.create!
                                └─ validates + callbacks
                                       └─ INSERT operations_feature_flags
                                       └─ INSERT operations_feature_flags_strategies
                                       └─ INSERT operations_scopes
```

### データフロー図

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

ユーザー入力           ───▶  form.vue (handleSubmit)     ───▶  Vuex Action
(name, description,                │
 strategies)                       ▼
                           new_feature_flag.vue
                           (createFeatureFlag)
                                   │
                                   ▼
                           API POST /feature_flags.json
                                   │
                                   ▼
                           FeatureFlagsController#create
                                   │
                                   ▼
                           CreateService#execute
                                   │
                                   ▼
                           Operations::FeatureFlag.create
                                   │
                                   ▼
                           PostgreSQL (INSERT)
                                   │
                                   ▼
                           JSON Response / Redirect
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| feature_flag.rb | `app/models/operations/feature_flag.rb` | モデル | FeatureFlagモデル定義 |
| feature_flags_controller.rb | `app/controllers/projects/feature_flags_controller.rb` | コントローラー | HTTPリクエスト処理 |
| new.html.haml | `app/views/projects/feature_flags/new.html.haml` | ビュー | HTMLテンプレート |
| new_feature_flag.vue | `app/assets/javascripts/feature_flags/components/new_feature_flag.vue` | Vueコンポーネント | 新規作成画面 |
| form.vue | `app/assets/javascripts/feature_flags/components/form.vue` | Vueコンポーネント | フォーム |
| strategy.vue | `app/assets/javascripts/feature_flags/components/strategy.vue` | Vueコンポーネント | 戦略設定 |
| create_service.rb | `app/services/feature_flags/create_service.rb` | サービス | 作成ビジネスロジック |
