NexusCore コードレビュー対応 Playbook
注意: このファイルは「AI / Cursor 向けの指示とプレイブック」です。 全体のドキュメントインデックスは DOCS_INDEX.md を参照してください。
0. 前提ルール(NexusCore 専用)
このリポジトリで AI を使うときは、常に以下を前提とすること。
- 本プロジェクト名は NexusCore である。
- 出力は必ず「差分パッチ形式(unified diff)」で行うこと。
- 既存の公開 API(関数シグネチャ、クラス名、エンドポイント URI)は原則として破壊的変更を禁止する。
- どうしても破壊的変更が必要な場合は、互換レイヤ(deprecated ラッパ等)を挟み、既存呼び出し元が壊れないようにする。
- 変更を行うファイルと、それに対応するテストファイルを必ずセットで編集すること。
- 可能な限り変更範囲を最小化し、副作用を限定すること。
1. 問題ごとの指示テンプレート(共通フォーマット)
各問題を修正するときは、下記テンプレートをそのまま使って Cursor に指示する。
[問題ID] [重要度ラベル] [短いタイトル]
1. 対象ファイル
path/to/file1.pypath/to/file2.py(テスト or 関連ユーティリティ)
2. 現状と問題点
現状コードの概要:
どの関数/メソッド/エンドポイントで何をしているかを簡潔に記述。
問題点:
何が危険/脆弱/不十分なのかを1〜3行で記述。
例:コマンドインジェクションの危険、認証なしの API、未検証の入力など。
3. 修正方針(何をどう直すか)
以下の条件を満たす形で修正コードを提案し、差分パッチ(unified diff)として出力すること。
目的
この修正で何を達成したいかを1〜2行で明記。
具体的な修正内容
どの関数・メソッドをどのように変更するかを箇条書きで指定。
例:
subprocess.run()のshell=Trueを禁止し、引数リスト形式に変更する。- API エンドポイントに認証デコレータを追加する。
- 入力値の型・範囲チェックを追加する。
- 依存パッケージのバージョン指定を追加する。
実装上の制約
- 外部インターフェース(関数シグネチャ、HTTP パラメータ、戻り値)は原則として変更しないこと。
- 変更が必要な場合は以下のルールを守ること:
- 既存呼び出しを壊さないように、引数は必ずデフォルト値付きのオプショナル引数として追加する。
- エンドポイント URI は変更しない。認証・バリデーションは内部実装として追加する。
- ログ出力や例外メッセージは、既存のログフォーマットをできる限り踏襲すること。
セキュリティ・堅牢性に関するルール
- 例外処理では
except Exception:ではなく、可能な限り具体的な例外型を捕捉すること。 - デバッグ用途のコード(
print、pdb.set_trace、debug=True等)は残さないこと。 - ファイルパス・外部入力・環境変数を利用する際は、必ず検証・制約を加えること。
4. 破壊的変更を避けるためのルール
次のものは変更禁止(または互換レイヤ必須)とする:
- HTTP エンドポイントの URI・HTTP メソッド・必須パラメータ。
- 公開クラス・公開関数(
__all__やドキュメントに記載されているもの)。 - 既存の戻り値型・辞書キー名。
リファクタリングは以下の範囲に限定する:
- 内部ヘルパー関数の抽出。
- 大きすぎる関数の分割(ただし公開 API はそのまま残す)。
- 既存のテストが緑のまま通ることを前提とする。
テスト仕様に反する挙動変更が必要な場合は、必ず指摘し、テストケースの変更理由をコメントで明示すること。
5. テスト方針(pytest)
テストファイルの場所
対応するテストファイルを以下の規約で作成または更新すること:
- 対象:
src/nexuscore/.../foo.py - テスト:
tests/.../test_foo.py(既存規約に合わせる)
追加・更新すべきテストケース
- 正常系:
- 変更後のメインフローが期待どおり動くことを確認するテスト。
- 異常系:
- 不正な入力(例:負の値、空文字、サイズ超過など)を与えたときに、安全な失敗(例外 or バリデーションエラー)が起きること。
- セキュリティ系(該当する場合):
- コマンドインジェクションのペイロードを与えても、シェルが解釈しないこと。
- 認証のないリクエストが 401/403 で拒否されること。
テスト実行コマンド(提案)
最低限、対象モジュールのテストを実行するコマンドを最後にコメントとして記載すること(例):
pytest tests/path/to/test_foo.py -q
可能なら、関連モジュールを含むサブツリー単位のテストコマンドも併記する。
6. 出力形式(必須)
出力はリポジトリルートからのパスを含む unified diff のみとすること。
例:
diff --git a/src/nexuscore/ui/unified_gradio_ui.py b/src/nexuscore/ui/unified_gradio_ui.py
index abcdef0..1234567 100644
--- a/src/nexuscore/ui/unified_gradio_ui.py
+++ b/src/nexuscore/ui/unified_gradio_ui.py
@@ -316,7 +316,10 @@ def run_tests(command: str, test_file: str | None = None) -> RunResult:
- if test_file.strip():
- cmd = f"{command} {test_file}"
- else:
- cmd = command
-
- result = subprocess.run(cmd, shell=True, ...)
+ cmd: list[str]
+ if test_file and test_file.strip():
+ cmd = [command, test_file]
+ else:
+ cmd = [command]
+
+ result = subprocess.run(cmd, shell=False, ...)
テキストでの説明は、diff の前後に短く要約を入れる程度にとどめること。
2. 主要な問題に対する「テンプレート記入例」
以下は、上記テンプレートを実際の問題に当てはめたサンプル(そのまま Cursor に渡せるレベル)です。
[CR-001] 🔴 コマンドインジェクション脆弱性の修正
1. 対象ファイル
src/nexuscore/ui/unified_gradio_ui.pytests/nexuscore/ui/test_unified_gradio_ui.py(新規作成または既存拡張)
2. 現状と問題点
現状コードの概要:
run_tests()(行 316-327 付近)で、ユーザー入力由来の test_file をシェルコマンド文字列に直接連結し、subprocess.run(..., shell=True) を使用している。
問題点:
この実装は、test.py; rm -rf / のような入力を通じて任意コマンド実行が可能な、典型的なコマンドインジェクション脆弱性を含む。
3. 修正方針(何をどう直すか)
目的
run_tests() におけるコマンドインジェクション脆弱性を除去し、安全な引数リスト形式でサブプロセスを起動する。
具体的な修正内容
commandとtest_fileを文字列連結するロジックを廃止し、List[str]による引数リストを構築する。subprocess.run()呼び出しでshell=Falseを指定する。test_fileがNoneまたは空文字の場合は、コマンドリストを[command]のみとする。test_fileが空白のみの場合も無効とみなし、無視する。
実装上の制約
run_tests()のシグネチャは変更しない(引数・戻り値はそのまま)。RunResult等の既存データ構造のフィールド構成は変えない。
セキュリティ・堅牢性に関するルール
- 例外発生時は既存のエラーハンドリングパス(ログ出力・
RunResultへの格納)を維持する。 - デバッグ用の
print文などは残さない。
4. 破壊的変更を避けるためのルール
run_tests()を呼び出す側のインターフェースは一切変えない。- 既存のログメッセージフォーマットに大きな変更を加えない(文言調整は必要最低限)。
5. テスト方針(pytest)
テストファイル
tests/nexuscore/ui/test_unified_gradio_ui.py に以下を追加。
テストケース
- 正常系:
- 通常の
command="pytest"、test_file="tests/test_sample.py"のとき、subprocess.run()が["pytest", "tests/test_sample.py"]を受け取る形で呼ばれることをmonkeypatchまたはunittest.mockで検証。
- 通常の
- セキュリティ系:
test_file="tests/test_sample.py; rm -rf /"を渡した場合でも、実際に;以降が別コマンドとして解釈されないこと(cmdが 2 要素のリストであること)を確認。
テストコマンド(提案)
pytest tests/nexuscore/ui/test_unified_gradio_ui.py -q
6. 出力形式
上記の修正を含む unified diff を出力すること。
[CR-002] 🔴 認証なし API /api/v1/execute の保護
1. 対象ファイル
src/nexuscore/api/server.pytests/nexuscore/api/test_server_execute.py
2. 現状と問題点
現状コードの概要:
/api/v1/execute エンドポイントに、認証・認可の仕組みが一切ない。
問題点:
任意のクライアントがプロジェクトパスを指定してコード実行相当の処理を要求できるため、リモートコード実行・データ窃取のリスクが高い。
3. 修正方針(何をどう直すか)
目的
/api/v1/execute に簡易なトークンベース認証を導入し、許可されたクライアント以外からの実行を拒否する。
具体的な修正内容
require_authデコレータを同ファイル内に追加し、Authorization: Bearer <TOKEN>ヘッダを検証するロジックを実装する。- 許可トークンは環境変数(例:
NEXUSCORE_API_TOKEN)から読み込む。 /api/v1/execute関数に@require_authを付与する。- トークンが不正・不足の場合は
401 Unauthorizedを返す。
実装上の制約
- エンドポイントの URI (
/api/v1/execute) や HTTP メソッド(POST)は変更しない。 - レスポンス JSON の構造は、エラー時に
{"error": "..."}を含む形で既存仕様と整合性を取る。
セキュリティ・堅牢性に関するルール
- ヘッダからのトークン取得時に
Noneや空文字を適切に扱う。 - エラーメッセージに機密情報(トークン値など)を含めない。
4. 破壊的変更を避けるためのルール
認証導入によって既存のクライアントが動かなくなる可能性があることをコメントに明示する。
ただし、本エンドポイントはセキュリティ上の理由から認証の追加が必須なため、互換性より安全性を優先すること(既存クライアントはトークンを付与する対応を前提)。
5. テスト方針(pytest)
テストファイル
tests/nexuscore/api/test_server_execute.py を作成し、Flask の test_client を使って検証する。
テストケース
- トークンなしリクエスト → 401 が返る。
- 不正トークン → 401 が返る。
- 正しいトークン → 200 または既存仕様どおりのレスポンスコードが返る(モックした実行ロジックを用いて副作用を避ける)。
テストコマンド(提案)
pytest tests/nexuscore/api/test_server_execute.py -q
6. 出力形式
上記の修正を含む unified diff を出力すること。
[CR-003] 🔴 サンドボックス保護の最低限実装
(同様に、src/nexuscore/core/sandbox_executor.py を対象として、resource.setrlimit によるメモリ・CPU 制限と禁止モジュールのブロックリストテストなどを、上記テンプレート形式で記述)
重要度別の問題分類
このテンプレートをベースに、以下の重要度別に問題を分類して管理する:
- CRITICAL(🔴): コマンドインジェクション / 認証なし API / サンドボックス / デバッグモード / 依存関係ピン留め
- HIGH(🟠): テストカバレッジ、Orchestrator の例外処理など
- MEDIUM(🟡): 入力検証、グローバル状態
それぞれ同じフォーマットで列挙していけば、Cursor に対する指示書として一貫性を保てます。