# 画面設計書 199-新規アクセストークン

## 概要

本ドキュメントは、詳細設定版の新規アクセストークン作成画面の設計書である。個人アクセストークンをより細かい粒度で設定して発行する画面の仕様を定義する。

### 本画面の処理概要

従来のアクセストークン発行画面よりも詳細な設定オプションを提供する画面である。Feature Flag `granular_personal_access_tokens` が有効な場合にアクセス可能となる。

**業務上の目的・背景**：セキュリティのベストプラクティスとして、最小権限の原則（Principle of Least Privilege）に従い、必要最小限の権限のみをトークンに付与することが推奨される。本画面は、より細かい粒度でスコープを設定し、セキュリティリスクを最小化したトークンを発行するために提供される。

**画面へのアクセス方法**：
1. アクセストークン一覧画面から「詳細設定でトークンを作成」リンクをクリック
2. または URL `/-/user_settings/personal_access_tokens/granular/new` に直接アクセス

**主要な操作・処理内容**：
1. トークン名の入力
2. 説明の入力
3. 有効期限の設定
4. 詳細なスコープの選択
5. トークンの発行

**画面遷移**：
- 遷移元: アクセストークン一覧画面
- 遷移先: アクセストークン一覧画面（トークン発行後）

**権限による表示制御**：
- ログイン必須
- Feature Flag `granular_personal_access_tokens` が有効な場合のみアクセス可能

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 81 | 個人アクセストークン | 主機能 | 新規アクセストークンの作成(詳細設定) |

## 画面種別

登録

## URL/ルーティング

```
GET /-/user_settings/personal_access_tokens/granular/new
```

## 入出力項目

| 項目名 | 項目ID | 入出力 | 型 | 必須 | 説明 |
|--------|--------|--------|-----|------|------|
| トークン名 | personal_access_token[name] | 入力 | string | Yes | トークンの識別名 |
| 説明 | personal_access_token[description] | 入力 | string | No | トークンの用途説明 |
| 有効期限 | personal_access_token[expires_at] | 入力 | date | Yes* | YYYY-MM-DD形式 |
| スコープ | personal_access_token[scopes][] | 入力 | array | Yes | 詳細な権限スコープ |

*`require_personal_access_token_expiry?` 設定による

## 表示項目

本画面は Vue.js コンポーネント（`#js-create-granular-token-app`）によりレンダリングされるため、表示項目はフロントエンドで定義される。

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| 利用可能スコープ一覧 | Gitlab::Auth.all_available_scopes | 設定可能なスコープ |
| スコープ説明 | 各スコープのドキュメント | スコープの権限説明 |
| 最大有効期限 | max_expiration_lifetime_in_days | インスタンス設定の最大期限 |

## イベント仕様

### 1-トークン発行

**トリガー**: 「Create personal access token」ボタン押下

**処理フロー**:
1. フォームデータのバリデーション（Vue.js側）
2. POST リクエストで `/personal_access_tokens` へ送信
3. `PersonalAccessTokens::CreateService` を呼び出し
4. 成功時: トークン値を表示、一覧画面へリダイレクト
5. 失敗時: エラーメッセージを表示

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| トークン発行 | personal_access_tokens | INSERT | 新規トークンの発行 |

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

#### personal_access_tokens

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | user_id | current_user.id | トークン所有者 |
| INSERT | organization_id | Current.organization.id | 組織ID |
| INSERT | name | フォーム入力値 | トークン名 |
| INSERT | description | フォーム入力値 | 説明 |
| INSERT | scopes | フォーム入力値 | 詳細スコープ配列 |
| INSERT | expires_at | フォーム入力値 | 有効期限 |
| INSERT | token_digest | SHA256ハッシュ | トークンハッシュ |
| INSERT | created_at | 現在日時 | 作成日時 |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|---------|
| MSG-001 | 成功 | (発行されたトークン値) | トークン発行成功時 |
| MSG-002 | エラー | (バリデーションエラー) | 入力値不正時 |

## 例外処理

| 例外 | 発生条件 | 対応処理 |
|-----|---------|---------|
| 未認証 | ログインしていない | ログイン画面へリダイレクト |
| 404 Not Found | Feature Flag が無効 | 404ページ表示 |
| バリデーションエラー | 必須項目未入力、有効期限超過等 | エラーメッセージを表示 |

## 備考

- Feature Flag `granular_personal_access_tokens` が無効な場合は 404 エラー
- 本画面で発行されるトークンは、従来のトークンと同様に `glpat-` プレフィックスを持つ
- 詳細スコープにより、従来より細かい権限制御が可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | personal_access_token.rb | `app/models/personal_access_token.rb` | トークンモデルの属性を確認 |

**読解のコツ**: granular トークンも同じ `PersonalAccessToken` モデルを使用する。スコープの詳細度が異なるのみ。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | personal_access_tokens_controller.rb | `app/controllers/user_settings/personal_access_tokens_controller.rb` | granular_new アクションを確認 |

**主要処理フロー**:
1. **46-48行目**: `granular_new` アクション - Feature Flag チェック後に画面表示

#### Step 3: ビューレイヤーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | granular_new.html.haml | `app/views/user_settings/personal_access_tokens/granular_new.html.haml` | Vue.js コンポーネントのマウントポイント確認 |

**主要処理フロー**:
- **4行目**: `#js-create-granular-token-app` - Vue.js マウントポイント
- `personal_access_token_data({})` でデータを渡す

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

```
UserSettings::PersonalAccessTokensController#granular_new
    │
    ├─ Feature.enabled?(:granular_personal_access_tokens, current_user)
    │      └─ [無効時] render_404
    │
    └─ render 'granular_new'
           └─ #js-create-granular-token-app
                  └─ personal_access_token_data({})

Vue.js Component (フロントエンド)
    │
    └─ POST /personal_access_tokens
           └─ PersonalAccessTokensController#create
                  └─ PersonalAccessTokens::CreateService#execute
```

### データフロー図

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

フォームデータ ───▶ Vue.js バリデーション ───▶ 検証結果
    │                      │
    │                      └─ POST /personal_access_tokens
    │
    └──────────────────────┼───────────────────▶ PersonalAccessTokens::CreateService
                           │
                           └─ personal_access_tokens テーブル
                                  │
                                  └─ { token: "glpat-xxx" }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| personal_access_tokens_controller.rb | `app/controllers/user_settings/personal_access_tokens_controller.rb` | コントローラー | リクエスト処理 |
| granular_new.html.haml | `app/views/user_settings/personal_access_tokens/granular_new.html.haml` | テンプレート | 画面表示 |
| personal_access_token.rb | `app/models/personal_access_token.rb` | モデル | トークンデータ定義 |
| create_service.rb | `app/services/personal_access_tokens/create_service.rb` | サービス | トークン発行ロジック |
| user_settings.rb | `config/routes/user_settings.rb` | 設定 | ルーティング定義 |
