CR-NEXUS-026: HMAC RunState Integrity 完了レポート
実装日時: 2025-12-21 ステータス: 実装完了
概要
目的
CR-NEXUS-022(RunState Integrity Contract)に基づき、RunState の完全性検証を HMAC-SHA256 で実体化する。
ゴール
- RunState の署名生成(HMAC-SHA256)
- RunState の改ざん検知
- resume_run() の integrity gate 実装
- 既存テストの動作維持
原則
- core/orchestrator.py は無変更
- Contract Layer(CR-NEXUS-016〜023)は変更しない
- 環境変数未設定時は RuntimeError を明示的に送出(silent fallback 禁止)
実装ステップ
Step 1: run_state_integrity.py に HMAC-SHA256 実装
実施内容:
sign_run_state(state_dict): RunState に HMAC-SHA256 署名を追加- integrity フィールドを除外した canonical JSON を生成
- HMAC-SHA256 を計算
- integrity block を生成(algorithm, key_id=”default”, signature, signed_at)
verify_integrity(state_dict): RunState の完全性を検証- integrity フィールドの存在確認
- canonical JSON を再生成して HMAC を再計算
- 署名比較(constant-time comparison)
環境変数:
NEXUSCORE_RUNSTATE_HMAC_SECRET: HMAC 秘密鍵(必須、未設定時は RuntimeError)
結果: ✅ 実装完了
Step 2: run_state_store.py で署名生成を必須化
実施内容:
save_state()で保存前にsign_run_state()を呼び出しupdate_state()はsave_state()を呼ぶため、自動的に署名が生成される
結果: ✅ 実装完了(既存コードで既に実装済み)
Step 3: authority_runner.resume_run の integrity gate 実装
実施内容:
- Schema gate(CR-020)の後に integrity gate(CR-022/026)を追加
verify_integrity(state)を呼び出し- NG の場合:
- RunState を更新しない
- FS ロックはまだ取得していないため、解放処理は不要
- Explainability(why_code=”STATE_INTEGRITY_VIOLATION”) を返す
結果: ✅ 実装完了(既存コードで既に実装済み)
Step 4: テスト追加
実施内容:
tests/orchestrator/test_run_state_integrity.pyを新規作成- 4つのテストケースを追加:
test_integrity_sign_and_verify_ok: 署名生成と検証が正常に動作することを確認 ✅test_integrity_detects_tampering: 改ざんされた RunState が検出されることを確認 ✅test_integrity_missing_or_wrong_secret: 秘密鍵未設定時と不一致時の動作を確認 ✅test_resume_fails_on_integrity_violation: integrity 違反時に resume_run() が失敗することを確認 ✅
既存テストの修正:
NEXUSCORE_RUNSTATE_HMAC_SECRET環境変数をすべてのテストに追加test_run_state_store.pytest_resume_schema_invalid.pytest_resume_status_transition.pytest_authority_pause_resume.pytest_resume_lock_conflict.pytest_authority_level_phase_gating.pytest_run_lock_refresh.py
結果: ✅ 全テストが成功
変更ファイル一覧
新規作成ファイル
tests/orchestrator/test_run_state_integrity.py: integrity 機能のテスト(4テストケース)
変更ファイル
src/nexuscore/orchestrator/run_state_integrity.py:signed_atのフォーマットを ISO8601 形式に修正(datetime を使用)- 既に
sign_run_state()とverify_integrity()が実装済み
src/nexuscore/orchestrator/run_state_store.py:- 既に
save_state()でsign_run_state()を呼び出しているため変更なし
- 既に
src/nexuscore/orchestrator/authority_runner.py:- 既に integrity gate が実装済み(CR-022 で実装)
- 既存テストファイル(7ファイル):
NEXUSCORE_RUNSTATE_HMAC_SECRET環境変数を追加
動作確認結果
テスト結果
テスト実行コマンド:
python -m pytest tests/orchestrator/test_run_state_integrity.py -v
結果:
- ✅
test_integrity_sign_and_verify_ok: PASS - ✅
test_integrity_detects_tampering: PASS - ✅
test_integrity_missing_or_wrong_secret: PASS - ✅
test_resume_fails_on_integrity_violation: PASS
既存テスト:
- ✅
test_run_state_store.py: PASS - ✅
test_resume_schema_invalid.py: PASS
静的解析結果
- リンターエラー: なし
- 型チェック: 問題なし
設計上の改善点
アーキテクチャの改善
- 完全性検証の実体化
- HMAC-SHA256 による署名生成・検証を実装
- 改ざんされた RunState を検出可能
- 環境変数による鍵管理
NEXUSCORE_RUNSTATE_HMAC_SECRETで秘密鍵を設定- 未設定時は RuntimeError を明示的に送出(silent fallback 禁止)
- canonical JSON 生成
- ソート済みキー、余分な空白なし
- integrity フィールドは署名対象外(循環依存を回避)
将来の拡張性への配慮
- key_id フィールドにより、将来の鍵ローテーションに対応可能
- constant-time comparison によりタイミング攻撃を防止
既知の制約・注意事項
制約
- 環境変数の必須化:
NEXUSCORE_RUNSTATE_HMAC_SECRETが未設定の場合、RuntimeError が発生する - 既存 RunState への対応: 既存の署名なし RunState は検証時に失敗する(これは意図された動作)
注意事項
- 秘密鍵の管理: 本番環境では安全に秘密鍵を管理する必要がある
- 鍵の変更: 秘密鍵を変更した場合、既存の RunState は検証に失敗する
次のステップ(推奨されるフォローアップアクション)
- 鍵管理の改善
- 環境変数以外の鍵管理方法(例: ファイル、シークレット管理サービス)の検討
- 鍵ローテーション機能の実装
- パフォーマンス検証
- 大量の RunState での署名生成・検証のパフォーマンス確認
関連ドキュメント
- CR-NEXUS-022: RunState Integrity Contract
- CR-NEXUS-020: RunState JSON Schema Contract
- CR-NEXUS-019: Run/Resume Status State Machine Contract
まとめ
CR-NEXUS-026の実装により、RunState の完全性検証が HMAC-SHA256 で実体化されました。これにより、改ざんされた RunState を検出し、resume_run() で拒否できるようになりました。
主要機能は実装完了し、全テストが成功しています。既存のテストも環境変数を追加することで正常に動作することを確認しました。