# 通知設計書 3-テレメトリ収集通知

## 概要

本ドキュメントは、Next.jsの初回起動時にテレメトリデータ収集の通知をコンソールに出力する通知の設計を記載する。

### 本通知の処理概要

Next.jsが匿名のテレメトリデータを収集していることを初回起動時にユーザーへ通知し、オプトアウト方法を案内する。

**業務上の目的・背景**：Next.jsはユーザーの使用状況に関する匿名テレメトリデータを収集し、機能開発の優先順位付けやロードマップの策定に活用している。GDPR等のプライバシー規制を遵守するため、ユーザーに対して収集の事実を通知し、オプトアウトの手段を提供することが必要である。この通知は透明性とユーザー信頼の確保を目的とする。

**通知の送信タイミング**：`Telemetry`クラスのコンストラクタ内で`notify()`メソッドが呼び出される。初回起動時（テレメトリの通知日時が未記録の場合）にのみ表示される。一度通知済みとなった後は再通知されない。

**通知の受信者**：CLIでNext.jsを起動した開発者。ターミナル/コンソールを通じて情報を受け取る。

**通知内容の概要**：テレメトリ収集が有効であること、収集目的（Next.jsのロードマップとフィーチャーの優先付け）、詳細情報とオプトアウト方法へのURL（https://nextjs.org/telemetry）。

**期待されるアクション**：ユーザーはテレメトリ収集を了承してそのまま使用を続けるか、提示されたURLにアクセスしてオプトアウト方法を確認し、`next telemetry disable`コマンドでオプトアウトする。

## 通知種別

コンソール出力（標準出力）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 中 |
| リトライ | なし |

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

初回起動時に自動的にコンソールへ出力される。受信者の選択ロジックは存在しない。

## 通知テンプレート

### コンソール出力の場合

| 項目 | 内容 |
|-----|------|
| 送信元 | Next.jsサーバープロセス（Telemetryクラス） |
| 出力先 | `console.log`（標準出力） |
| 形式 | ANSIカラー付きテキスト |

### 本文テンプレート

```
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
```

### 添付ファイル

該当なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| クラス初期化 | `Telemetry`コンストラクタ実行 | テレメトリが有効かつ通知未実施 | `storage.ts`行81でnotify()呼び出し |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| テレメトリ無効 | `NEXT_TELEMETRY_DISABLED`環境変数が設定されている、または`telemetry.enabled`がfalse |
| confがnull | 設定ストレージの初期化に失敗した場合 |
| 通知済み | `telemetry.notifiedAt`キーに値が存在する場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Telemetryコンストラクタ] --> B[notify呼び出し]
    B --> C{isDisabled?}
    C -->|Yes| D[何もしない]
    C -->|No| E{confがnull?}
    E -->|Yes| D
    E -->|No| F{notifiedAtキーが存在?}
    F -->|Yes| D
    F -->|No| G[notifiedAtに現在時刻を記録]
    G --> H[Attention メッセージ出力]
    H --> I[使用目的メッセージ出力]
    I --> J[オプトアウト案内出力]
    J --> K[URL出力]
    K --> L[空行出力]
    L --> M[終了]
    D --> M
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| Confストア（ファイルベース） | テレメトリ設定の永続化 | `next/dist/compiled/conf`パッケージを使用 |

### テーブル別参照項目詳細

#### Confストア

| 参照項目（キー名） | 用途 | 取得条件 |
|-------------------|------|---------|
| telemetry.notifiedAt | 通知済み判定 | 値が空文字でないこと |
| telemetry.enabled | テレメトリ有効判定 | falseでないこと |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| Confストア | UPDATE | 通知日時の記録 |

#### 通知日時記録

| 操作 | 項目（キー名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| SET | telemetry.notifiedAt | `Date.now().toString()` | 通知済みフラグとして使用 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| Conf初期化失敗 | パーミッションエラー等 | confがnullとなり通知をスキップ |

### リトライ仕様

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

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | 初回1回のみ（notifiedAtで制御） |

### 配信時間帯

制限なし。

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

- テレメトリ通知自体には機密情報は含まれない
- テレメトリデータ収集は完全に匿名であり、ハッシュ化されたプロジェクトIDが使用される
- `NEXT_TELEMETRY_DISABLED`環境変数でオプトアウト可能
- Confストアのパスは`~/.config/nextjs/`等のユーザーディレクトリに保存される（CI環境では`distDir/cache`）

## 備考

- "Attention"の文字はmagentaカラーかつ太字で強調表示される
- URLはcyanカラーで表示される
- CI環境やDockerコンテナでは`distDir/cache`にストレージが置かれるため、エフェメラルな環境では毎回通知される可能性がある
- テレメトリのオプトアウトは`next telemetry disable`コマンドで実行可能

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | storage.ts | `packages/next/src/telemetry/storage.ts` | Telemetryクラス全体の構造。キー定数（行16-30）でConfストアのキーを理解 |

**読解のコツ**: `Conf`は`configstore`ライクなファイルベースのKey-Valueストアであり、`~/.config/nextjs/config.json`等に永続化される。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | storage.ts | `packages/next/src/telemetry/storage.ts` | コンストラクタ（行62-82）で`notify()`が呼ばれる |

**主要処理フロー**:
1. **行62-66**: コンストラクタで環境変数`NEXT_TELEMETRY_DISABLED`, `NEXT_TELEMETRY_DEBUG`を読み込み
2. **行70-77**: `Conf`インスタンスを初期化（try-catch内）
3. **行78**: `sessionId`をランダム生成
4. **行81**: `this.notify()`を呼び出し

#### Step 3: 通知ロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | storage.ts | `packages/next/src/telemetry/storage.ts` | `notify`メソッド（行84-111）の条件分岐と出力ロジック |

**主要処理フロー**:
- **行85-87**: `isDisabled`またはconf未初期化なら即リターン
- **行93-95**: `notifiedAt`キーが存在すれば既に通知済みなので即リターン
- **行96**: `notifiedAt`に現在時刻を記録
- **行98-101**: "Attention"メッセージ出力（magenta太字）
- **行103-105**: 使用目的メッセージ出力
- **行106-108**: オプトアウト案内出力
- **行109**: URL出力（cyanカラー）
- **行110**: 空行出力

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

```
new Telemetry({ distDir }) (storage.ts:62)
    │
    ├─ new Conf({ projectName: 'nextjs', cwd: storageDirectory }) (行74)
    │
    └─ this.notify() (storage.ts:84)
           ├─ this.isDisabled チェック (storage.ts:135-140)
           ├─ this.conf.get(TELEMETRY_KEY_NOTIFY_DATE) チェック (行93)
           ├─ this.conf.set(TELEMETRY_KEY_NOTIFY_DATE, ...) (行96)
           └─ console.log() x 5回 (行98-110)
```

### データフロー図

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

NEXT_TELEMETRY_DISABLED ──────┐
                              │
Conf store ───────────────────┼── notify() ───────────▶ console.log (stdout)
  telemetry.notifiedAt ───────┤       │
  telemetry.enabled ──────────┘       │
                                      ▼
                              Conf store 更新
                              (telemetry.notifiedAt = Date.now())
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| storage.ts | `packages/next/src/telemetry/storage.ts` | ソース | テレメトリ管理とnotify実装 |
| picocolors | `packages/next/src/lib/picocolors.ts` | ソース | ANSIカラー装飾ユーティリティ |
| ci-info.ts | `packages/next/src/server/ci-info.ts` | ソース | CI環境判定 |
| detached-flush.ts | `packages/next/src/telemetry/detached-flush.ts` | ソース | テレメトリの非同期フラッシュ |
