# 画面設計書 15-セキュア入力オーバーレイ

## 概要

本ドキュメントは、Ghosttyアプリケーションのセキュア入力オーバーレイの設計仕様を定義する。セキュア入力オーバーレイは、macOSのセキュア入力モード（Secure Keyboard Entry）がアクティブであることを視覚的に示すインジケーターであり、パスワード入力時などに自動的に表示されるmacOS専用のオーバーレイ画面である。

### 本画面の処理概要

セキュア入力オーバーレイは、セキュリティ機能が有効であることをユーザーに明示し、安心感を提供する画面である。

**業務上の目的・背景**：macOSのセキュア入力モードは、キーボード入力が他のアプリケーション（キーロガーなど）に傍受されないようにする重要なセキュリティ機能である。Ghosttyはパスワードプロンプトを検出すると自動的にこのモードを有効化する。しかし、ユーザーはこの保護が有効になっていることを視覚的に確認できないため、セキュア入力オーバーレイでシールドアイコンを表示することで、セキュリティ状態を明確に伝える。また、メニューから「Secure Keyboard Entry」を手動で有効化した場合も同様に表示される。

**画面へのアクセス方法**：
1. ターミナルでパスワードプロンプト（sudo, ssh, passwdなど）が検出された時に自動表示
2. メニューから「Ghostty > Secure Keyboard Entry」を有効化した時に表示
3. SecureInput.shared.enabledがtrueになった時にSwiftUIの条件付き表示

**主要な操作・処理内容**：
1. シールドアイコン（lock.shield.fill）のアニメーション表示
2. アイコンをクリックするとポップオーバーで説明文を表示
3. ポップオーバーにはセキュア入力の説明と有効化の理由を記載
4. 回転するグラデーションアニメーションでアクティブ状態を強調
5. 不透明度が変化するパルスアニメーション

**画面遷移**：
- 遷移元：メインターミナルウィンドウ（セキュア入力有効化時に自動表示）
- 遷移先：なし（オーバーレイとして表示、セキュア入力解除時に自動非表示）

**権限による表示制御**：SecureInput.shared.enabledの状態に基づいて表示/非表示が切り替わる。ユーザー権限による制御は存在しない。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 77 | セキュア入力 | 主機能 | セキュア入力モードアクティブの視覚的インジケーター表示 |

## 画面種別

オーバーレイ（ステータスインジケーター）

## URL/ルーティング

macOSネイティブアプリケーションのため、URLルーティングは存在しない。SecureInput.shared.enabledの@Publishedプロパティの変更を監視してSwiftUIビューが自動的に表示/非表示を切り替える。

## 入出力項目

| 項目名 | 入出力 | データ型 | 必須 | 説明 |
|--------|--------|----------|------|------|
| なし | - | - | - | 入力項目なし（ステータス表示のみ） |

## 表示項目

| 項目名 | データ型 | ソース | 説明 |
|--------|----------|--------|------|
| シールドアイコン | SF Symbol | 固定値 | 「lock.shield.fill」（25x25px） |
| グラデーションアニメーション | AngularGradient | 計算値 | cyan, blue, yellow, blue, cyanの回転グラデーション |
| ポップオーバー説明文 | String | 固定値 | セキュア入力の説明テキスト |

## イベント仕様

### 1-アイコンタップ（onTapGesture）

アイコンをタップすると、isPopover状態がtrueになり、ポップオーバーが表示される。

### 2-ポップオーバー表示

.popover(isPresented: $isPopover)により、ポップオーバーが下矢印付きで表示される。内容はセキュア入力の説明文。

### 3-グラデーションアニメーション開始（onAppear）

画面表示時にonAppear内でwithAnimationを使用して以下のアニメーションを開始:
- gradientAngleを0度から360度まで2秒間で回転（repeatForever、autoreverses: false）
- gradientOpacityを0.5から1.0まで2秒間でパルス（repeatForever、autoreverses: true）

### 4-セキュア入力状態変更

SecureInput.shared.enabledの値が変更されると、親ビューの条件付きレンダリングによりオーバーレイの表示/非表示が切り替わる。

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| なし | - | - | データベース操作なし（システム状態表示のみ） |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|---------------|----------|
| MSG-01 | 説明 | Secure Input is active. Secure Input is a macOS security feature that prevents applications from reading keyboard events. This is enabled automatically whenever Ghostty detects a password prompt in the terminal, or at all times if `Ghostty > Secure Keyboard Entry` is active. | ポップオーバー表示時 |

## 例外処理

| 例外状態 | 画面の振る舞い |
|---------|---------------|
| EnableSecureEventInput失敗 | ログ出力、オーバーレイは表示されない |
| DisableSecureEventInput失敗 | ログ出力、オーバーレイは表示されたまま |

## 備考

- macOS専用画面（GTK版には対応機能なし）
- Carbon APIのEnableSecureEventInput/DisableSecureEventInputを使用
- SecureInputはシングルトンパターン（SecureInput.shared）
- アプリケーション非アクティブ時は自動的にセキュア入力を無効化
- アプリケーション再アクティブ時に自動的に再有効化
- スコープ付きセキュア入力（特定のオブジェクトがフォーカス中のみ有効）をサポート
- グローバルセキュア入力（常時有効）もサポート
- ポインタースタイルは.link（カーソルがリンク形状に変化）
- 配置は画面右上（padding: top 10, trailing 10）

---

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

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

### 推奨読解順序

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

SecureInputクラスがセキュア入力の状態管理を担当する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | SecureInput.swift | `macos/Sources/Features/Secure Input/SecureInput.swift` | シングルトン、@Publishedプロパティ、スコープ管理 |

**読解のコツ**: ObservableObjectと@Publishedの連携を理解すること。enabled状態の変更がSwiftUIビューに自動的に伝播される仕組みを把握する。

#### Step 2: 状態管理ロジックを理解する

SecureInputがどのようにCarbon APIと連携するかを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | SecureInput.swift | `macos/Sources/Features/Secure Input/SecureInput.swift` | apply(), setScoped(), removeScoped() |

**主要処理フロー**:
1. **16行目**: static let shared - シングルトンインスタンス
2. **24-28行目**: global - グローバル有効化フラグ
3. **31行目**: scoped - スコープ付きオブジェクトとフォーカス状態のマップ
4. **34行目**: @Published enabled - 現在のセキュア入力状態
5. **39-41行目**: desired - 有効化すべきかどうかの計算プロパティ
6. **84-105行目**: apply() - EnableSecureEventInput/DisableSecureEventInputの呼び出し
7. **109-121行目**: onDidBecomeActive - アプリアクティブ時の再有効化
8. **123-134行目**: onDidResignActive - アプリ非アクティブ時の無効化

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

SecureInputOverlayがSwiftUIビューとしてオーバーレイを表示する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | SecureInputOverlay.swift | `macos/Sources/Features/Secure Input/SecureInputOverlay.swift` | アニメーション、ポップオーバー、レイアウト |

**主要処理フロー**:
- **4-6行目**: @Stateプロパティ - gradientAngle, gradientOpacity, isPopover
- **11-68行目**: body - VStack/HStackによるレイアウト
- **16-19行目**: シールドアイコン - SF Symbol「lock.shield.fill」
- **22-47行目**: 背景 - AngularGradientとRadialGradientの組み合わせ
- **53-55行目**: onTapGesture - ポップオーバー表示トリガー
- **59-67行目**: popover - 説明文表示
- **72-80行目**: onAppear - アニメーション開始

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

```
SecureInput.shared (Singleton)
    │
    ├─ @Published enabled ────────────▶ SwiftUI View Binding
    │                                        │
    │                                        ▼
    │                                   SecureInputOverlay
    │                                        │
    │                                        ├─ シールドアイコン表示
    │                                        ├─ グラデーションアニメーション
    │                                        └─ ポップオーバー説明
    │
    ├─ global (didSet) ───────────────▶ apply()
    │                                        │
    │                                        ▼
    │                                   EnableSecureEventInput()
    │                                   DisableSecureEventInput()
    │
    ├─ setScoped(object, focused) ────▶ scoped[object] = focused
    │                                        │
    │                                        ▼
    │                                   apply()
    │
    └─ Notifications
           ├─ didBecomeActive ────────▶ EnableSecureEventInput()
           └─ didResignActive ────────▶ DisableSecureEventInput()
```

### データフロー図

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

パスワードプロンプト検出       SecureInput                         SecureInputOverlay
(ターミナル)        ───▶      - setScoped(id, true)   ───▶        - シールドアイコン
                              - apply()                            - アニメーション
                              - EnableSecureEventInput()

メニュー選択                   SecureInput                         SecureInputOverlay
(Secure Keyboard   ───▶      - global = true         ───▶        - シールドアイコン
 Entry)                       - apply()                            - アニメーション

フォーカス喪失                 SecureInput                         SecureInputOverlay
(別ウィンドウ)     ───▶      - setScoped(id, false)  ───▶        - 非表示
                              - apply()

アプリ非アクティブ             SecureInput                         SecureInputOverlay
                   ───▶      - DisableSecureEventInput() ───▶    - 非表示
                              - enabled = false
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| SecureInputOverlay.swift | `macos/Sources/Features/Secure Input/SecureInputOverlay.swift` | ソース | オーバーレイビュー（SwiftUI） |
| SecureInput.swift | `macos/Sources/Features/Secure Input/SecureInput.swift` | ソース | セキュア入力状態管理（シングルトン） |
| TerminalView.swift | `macos/Sources/Features/Terminal/TerminalView.swift` | ソース | オーバーレイを含むメインターミナルビュー |
| Backport.swift | `macos/Sources/Helpers/Backport.swift` | ソース | .pointerStyle(.link)のバックポート実装 |
