# 機能設計書 59-シークレット

## 概要

本ドキュメントは、VS Codeのシークレット管理機能に関する設計書である。拡張機能やシステムが機密情報（APIキー、トークン、パスワード等）を安全に保存・取得するための機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：
拡張機能が外部サービスと連携する際、認証情報などの機密データを安全に保存する必要がある。OSのセキュアストレージ（Keychain、Credential Manager等）と連携し、暗号化されたシークレット管理を提供する。

**機能の利用シーン**：
- 拡張機能でのAPIトークン保存
- GitHubなど外部サービスの認証情報管理
- OAuth認証のアクセストークン・リフレッシュトークン保存
- ユーザー認証情報の安全な保管

**主要な処理内容**：
1. シークレットの取得（get）
2. シークレットの保存（set）
3. シークレットの削除（delete）
4. シークレットキー一覧取得（keys）
5. 暗号化/復号化処理
6. シークレット変更イベント通知

**関連システム・外部連携**：
- 暗号化サービス（IEncryptionService）: 暗号化/復号化処理
- ストレージサービス（IStorageService）: データ永続化
- OSのセキュアストレージ（Keychain, Windows Credential Manager等）

**権限による制御**：
拡張機能ごとにスコープが分離されている

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | UIなし（APIのみ） |

## 機能種別

セキュリティ / 暗号化 / ストレージ

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| key | string | Yes | シークレットのキー | - |
| value | string | Yes(set) | 保存する値 | - |

### 入力データソース

- 拡張機能API呼び出し
- システム内部からの呼び出し

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| value | string \| undefined | 取得したシークレット値 |
| keys | string[] | シークレットキー一覧 |

### 出力先

- 呼び出し元（Promise経由）
- シークレット変更イベント（onDidChangeSecret）

## 処理フロー

### 処理シーケンス

```
1. get(key)呼び出し
   └─ キューに追加（SequencerByKey）
2. ストレージサービス取得
   └─ 初期化済みストレージを使用
3. キー変換
   └─ secret://プレフィックス付加
4. 暗号化データ取得
   └─ StorageScope.APPLICATIONから取得
5. 復号化
   └─ インメモリ時はスキップ
6. 結果返却
```

### フローチャート

```mermaid
flowchart TD
    A[get/set/delete] --> B[キュー追加]
    B --> C[ストレージ初期化確認]
    C --> D{暗号化利用可能?}
    D -->|Yes| E[永続化ストレージ使用]
    D -->|No| F[インメモリストレージ使用]
    E --> G[暗号化/復号化処理]
    F --> H[平文で処理]
    G --> I[ストレージ操作]
    H --> I
    I --> J[結果返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-59-01 | キープレフィックス | 'secret://'をキーに付加 | 常時 |
| BR-59-02 | 暗号化フォールバック | 暗号化不可時はインメモリ | 暗号化不可時 |
| BR-59-03 | インメモリ時平文 | インメモリ時は暗号化スキップ | type='in-memory' |
| BR-59-04 | 復号化エラー時削除 | 復号化失敗時はシークレット削除 | エラー時 |
| BR-59-05 | キュー処理 | 同一キーへの操作は順次実行 | 常時 |
| BR-59-06 | スコープ | StorageScope.APPLICATION固定 | 常時 |

### 計算ロジック

```typescript
// シークレットストレージプロバイダーの型
interface ISecretStorageProvider {
  type: 'in-memory' | 'persisted' | 'unknown';
  get(key: string): Promise<string | undefined>;
  set(key: string, value: string): Promise<void>;
  delete(key: string): Promise<void>;
  keys?(): Promise<string[]>;
}

// キー変換ロジック
private getKey(key: string): string {
  return `${this._storagePrefix}${key}`;  // 'secret://' + key
}

// 初期化ロジック
async initialize(): Promise<IStorageService> {
  if (!useInMemoryStorage && await encryptionService.isEncryptionAvailable()) {
    type = 'persisted';
    return storageService;
  } else {
    type = 'in-memory';
    return new InMemoryStorageService();
  }
}
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| set | storage | INSERT/UPDATE | 暗号化シークレット保存 |
| get | storage | SELECT | 暗号化シークレット取得 |
| delete | storage | DELETE | シークレット削除 |
| keys | storage | SELECT | キー一覧取得 |

### ストレージ設定

| 項目 | 値 |
|------|-----|
| StorageScope | APPLICATION |
| StorageTarget | MACHINE |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 復号化エラー | 暗号化データ破損 | シークレット削除、undefined返却 |
| - | 暗号化エラー | 暗号化処理失敗 | エラーログ出力、例外スロー |
| - | 暗号化不可 | OSセキュアストレージ不可 | インメモリにフォールバック |

### リトライ仕様

該当なし（エラー時はフォールバックまたは即時失敗）

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

該当なし（SequencerByKeyによる順次処理）

## パフォーマンス要件

- 暗号化/復号化は非同期で実行
- 同一キーへの操作はキューで順次処理
- Lazyによる遅延初期化

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

- OSのセキュアストレージを優先使用
- 暗号化不可時はインメモリ（セッション終了で消失）
- シークレットはログに出力しない（キーのみトレースログ）
- 拡張機能ごとにスコープ分離

## 備考

- 暗号化サービスの可用性はプラットフォームに依存
- macOSではKeychain、WindowsではCredential Managerを使用
- LinuxではGNOME Keyring/KWalletを使用（インストール状況による）

---

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

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

### 推奨読解順序

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

シークレット関連の型定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | secrets.ts | `src/vs/platform/secrets/common/secrets.ts` | ISecretStorageProvider、ISecretStorageService |

**読解のコツ**:
- typeは'in-memory'、'persisted'、'unknown'の3種類
- get/set/deleteがコアメソッド

**主要処理フロー**:
1. **15行目**: ISecretStorageService decorator登録
2. **17-23行目**: ISecretStorageProvider - ストレージプロバイダーインターフェース
3. **25-28行目**: ISecretStorageService - サービスインターフェース
4. **30-51行目**: BaseSecretStorageService - 基底クラスとコンストラクタ
5. **33行目**: _storagePrefix = 'secret://' - キープレフィックス
6. **38行目**: SequencerByKey - キューによる順次処理
7. **40行目**: _type - ストレージタイプ状態
8. **66-92行目**: get() - シークレット取得処理
9. **94-114行目**: set() - シークレット保存処理
10. **116-125行目**: delete() - シークレット削除処理
11. **127-135行目**: keys() - キー一覧取得
12. **137-158行目**: initialize() - 初期化処理（暗号化可否判定）
13. **175-177行目**: getKey() - キープレフィックス付加

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

```
ISecretStorageService
    │
    ├─ get(key)
    │      │
    │      └─ _sequencer.queue(key, async)
    │             │
    │             ├─ resolvedStorageService
    │             ├─ getKey(key) → 'secret://' + key
    │             ├─ storageService.get(fullKey, StorageScope.APPLICATION)
    │             └─ _encryptionService.decrypt(encrypted)
    │
    ├─ set(key, value)
    │      │
    │      └─ _sequencer.queue(key, async)
    │             │
    │             ├─ _encryptionService.encrypt(value)
    │             └─ storageService.store(fullKey, encrypted,
    │                    StorageScope.APPLICATION, StorageTarget.MACHINE)
    │
    ├─ delete(key)
    │      │
    │      └─ storageService.remove(fullKey, StorageScope.APPLICATION)
    │
    ├─ keys()
    │      │
    │      └─ storageService.keys().filter(k => k.startsWith('secret://'))
    │
    └─ onDidChangeSecret: Event<string>
           │
           └─ 外部からシークレット変更を監視
```

### データフロー図

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

set(key, value)
    │
    ↓
┌───────────────┐
│キュー追加     │
│(SequencerByKey)│
└───────────────┘
    │
    ↓
┌───────────────┐
│初期化確認     │
│(Lazy)         │
└───────────────┘
    │
    ↓
┌───────────────┐    ┌───────────────┐
│暗号化可能?    │───→│InMemoryStorage│
│               │ No │(フォールバック)│
└───────────────┘    └───────────────┘
    │ Yes
    ↓
┌───────────────┐
│暗号化処理     │
│(IEncryption)  │
└───────────────┘
    │
    ↓
┌───────────────┐
│ストレージ保存 │
│scope:APP      │
│target:MACHINE │
└───────────────┘
    │
    ↓
[onDidChangeSecret]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| secrets.ts | `src/vs/platform/secrets/common/secrets.ts` | ソース | 共通型定義・基底クラス |
| encryptionService.ts | `src/vs/platform/encryption/common/encryptionService.ts` | ソース | 暗号化サービスインターフェース |
| storage.ts | `src/vs/platform/storage/common/storage.ts` | ソース | ストレージサービス |
