# 機能設計書 64-フォームバリデーション

## 概要

本ドキュメントは、Jenkins における Web 画面の入力検証機能（FormValidation）の設計について記述する。

### 本機能の処理概要

フォームバリデーション機能は、Jenkins の設定画面における入力値の検証を行い、リアルタイムでフィードバックを提供する基盤機能である。AJAX を使用した非同期検証により、ユーザーが入力した値の妥当性を即座に確認できる。

**業務上の目的・背景**：CI/CD システムの設定は複雑であり、設定ミスはビルド失敗やセキュリティ問題につながる可能性がある。フォームバリデーション機能は、ユーザーが設定を保存する前に入力値の問題を検出し、適切なフィードバック（OK、警告、エラー）を提供することで、設定品質を向上させる。また、検証ロジックを再利用可能な形で提供し、プラグイン開発者が容易に入力検証を実装できるようにする。

**機能の利用シーン**：
- ジョブ設定画面での入力値検証
- システム設定画面での設定値検証
- プラグイン設定画面でのカスタム検証
- ノード設定画面での接続情報検証
- ユーザー登録画面での入力検証

**主要な処理内容**：
1. doCheckXxx() メソッドによる検証ロジックの定義
2. FormValidation オブジェクトによる検証結果の表現
3. AJAX リクエストによる非同期検証
4. 検証結果の HTML レンダリング
5. 複数の検証結果の集約
6. 標準検証ユーティリティの提供（数値、URL、実行ファイル等）

**関連システム・外部連携**：
- Stapler: Web フレームワーク
- Descriptor: 設定可能なオブジェクトのメタデータ
- JavaScript: クライアント側の検証トリガー
- ProxyConfiguration: URL 検証時のプロキシ対応

**権限による制御**：一部の検証（実行ファイルの存在確認など）は Jenkins.ADMINISTER 権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | 新規ジョブ作成 | API連携 | ジョブ名の入力検証 |
| 3 | 新規View作成 | API連携 | View名の入力検証 |
| 7 | ユーザー登録 | API連携 | 入力値の検証 |
| 12 | ジョブ設定 | API連携 | 設定値の入力検証 |
| 23 | ノード設定 | API連携 | 設定値の入力検証 |
| 29 | システム設定 | API連携 | 設定値の入力検証 |
| 76 | View設定 | API連携 | 設定値の入力検証 |
| 78 | プロキシ設定 | API連携 | 設定値の入力検証 |

## 機能種別

バリデーション / UI連携

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | String | Yes | 検証対象の入力値 | - |
| 追加パラメータ | 各種 | No | @QueryParameter で指定された追加パラメータ | - |

### 入力データソース

- Web フォームからの入力値
- JavaScript からの AJAX リクエスト

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| kind | Kind | 検証結果の種別（OK/WARNING/ERROR） |
| message | String | 検証結果メッセージ |
| html | String | HTML フォーマットされた検証結果 |

### 出力先

- HTTP レスポンス（text/html）
- ブラウザ上の検証結果表示領域

## 処理フロー

### 処理シーケンス

```
【クライアント側】
1. フォーム入力値の変更検知
   └─ JavaScript のイベントハンドラ

2. AJAX リクエストの構築
   └─ doCheckXxx URL の生成
   └─ 依存パラメータの収集

3. 検証リクエストの送信
   └─ 非同期 HTTP リクエスト

【サーバー側】
4. Descriptor.doCheckXxx() の呼び出し
   └─ Stapler による URL マッピング
   └─ @QueryParameter によるパラメータ注入

5. 検証ロジックの実行
   └─ 入力値の検証
   └─ FormValidation オブジェクトの生成

6. HTTP レスポンスの生成
   └─ renderHtml() で HTML 生成
   └─ Content-Security-Policy ヘッダー設定

【クライアント側】
7. 検証結果の表示
   └─ HTML の挿入
   └─ スタイルクラスの適用（ok/warning/error）
```

### フローチャート

```mermaid
flowchart TD
    A[フォーム入力変更] --> B[JavaScript イベント]
    B --> C[AJAX リクエスト構築]
    C --> D[doCheckXxx 呼び出し]
    D --> E{検証ロジック実行}
    E -->|成功| F[FormValidation.ok]
    E -->|警告| G[FormValidation.warning]
    E -->|エラー| H[FormValidation.error]
    F --> I[renderHtml]
    G --> I
    H --> I
    I --> J[HTTP レスポンス]
    J --> K[結果表示]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-64-01 | OK 結果 | 検証成功時は緑色のメッセージを表示 | 検証成功時 |
| BR-64-02 | WARNING 結果 | 潜在的な問題がある場合は黄色のメッセージを表示 | 警告条件に該当時 |
| BR-64-03 | ERROR 結果 | 明らかな問題がある場合は赤色のメッセージを表示 | エラー条件に該当時 |
| BR-64-04 | CSP ヘッダー | 検証結果レスポンスには Content-Security-Policy を設定 | 常時 |
| BR-64-05 | メッセージエスケープ | ユーザー入力を含むメッセージは HTML エスケープ必須 | XSS 防止 |

### 計算ロジック

**集約検証の結果判定**:
- 複数の検証結果を集約する場合、最も深刻な結果（ERROR > WARNING > OK）が全体の結果となる
- aggregate() メソッドで実装

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

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

該当なし（フォームバリデーション機能はデータベース操作を行わない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| IOException | 入出力エラー | URL 検証時の接続失敗 | エラーメッセージを FormValidation.error で返却 |
| RuntimeException | 実行時エラー | 検証ロジック内の例外 | スタックトレース付きのエラー表示 |

### リトライ仕様

該当なし（検証は即座に結果を返す）

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

該当なし

## パフォーマンス要件

- 検証は非同期で行われ、UI をブロックしない
- 検証リクエストは軽量であるべき
- 長時間かかる検証は別途プログレス表示を検討

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

- XSS 防止のため、Util.escape() でメッセージをエスケープ
- Content-Security-Policy ヘッダーで sandbox 設定
- 管理者権限が必要な検証（validateExecutable 等）は権限チェックを実施
- スタックトレースの表示は慎重に（情報漏洩のリスク）

## 備考

- FormValidation は IOException を継承し、throw でエラーを返すことも可能
- errorWithMarkup() 等で HTML を含むメッセージを返す場合は XSS に注意
- CheckMethod クラスで検証 URL の構築を支援

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | FormValidation.java | `core/src/main/java/hudson/util/FormValidation.java` | Kind 列挙型（126-140行目）と基本構造 |

**読解のコツ**: FormValidation は IOException を継承している点に注目（120行目）。これにより throw でエラーを返すパターンが可能になっている。

#### Step 2: ファクトリメソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | FormValidation.java | `core/src/main/java/hudson/util/FormValidation.java` | ok()、warning()、error() メソッド群（149-220行目） |

**主要処理フロー**:
1. **149-159行目**: error()、warning()、ok() - メッセージ付きファクトリメソッド
2. **166-168行目**: ok() - シングルトン OK 結果
3. **194-211行目**: スタックトレース付きエラー生成

#### Step 3: 標準検証ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | FormValidation.java | `core/src/main/java/hudson/util/FormValidation.java` | validateXxx() メソッド群（330-461行目） |

**主要処理フロー**:
- **330-373行目**: validateExecutable() - 実行ファイル検証
- **378-386行目**: validateNonNegativeInteger() - 非負整数検証
- **415-423行目**: validatePositiveInteger() - 正整数検証
- **428-432行目**: validateRequired() - 必須チェック
- **445-461行目**: validateBase64() - Base64 検証

#### Step 4: URLCheck を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | FormValidation.java | `core/src/main/java/hudson/util/FormValidation.java` | URLCheck 抽象クラス（469-584行目） |

**主要処理フロー**:
- **478-501行目**: open(URI) - URL からテキスト取得
- **526-530行目**: findText() - 文字列検索
- **554-561行目**: handleIOException() - エラーハンドリング

#### Step 5: CheckMethod を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | FormValidation.java | `core/src/main/java/hudson/util/FormValidation.java` | CheckMethod クラス（623-725行目） |

**主要処理フロー**:
- **636-647行目**: コンストラクタ - doCheckXxx メソッドの検出
- **652-674行目**: findParameters() - パラメータの自動検出
- **683-702行目**: toCheckUrl() - 検証 URL の生成

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

```
FormValidation 操作
    │
    ├─ ファクトリメソッド
    │      ├─ ok() / ok(message) (157-159, 166-168行目)
    │      ├─ warning() / warning(message) (153-155, 178-180行目)
    │      └─ error() / error(message) (149-151, 174-176行目)
    │
    ├─ 標準検証
    │      ├─ validateExecutable() (330-373行目)
    │      ├─ validateNonNegativeInteger() (378-386行目)
    │      ├─ validatePositiveInteger() (415-423行目)
    │      ├─ validateRequired() (428-432行目)
    │      └─ validateBase64() (445-461行目)
    │
    ├─ URLCheck
    │      ├─ open(URI) (478-501行目)
    │      ├─ findText() (526-530行目)
    │      └─ check() - 抽象メソッド (583行目)
    │
    └─ レスポンス生成
           ├─ generateResponse() (603-605行目)
           └─ renderHtml() - 抽象メソッド (607行目)
```

### データフロー図

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

フォーム入力 ─────────▶ AJAX リクエスト
                              │
                              ▼
                       Descriptor.doCheckXxx()
                              │
                              ▼
                       検証ロジック実行
                              │
                              ▼
                       FormValidation 生成 ─────▶ Kind (OK/WARNING/ERROR)
                              │
                              ▼
                       renderHtml() ────────────▶ HTML レスポンス
                              │
                              ▼
                       generateResponse() ─────▶ HTTP レスポンス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| FormValidation.java | `core/src/main/java/hudson/util/FormValidation.java` | ソース | フォーム検証の主要クラス |
| Descriptor.java | `core/src/main/java/hudson/model/Descriptor.java` | ソース | doCheckXxx メソッドの定義場所 |
| ProxyConfiguration.java | `core/src/main/java/hudson/ProxyConfiguration.java` | ソース | URL 検証時のプロキシ設定 |
| DOSToUnixPathHelper.java | `core/src/main/java/hudson/util/DOSToUnixPathHelper.java` | ソース | パス検証ヘルパー |
| Util.java | `core/src/main/java/hudson/Util.java` | ソース | エスケープ処理 |
