# 機能設計書 87-動的プロファイル生成(SSH)

## 概要

本ドキュメントは、Windows Terminal が SSH 設定ファイルからホスト情報を検出し、各ホストに対応するプロファイルを動的に生成する機能を記述する。

### 本機能の処理概要

**業務上の目的・背景**：SSH 接続は開発者の日常業務で頻繁に使用される。`~/.ssh/config` に定義されたホストに対して自動的にプロファイルを生成することで、ユーザーが手動で SSH コマンドを入力する手間を省き、ワンクリックで接続できるようにする。

**機能の利用シーン**：ユーザーが SSH 設定ファイルにリモートホストを追加した後、Windows Terminal の次回起動時にプロファイルが自動的に追加される。

**主要な処理内容**：
1. OpenSSH の実行ファイル（ssh.exe）の検出（System32 / Program Files の3か所）
2. システム SSH 設定ファイル（`%ProgramData%\ssh\ssh_config`）の読み込み
3. ユーザー SSH 設定ファイル（`%UserProfile%\.ssh\config`）の読み込み
4. 設定ファイルから Host / HostName ペアを抽出
5. 各ホストに対してプロファイルを生成

**関連システム・外部連携**：OpenSSH（ssh.exe）、SSH 設定ファイル。

**権限による制御**：特別な権限は不要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | バックグラウンド処理。直接の関連画面はない |

## 機能種別

データ連携 / 自動検出

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| profiles | std::vector<winrt::com_ptr<Profile>>& | Yes | 生成プロファイル格納先 | - |

### 入力データソース

- SSH 設定ファイル：`%ProgramData%\ssh\ssh_config`（システム）、`%UserProfile%\.ssh\config`（ユーザー）
- ssh.exe：`%SystemRoot%\System32\OpenSSH\ssh.exe`、`%ProgramFiles%\OpenSSH\ssh.exe`、`%ProgramFiles(x86)%\OpenSSH\ssh.exe`

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| Profile | winrt::com_ptr<Profile> | 各 SSH ホスト用のプロファイルオブジェクト |

### 出力先

profiles ベクタに追加。

## 処理フロー

### 処理シーケンス

```
1. SshHostGenerator::GenerateProfiles() が呼び出される
2. _tryFindSshExePath() で ssh.exe を検出
   └─ System32/OpenSSH、ProgramFiles/OpenSSH、ProgramFiles(x86)/OpenSSH の順に検索
3. ssh.exe が見つかった場合、設定ファイルからホスト名を抽出
   └─ _getHostNamesFromConfigFile(システム設定)
   └─ _getHostNamesFromConfigFile(ユーザー設定)
4. 各ホスト名に対してプロファイルを生成
   └─ プロファイル名: "SSH - {hostName}"
   └─ コマンドライン: "{sshExePath}" {hostName}
   └─ アイコン: \uE977 (PC1)
```

### フローチャート

```mermaid
flowchart TD
    A[GenerateProfiles 開始] --> B[_tryFindSshExePath]
    B --> C{ssh.exe 発見?}
    C -->|No| D[終了 - プロファイルなし]
    C -->|Yes| E[システム設定ファイル読み込み]
    E --> F[ユーザー設定ファイル読み込み]
    F --> G{各ホスト名}
    G --> H[プロファイル生成]
    H --> G
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-87-01 | Host+HostName ペア | Host エントリの後に HostName が続く場合のみプロファイルを生成 | 設定ファイル解析時 |
| BR-87-02 | コメント除外 | # で始まる行はコメントとして無視 | 設定ファイル解析時 |
| BR-87-03 | ssh.exe 検出順 | System32 → ProgramFiles → ProgramFiles(x86) の優先度で検索 | ssh.exe 検出時 |
| BR-87-04 | 正規表現パース | `^\s*(\w+)\s+([^\s]+.*[^\s])\s*$` でキー・値を抽出 | 設定行パース時 |

### 計算ロジック

該当なし。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ssh.exe 不在 | OpenSSH がインストールされていない | プロファイル生成をスキップ |
| - | 設定ファイル不在 | SSH 設定ファイルが存在しない | スキップ |
| - | パースエラー | 設定ファイルの形式が不正 | CATCH_LOG で記録しスキップ |

### リトライ仕様

リトライなし。

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

該当なし。

## パフォーマンス要件

ファイル存在確認とテキストファイル読み込みのみのため高速に完了する。

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

ssh.exe のパスは環境変数で展開される既知のパスのみを検索する。

## 備考

- 名前空間：`Windows.Terminal.SSH`
- プロファイルアイコン：\uE977（PC1セグエフォントグリフ）
- ジェネレータアイコン：\uE969（StorageNetworkWireless）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SshHostGenerator.h | `src/cascadia/TerminalSettingsModel/SshHostGenerator.h` | クラス定義とプライベートメソッド（23-37行目）。_configKeyValueRegex メンバに注目 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SshHostGenerator.cpp | `src/cascadia/TerminalSettingsModel/SshHostGenerator.cpp` | GenerateProfiles メソッド（147-167行目） |

**主要処理フロー**:
1. **149-150行目**: _tryFindSshExePath で ssh.exe を検索
2. **154-155行目**: システムとユーザーの設定ファイルからホスト名を抽出
3. **157-165行目**: 各ホストに対してプロファイルを生成

#### Step 3: 設定ファイル解析を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SshHostGenerator.cpp | `src/cascadia/TerminalSettingsModel/SshHostGenerator.cpp` | _getHostNamesFromConfigFile（86-124行目）と _tryParseConfigKeyValue（65-84行目） |

**主要処理フロー**:
- **35行目**: 正規表現 `^\s*(\w+)\s+([^\s]+.*[^\s])\s*$` の定義
- **86-124行目**: 設定ファイルを行単位で読み込み、Host/HostName ペアを抽出
- **105-108行目**: Host キーの値を lastHost に保存
- **110-117行目**: HostName キーが見つかったら lastHost をホスト名リストに追加

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

```
SshHostGenerator::GenerateProfiles (147行目)
    │
    ├─ _tryFindSshExePath (47行目)
    │
    ├─ _getHostNamesFromConfigFile(システム設定) (86行目)
    │      └─ _tryParseConfigKeyValue (65行目)
    │
    ├─ _getHostNamesFromConfigFile(ユーザー設定) (86行目)
    │      └─ _tryParseConfigKeyValue (65行目)
    │
    └─ CreateDynamicProfile (各ホスト) (DynamicProfileUtils.h)
```

### データフロー図

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

ssh.exe 検出 ──────▶ _tryFindSshExePath
                          │
SSH設定ファイル ───▶ _getHostNamesFromConfigFile ──▶ hostNames[]
(system/user)        └─ _tryParseConfigKeyValue         │
                                                        ▼
                                               GenerateProfiles
                                                        │
                                                        ▼
                                               Profile オブジェクト群
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SshHostGenerator.h | `src/cascadia/TerminalSettingsModel/SshHostGenerator.h` | ヘッダ | クラス定義 |
| SshHostGenerator.cpp | `src/cascadia/TerminalSettingsModel/SshHostGenerator.cpp` | ソース | SSH ホスト検出とプロファイル生成 |
| IDynamicProfileGenerator.h | `src/cascadia/TerminalSettingsModel/IDynamicProfileGenerator.h` | ヘッダ | ジェネレータインターフェース |
| DynamicProfileUtils.h | `src/cascadia/TerminalSettingsModel/DynamicProfileUtils.h` | ヘッダ | ユーティリティ |
