Skip to content

機能仕様書: HTTP/プロキシ対応とテレメトリ透明性 #87

@akiojin

Description

@akiojin

Spec

機能仕様書: HTTP/プロキシ対応とテレメトリ透明性

機能ID: SPEC-a28f3f95
作成日: 2025-12-04
ステータス: 下書き
入力: ユーザー説明: "HTTP/プロキシ対応、テレメトリ明示"

ユーザーシナリオ&テスト (必須)

ユーザーストーリー1 - HTTPのみ許可された環境で接続したい (優先度: P1)

企業ネットワークで TCP/stdio が遮断されていても、HTTP/JSON-RPC で Unity CLI Bridge サーバーに接続したい。追加ツールなしで --http 起動し、ヘルスチェックで即確認したい。

この優先度の理由: ネットワーク制約で導入可否が左右されるため最重要。

独立テスト: npx ... --http 6401 で起動し /healthz が 200 を返すことを確認すれば価値成立。

受け入れシナリオ:

  1. 前提 TCP/stdio が閉じた社内ネットワーク、実行 HTTP モードで起動しヘルスチェック実行、結果 200 応答と接続手順が得られクライアント接続が成功する。
  2. 前提 HTTP ポートが占有されている、実行 同ポート指定で起動、結果 起動が失敗し代替ポート候補と再実行例が表示される。

ユーザーストーリー2 - テレメトリ送信を明示的に管理したい (優先度: P2)

セキュリティポリシーの厳しい環境で、デフォルトは送信なし、必要なら明示的に許可する形にしたい。設定値と送信先がログと README で確認でき、無効化状態を起動時に表示してほしい。

この優先度の理由: 事前審査のボトルネックを解消し、導入を早める。

独立テスト: テレメトリ無効で起動し、ネットワークキャプチャで外向き通信 0 件を確認すれば価値成立。

受け入れシナリオ:

  1. 前提 テレメトリ禁止ポリシー、実行 デフォルト設定で起動、結果 起動ログに「テレメトリ送信なし」が表示され、送信が発生しない。
  2. 前提 テレメトリを明示的に許可したい、実行 環境変数を設定して起動、結果 送信先と収集項目がログに表示され、オプトアウト方法も併記される。

エッジケース

  • HTTP/stdio の両方を有効にした際にプロセスを二重起動しない(単一プロセスで複数チャネルを扱うか、拒否する)。
  • 企業プロキシ環境で HTTP_PROXY などが未設定の場合、起動時にヒントを表示する。
  • ヘルスチェックだけが通り実処理が失敗する場合、HTTP レスポンスに詳細なエラー理由を含める。
  • テレメトリ無効時に依存ライブラリが自動送信を試みた場合、起動を失敗させ原因を明示する。

要件 (必須)

機能要件

  • FR-001: サーバー起動時に HTTP トランスポートを有効化でき、標準ヘルスチェックエンドポイントを提供する。
  • FR-002: stdio/TCP と HTTP を排他的または同時に有効化でき、起動ログに有効チャネルとポートを明示する。
  • FR-003: HTTP ポート競合時は起動をブロックし、代替ポート候補と再実行例を提示する。
  • FR-004: テレメトリ送信のデフォルトを「送信なし」とし、送信先・収集項目・オプトアウト方法を README と起動ログで開示する。
  • FR-005: テレメトリを有効にした場合は起動時に送信先をログ出力し、無効時は外向き通信が 0 であることを確認できる。
  • FR-006: HTTP モード有効時も既存 CLI/クライアント互換性を維持し、API 仕様を README に追記する。
  • FR-007: エラー時のレスポンスは人間可読(日本語/英語どちらか)で返す。

主要エンティティ

  • 接続チャネル設定: stdio/TCP/HTTP の有効フラグ、ポート、ヘルスチェックパス。
  • テレメトリ設定: 送信有無、送信先、収集項目、オプトアウト方法。

スコープ外

  • HTTP 認証や VPN/プロキシ自動検出。
  • 送信データの分析基盤構築。

技術制約

  • Unity 2020.3 LTS 以降で動作すること。
  • HTTP モード追加によって既存 stdio/TCP モードを破壊しないこと。
  • テレメトリ無効時に外部通信を行わないこと(依存ライブラリも含む)。

前提条件

  • MCP クライアントが HTTP もしくは stdio/TCP のいずれかをサポートしている。
  • HTTP 用ポートがローカルで開放できる権限がある。

依存関係

  • 既存の Unity CLI Bridge サーバー起動フロー(CLI/Node)。
  • 既存ポート設定管理ロジック。

成功基準

  1. HTTP モード起動時のヘルスチェック成功率が社内ネットワーク検証 3 回中 3 回で 100%。
  2. テレメトリ無効設定下の外向き通信がネットワークキャプチャで 0 件。
  3. ポート競合時に 100% 再実行ガイドが表示され、重複起動が発生しない。

Plan

実装計画: HTTP/プロキシ対応とテレメトリ透明性

機能ID: SPEC-a28f3f95 | 日付: 2025-12-04 | 仕様: spec.md
入力: /specs/SPEC-a28f3f95/spec.md の機能仕様

概要

HTTP/JSON-RPC での起動モードを追加し、ポート競合検知とヘルスチェックを提供する。同時にテレメトリ挙動をデフォルト無効・明示化し、送信先/オプトアウトをログと README に反映する。既存 stdio/TCP モードとの互換性を維持し、ポート競合時はガイド付きで安全に失敗する。

技術コンテキスト

言語/バージョン: Node.js 18/20/22 LTS (ESM)
主要依存関係: @modelcontextprotocol/sdk, fastify/express不使用(軽量HTTPサーバーは標準httpで実装予定)、better-sqlite3(既存)
ストレージ: なし(設定は既存 config)
テスト: node --test (contract/integration/unit)
対象プラットフォーム: Linux/macOS/Windows, Unity 2020.3+ クライアント
プロジェクトタイプ: single (unity-cli)
パフォーマンス目標: HTTP ヘルスチェック応答 ≤50ms ローカル, 起動時ポート競合検知 ≤200ms
制約: 既存 CLI 互換、外向き通信ゼロを保証 (テレメトリ無効時)
スケール/スコープ: 1 HTTP リスナー追加 + ログ/設定ドキュメント更新

憲章チェック

シンプルさ: プロジェクト1、標準 http モジュール直使用、追加ラッパーなし → OK
アーキテクチャ: 既存 unity-cli に HTTP リスナーを追加、ライブラリ分割不要 → OK
テスト: RED→GREEN→REFACTOR、contract→integration→unit 順で作成 → 厳守
可観測性: 起動ログにチャネル/ポート/テレメトリ状態を出力、ヘルスチェックで状態確認 → OK
バージョニング: 破壊的変更なし、semantic-release patch/minor 予定 → OK

プロジェクト構造

unity-cli/
  src/
    core/httpServer.js        # 新規: HTTP トランスポート
    core/server.js            # 既存: 起動オプションにhttp追加
  tests/
    contract/http-health.test.js
    integration/http-mode.test.js
    unit/core/httpServer.test.js
specs/SPEC-a28f3f95/
  spec.md
  plan.md
  research.md
  data-model.md
  quickstart.md
  contracts/
    http-endpoints.md
    telemetry-config.md
  tasks.md (後で /speckit.tasks 相当で作成)

Phase 0: アウトライン&リサーチ (research.md に反映)

  • HTTP 実装方式: Node.js 標準 http vs fastify/express → シンプルさ優先で標準 http を選定。
  • ポート競合検知: server.listen エラーハンドリングで EADDRINUSE を捕捉し、再提案ポートを返す。
  • ヘルスチェック仕様: GET /healthz 200/JSON {status:"ok", mode:"http"}。
  • テレメトリ: デフォルト無効、環境変数 UNITY_CLI_TELEMETRY=on/off で切替、送信先なしを保証。

Phase 1: 設計&契約 (data-model.md, contracts/, quickstart.md)

  • data-model: ConnectionChannelSetting, TelemetrySetting のフィールド定義。
  • contracts: http-endpoints (healthz, errorフォーマット), telemetry-config (環境変数・ログ出力項目)。
  • quickstart: HTTP 起動手順、ポート競合時の再試行例、テレメトリ設定例。

Phase 2: タスク計画アプローチ

/specs/SPEC-a28f3f95/tasks.md にテスト優先で作成 (次フェーズ)。

Tasks

タスク: HTTP/プロキシ対応とテレメトリ透明性 (SPEC-a28f3f95)

入力: plan.md, research.md, data-model.md, contracts/
前提条件: Node.js 18/20/22, Unity 不要 (サーバー単体)

Phase 3.1: セットアップ

  • T001 リポ構成確認と http モード用フォルダ src/core/httpServer.js 追加
  • T002 [P] ESLint/Prettier 設定に HTTP ファイルを含める

Phase 3.2: テストファースト (TDD)

  • T003 tests/contract/http-health.test.js に GET /healthz contract test (200, error)
  • T004 [P] tests/integration/http-mode.test.js に HTTP 起動/停止・ポート競合シナリオ
  • T005 tests/unit/core/httpServer.test.js に EADDRINUSE/invalid-port のユニットテスト
  • T006 [P] tests/unit/core/telemetry.test.js に telemetry on/off ログ出力と送信ゼロを検証

Phase 3.3: コア実装

  • T007 src/core/httpServer.js 実装(healthz, graceful shutdown, port check)
  • T008 src/core/server.js に HTTP 起動オプション追加(stdio/TCP 共存)
  • T009 CLI オプション/README に --http, telemetry 設定を追記

Phase 3.4: 統合

  • T010 ポート競合時の代替ポート提案ロジック実装&ログ
  • T011 テレメトリ設定のログ出力と外向き通信ブロック確認(テストと連動)

Phase 3.5: 仕上げ

  • T012 [P] docs/README 更新(Quickstart, env, error examples)
  • T013 [P] manual smoke: HTTP ヘルスチェック3回成功を記録

依存関係

  • T003,T004,T005,T006 → T007,T008,T010,T011
  • T007 → T008
  • T008 → T009

並列実行候補

  • [P] T002 と T003/T004/T005/T006 は並列可(別ファイル)
  • [P] T012,T013 は実装完了後並列可

TDD

TODO

Research

Research: HTTP/プロキシ対応とテレメトリ透明性 (SPEC-a28f3f95)

決定

  • HTTP リスナーは Node.js 標準 http で実装し、依存追加を避ける。
  • ヘルスチェックは GET /healthz、レスポンス { status: "ok", mode: "http" }、p99 応答 50ms 目標。
  • ポート競合 (EADDRINUSE) 検出時は起動失敗+代替ポート3候補をログ提示。
  • テレメトリはデフォルト無効。環境変数 UNITY_CLI_TELEMETRY=on のときのみ送信先を明示ログし、それ以外は外向き通信ゼロを保証。

未解決/要確認

  • テレメトリ送信を許可した場合の送信先 URL とペイロードスキーマ(現行送信が無い前提、設ける場合の仕様を要決定)。
  • HTTP/stdio 同時有効化時のシグナルハンドリング(停止処理)を単一プロセスで行うか、別モジュールに分けるか。

参考

  • Node.js server.listen エラーコード一覧 (EADDRINUSE) を用いた競合検出。
  • セキュリティポリシー準拠: テレメトリ無効時は DNS ルックアップも発生させない。

Data Model

Data Model: HTTP/プロキシ & Telemetry (SPEC-a28f3f95)

ConnectionChannelSetting

  • mode: "stdio" | "tcp" | "http" | "both"
  • httpPort: number (optional, required when mode includes http)
  • host: string (default localhost)
  • healthPath: string (default /healthz)
  • status: "starting" | "ready" | "error"
  • error?: string (last startup error)

TelemetrySetting

  • enabled: boolean (default false)
  • optInSource: "env" | "cli" | "config"
  • destinations: string[] (when enabled; empty when disabled)
  • fields: string[] (collected fields; empty when disabled)
  • lastReportedAt?: ISO datetime (when enabled)

HealthResponse (HTTP)

  • status: "ok" | "error"
  • mode: "http"
  • uptimeMs: number
  • telemetryEnabled: boolean
  • port: number
  • error?: string

Quickstart

Quickstart: HTTP/プロキシ対応 & テレメトリ透明性

HTTP モード起動

npx @akiojin/unity-cli --http 6401
# 出力例: HTTP listening on http://localhost:6401, telemetry: off
curl -s http://localhost:6401/healthz

ポート競合時の再試行

npx @akiojin/unity-cli --http 6401 || \
  npx @akiojin/unity-cli --http 6501

テレメトリ設定

  • 既定: 送信なし(外向き通信ゼロ)。
  • 明示的に有効化: UNITY_CLI_TELEMETRY=on npx @akiojin/unity-cli --http
  • 無効化確認: 起動ログに telemetry: off 表示、ネットワークキャプチャで送信 0 件。

併用 (stdio + HTTP)

npx @akiojin/unity-cli --stdio --http 6401

有効チャネルは起動ログで確認する。

Contracts

Migrated from local files. See artifact comments below.

Checklists

Artifact files under checklists/ are managed in issue comments with checklist:<name> entries.

Acceptance Checklist

  • Add acceptance checklist

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions