# 通知設計書 6-SecretBufferシュレッド警告

## 概要

本ドキュメントは、Juliaランタイムにおける`SecretBuffer`シュレッド警告通知の設計を記述する。`SecretBuffer`オブジェクトが手動で`shred!`されずにガベージコレクション（GC）によって自動シュレッドされた場合に警告ログを出力する。

### 本通知の処理概要

**業務上の目的・背景**：`SecretBuffer`はパスワードやAPIキーなどの機密データを安全に保持するためのIOバッファである。機密データは使用後速やかにメモリからゼロクリアされるべきであり、GCによる自動回収を待つと機密データがメモリ上に長時間残存するリスクがある。本通知は開発者に対して手動の`shred!`呼び出しを推奨し、機密データのメモリ露出時間を最小化することを促す。

**通知の送信タイミング**：GCのファイナライザ（`final_shred!`関数）が実行された際に、`SecretBuffer`がまだシュレッドされていない（`!isshredded(s)`）場合に通知される。`@async`で非同期タスクとして出力される。

**通知の受信者**：Juliaプログラムを実行している開発者。ログメッセージとして標準エラー出力（または設定されたログハンドラ）に出力される。

**通知内容の概要**：「a SecretBuffer was `shred!`ed by the GC; use `shred!` manually after use to minimize exposure.」というメッセージが`@warn`マクロにより出力される。

**期待されるアクション**：開発者は`SecretBuffer`の使用箇所を特定し、使用後に明示的に`Base.shred!(s)`を呼び出すようコードを修正する。`shred!(f, x)`パターンの使用が推奨される。

## 通知種別

ログ出力（Warnレベル） - Juliaの`@warn`マクロによるロギングシステム経由の警告通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（`@async`タスク内で出力、GCファイナライザから呼ばれるため） |
| 優先度 | 高（セキュリティに関わる機密データの取り扱い） |
| リトライ | 無し |

### 送信先決定ロジック

Juliaのロギングフレームワーク（`CoreLogging`）に委譲される。デフォルトでは`stderr`に出力される。

## 通知テンプレート

### メール通知の場合

該当なし（ログ出力のみ）

### 本文テンプレート

```
┌ Warning: a SecretBuffer was `shred!`ed by the GC; use `shred!` manually after use to minimize exposure.
└ @ Base secretbuffer.jl:191
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | 固定メッセージのため変数なし | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| GCファイナライザ | `final_shred!`の実行 | `!isshredded(s)` - バッファがまだシュレッドされていない | GCがSecretBufferを回収しようとした際に未シュレッドであれば警告 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| `isshredded(s)` | 既に手動で`shred!`が呼ばれていた場合は通知されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[GCがSecretBufferを回収] --> B["final_shred!呼び出し"]
    B --> C{isshredded?}
    C -->|Yes| D["shred!(s) - 再シュレッド"]
    C -->|No| E["@async @warn 警告出力"]
    E --> F["shred!(s) - 強制シュレッド"]
    D --> G[終了]
    F --> G
```

## データベース参照・更新仕様

### 参照テーブル一覧

該当なし（データベースは使用しない）

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| なし | 本通知自体はエラー処理を持たない。`@async`で非同期実行されるためファイナライザをブロックしない | - |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし（未シュレッドのSecretBufferがGC回収されるたびに出力） |

### 配信時間帯

制限なし（GC実行時に出力）

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

- 本通知自体はセキュリティを強化するためのものである
- 通知メッセージには機密データの内容は含まれない
- `SecretBuffer`の`show`メソッドは常に`SecretBuffer("*******")`と表示し、内容を隠蔽する（103行目）
- `==(s1, s2)`は定数時間比較を使用し、タイミング攻撃を防止する（106-115行目）

## 備考

- `SecretBuffer`の作成時に`finalizer(final_shred!, s)`でファイナライザが登録される（38行目）
- `@async`で非同期出力する理由は、GCファイナライザ内でI/O操作を直接行うことが安全でないため
- `isshredded`は全データバイトがゼロであるかをチェックする（217行目）
- `shred!`後も`SecretBuffer`オブジェクト自体は使用可能（ただし空の状態）

---

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

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

### 推奨読解順序

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

`SecretBuffer`の内部構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | secretbuffer.jl | `base/secretbuffer.jl` | `SecretBuffer`構造体（31-41行目） - `data::Memory{UInt8}`, `size::Int`, `ptr::Int`フィールド |

**読解のコツ**: `SecretBuffer`は`mutable struct`であり、`IO`を継承する。コンストラクタ内で`finalizer(final_shred!, s)`が登録される（38行目）。

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

通知が発生する`final_shred!`関数を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | secretbuffer.jl | `base/secretbuffer.jl` | `final_shred!`関数（190-193行目） |

**主要処理フロー**:
1. **191行目**: `!isshredded(s)`で未シュレッド状態をチェック
2. **191行目**: 未シュレッドなら`@async @warn`で警告を非同期出力
3. **192行目**: `shred!(s)`で強制シュレッド（条件に関わらず必ず実行）

#### Step 3: shred!とisshredded関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | secretbuffer.jl | `base/secretbuffer.jl` | `shred!`関数（210-215行目） - `securezero!`でデータをゼロクリア |
| 3-2 | secretbuffer.jl | `base/secretbuffer.jl` | `isshredded`関数（217行目） - 全バイトがゼロかチェック |
| 3-3 | secretbuffer.jl | `base/secretbuffer.jl` | `shred!(f, x)`パターン（226-232行目） - 推奨される使用パターン |

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

```
GC (ガベージコレクション)
    |
    +-- finalizer callback
        |
        +-- final_shred!(s::SecretBuffer)  [base/secretbuffer.jl:190]
            |
            +-- isshredded(s)  [base/secretbuffer.jl:217]
            |   +-- all(iszero, s.data)
            |
            +-- (未シュレッド時) @async @warn "..."  [base/secretbuffer.jl:191]
            |
            +-- shred!(s)  [base/secretbuffer.jl:210]
                +-- securezero!(s.data)
                +-- s.ptr = 1, s.size = 0
```

### データフロー図

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

SecretBufferオブジェクト ──> final_shred!             ──> シュレッド済みSecretBuffer
(GCによる回収)              |
                            +-- isshredded チェック
                            +-- (false) @async @warn ──> stderr
                            +-- shred! 実行
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| secretbuffer.jl | `base/secretbuffer.jl` | ソース | SecretBufferの全実装（構造体、I/O操作、シュレッド機能） |
