Skip to content

feat: initial chronos-gate separation from chronos-graph - #1

Merged
yohi merged 42 commits into
masterfrom
feature/separate-gate
Jun 20, 2026
Merged

feat: initial chronos-gate separation from chronos-graph#1
yohi merged 42 commits into
masterfrom
feature/separate-gate

Conversation

@yohi

@yohi yohi commented Jun 18, 2026

Copy link
Copy Markdown
Owner
  • Migrate mcp_gateway/ → chronos_gate/ with full package rename
  • Add CLI entrypoint 'chronos-gate' with 'run' and 'evaluate' subcommands
  • Add OpenCode plugin for security evaluation (chronos-gate.js)
  • Add upstream support for context-store-mcp dependency
  • Add comprehensive test suite (412 tests)
  • Add LICENSE, package.json, pyproject.toml

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced ChronosGate, a universal security evaluator gateway for AI agent tool calls with intent-based access control.
    • Added human-in-the-loop approvals, structured output filtering, audit logging, and session-based SSE/JSON-RPC endpoints.
    • Added an LLM-based evaluation path with decision caching and an OpenCode plugin for permission gating.
    • Added a CLI for tool-call evaluation via JSON I/O.
  • Documentation

    • Added a comprehensive README plus intents.yaml and example policy files.
  • Infrastructure

    • Added automated dependency updates and new CI workflows (lint/typecheck/tests, coverage, CodeQL, Semgrep, SonarCloud) and release automation.

- Migrate mcp_gateway/ → chronos_gate/ with full package rename
- Add CLI entrypoint 'chronos-gate' with 'run' and 'evaluate' subcommands
- Add OpenCode plugin for security evaluation (chronos-gate.js)
- Add upstream support for context-store-mcp dependency
- Add comprehensive test suite (412 tests)
- Add LICENSE, package.json, pyproject.toml
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR adds Chronos Gate packaging and automation, policy and evaluator models, CLI and plugin evaluation, gateway runtime and approval handling, and integration coverage across the new runtime paths.

Changes

Chronos Gate bootstrap

Layer / File(s) Summary
Project setup
.coderabbit.yaml, .github/dependabot.yml, .gitignore, .github/workflows/*, package.json, pyproject.toml, codecov.yml, sonar-project.properties, scripts/*, README.md
Adds repository review settings, dependency automation, ignore rules, package metadata, CI/security/release workflows, helper scripts, coverage/sonar config, and top-level documentation.
Policy and evaluator contracts
intents.yaml, intents.example.yaml, src/chronos_gate/policies/intents.example.yaml, src/chronos_gate/policy/*, src/chronos_gate/filters/*, src/chronos_gate/config.py, src/chronos_gate/errors.py, src/chronos_gate/__init__.py, tests/unit/test_*policy*, tests/unit/test_*settings*, tests/unit/test_chronos_gate_evaluator_models.py, tests/unit/test_param_constraint.py, tests/unit/test_notifier_sanitization.py, tests/unit/test_approval_models.py
Adds policy YAMLs, typed policy validation and loading, evaluator/redaction data models, output filters, configuration models, error types, and supporting tests.
CLI and plugin evaluation
src/chronos_gate/__main__.py, src/chronos_gate/cli.py, src/chronos_gate/policy/composite.py, src/chronos_gate/policy/llm_evaluator.py, src/chronos_gate/policy/memory_client.py, src/chronos_gate/policy/_composite_llm.py, .opencode/plugins/chronos-gate.js, tests/unit/test_chronos_gate_cli.py, tests/unit/test_chronos_gate_composite.py, tests/unit/test_chronos_gate_llm_evaluator.py, tests/unit/test_chronos_gate_memory_client.py, tests/integration/test_evaluator_cli_subprocess.py
Adds JSON I/O CLI evaluation, tiered policy and LLM judging, dashboard memory lookup, module entrypoint routing, OpenCode permission evaluation, and coverage for those paths.
Gateway runtime and tool calls
src/chronos_gate/app.py, src/chronos_gate/server.py, src/chronos_gate/auth/*, src/chronos_gate/audit/*, src/chronos_gate/tools/*, src/chronos_gate/upstream/*, tests/unit/test_build_app_hidden_tools.py, tests/unit/test_session_*, tests/unit/test_tool_registry_hidden.py, tests/unit/test_upstream_timeout.py, tests/unit/test_settings_ingestion_mode.py
Adds the FastAPI app and routes, handshake/session lifecycle, upstream MCP client and timeout handling, tool proxy/registry behavior, audit logging, and tests for runtime state and gateway wiring.
Approval flow and request limits
src/chronos_gate/approval/*, src/chronos_gate/middleware.py, tests/unit/test_approval_*, tests/unit/test_session_eviction_hook.py
Adds approval request models, sanitization, notifier logging, pending approval registry, body-size middleware, approval route handling, and approval-focused tests.
Cross-project integration coverage
tests/integration/test_phase2_timeout_integration.py
Adds integration tests covering retry, ingestion timing, upstream timeout normalization, and read-only evaluator bypass with adjacent Chronos components.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

🐇 I hopped through gates of policy bright,
And sniffed the routes from day to night.
The tools, the tests, the toasts aligned,
With secrets masked and paths confined.
A tidy burrow, warm and true—
Chronos Gate now hops on through.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.94% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: the initial separation of chronos-gate from chronos-graph by migrating the mcp_gateway package to a new chronos_gate package with a complete rename.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/separate-gate

Comment @coderabbitai help to get the list of available commands and usage tips.

@yohi

yohi commented Jun 18, 2026

Copy link
Copy Markdown
Owner Author

@greptileai

@greptile-apps

greptile-apps Bot commented Jun 18, 2026

Copy link
Copy Markdown

Greptile Summary

このPRはMCPゲートウェイ機能を mcp_gateway/ から chronos_gate/ パッケージとして独立したリポジトリに分離するもので、CLIエントリポイント、OpenCodeプラグイン、412テスト、完全なCI/CDパイプラインを追加します。

  • セキュリティ評価ゲートウェイをスタンドアロンパッケージとして再構成し、意図ベースアクセス制御(IBAC)エンジン・LLM評価レイヤー・人間承認フローを含む
  • CompositeEvaluator / PendingApprovalRegistry / InMemorySessionRegistry など主要コンポーネントを新規追加し、MaxBodySizeMiddleware でリクエストサイズ制限も実装
  • GitHub Actions CI/CDワークフロー(テスト・型チェック・CodeQL・Semgrep・SonarCloud・npm公開)を追加

Confidence Score: 4/5

1箇所のバグを修正すれば安全にマージ可能。

_execute_tool_call 内の PolicyError・UpstreamError ハンドラで tool=tool_name(変数)の代わりに tool="tool_name"(文字列リテラル)が監査ログに書き込まれる。これらのエラーパスが発生した際、監査ログ上で実際のツール名が記録されず、インシデント調査や監査追跡が機能しなくなる。それ以外のコンポーネント(セッション管理・承認レジストリ・LLM評価層・ミドルウェア)は品質・整合性ともに問題なし。

src/chronos_gate/server.py の _execute_tool_call 関数(PolicyError・UpstreamError の audit.log 呼び出し箇所)

Security Review

  • 監査ログの改ざんリスク: server.py_execute_tool_call 内で、PolicyError および UpstreamError 発生時の監査ログが tool=tool_name(変数)ではなく tool=\"tool_name\"(文字列リテラル)を記録する。実際のツール名が記録されないため、セキュリティ調査・インシデントレスポンスの際に正確な情報が得られない。
  • その他(認証・認可・インジェクション・シークレット漏洩): 明確な脆弱性は確認されなかった。_SAFE_KEYS による session_id のマスクスキップ(前PRスレッドで修正済み)、_resolve_fallback_mode"ask" デフォルト(前PRスレッドで修正済み)、LLMプロンプトインジェクション対策の XML エスケープ処理も実装済み。

Important Files Changed

Filename Overview
src/chronos_gate/server.py メインのSSE/messages/approvals/evaluateルーターハンドラ。_execute_tool_call 内の2箇所で tool="tool_name" という文字列リテラルが変数の代わりに使用されており、PolicyError・UpstreamError 発生時の監査ログが壊れる(P1)。
src/chronos_gate/policy/_composite_llm.py LLM判定のコアロジック。except BaseException で CancelledError も捕捉しフューチャーに例外を伝播させる実装になっており、過去に指摘された asyncio.shield ハング問題は解決済み。
src/chronos_gate/policy/composite.py CompositeEvaluator(Tier1決定論エンジン + Tier2 LLM)。キャッシュ・コアレッシング・fallback設定の実装が整合的で問題なし。
src/chronos_gate/approval/registry.py asyncio.Event ベースの承認待ちレジストリ。タイムアウト・CancelledError・セッション退場時のキャンセル処理が正確に実装されている。
src/chronos_gate/auth/session.py スレッドセーフなインメモリセッションレジストリ。TTL/アイドルタイムアウト・退場フックの実装が正確。
src/chronos_gate/audit/logger.py _SAFE_KEYS に "sid"/"session_id" を追加し UUID hex がマスクされる問題を修正済み。前PRスレッドで指摘された問題は解消されている。
src/chronos_gate/middleware.py Content-Length あり/なし両パスでリクエストボディサイズ制限を実装。バッファリング戦略・413応答処理が正確。
src/chronos_gate/policy/llm_evaluator.py LLM判定器。XMLエスケープ・JSONパース・フォールバック処理が堅牢。Cloudflare Workers AI向けの system ロール非対応ケースも適切に処理。
src/chronos_gate/app.py FastAPIアプリファクトリ。依存注入・ライフサイクル管理・ツールレジストリ初期化が整合的。
src/chronos_gate/upstream/context_store_client.py stdio MCP クライアント。環境変数の allowlist フィルタリング・エラーハンドリング・ツールキャッシュが適切に実装されている。
.github/workflows/release.yml npm プラグインのリリースワークフロー。軽量タスクに ubuntu-slim を使用しており、チームルールに準拠。
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
src/chronos_gate/server.py:597-614
**監査ログのツール名が文字列リテラルになっている**

`PolicyError` および `UpstreamError` 発生時の監査ログで `tool=tool_name`(変数)ではなく `tool="tool_name"`(文字列リテラル)が記録されています。これらのエラーパスで発生したすべての監査イベントが `"tool_name"` という固定文字列になり、実際にどのツール呼び出しでエラーが発生したか追跡できなくなります。

```suggestion
    except PolicyError as exc:
        audit.log(
            ev="call",
            decision="deny",
            reason="sanitize",
            agent=record.agent_id,
            sid=sid,
            tool=tool_name,
        )
        return _jsonrpc_error(rpc_id, -32602, str(exc))
    except UpstreamError:
        audit.log(
            ev="call",
            decision="upstream_error",
            agent=record.agent_id,
            sid=sid,
            tool=tool_name,
        )
```

Reviews (8): Last reviewed commit: "fix: pluginでの'ask'判定の格下げを修正し確認プロンプトを正常化" | Re-trigger Greptile

Comment thread src/chronos_gate/audit/logger.py
Comment thread src/chronos_gate/server.py Outdated
Comment thread .github/workflows/release.yml
Comment thread .opencode/plugins/chronos-gate.js Outdated
yohi added 3 commits June 19, 2026 08:24
- CodeRabbit AIレビュー設定 (.coderabbit.yaml)
- Dependabot自動更新設定 (.github/dependabot.yml)
- CodeQLセキュリティ解析 (.github/workflows/codeql.yml)
- Semgrep静的解析 (.github/workflows/semgrep.yml)
- SonarCloud品質ゲート (.github/workflows/sonarcloud.yml)
- Codecovカバレッジレポート (.github/workflows/codecov.yml)
- SonarCloudプロジェクト設定 (sonar-project.properties)
- Codecov閾値設定 (codecov.yml)

デフォルトブランチはmasterを対象としています。
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

Comment thread src/chronos_gate/server.py Fixed
Comment thread src/chronos_gate/server.py Fixed
@yohi

yohi commented Jun 19, 2026

Copy link
Copy Markdown
Owner Author

@greptileai

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

🧹 Nitpick comments (5)
src/chronos_gate/app.py (1)

80-90: 💤 Low value

Consider forwarding the reason parameter to cancel_session.

The callback receives a reason argument but doesn't pass it to cancel_session, which will always use the default "session_evicted". If different eviction reasons should be preserved in the approval history, forward the parameter:

     async def _on_session_evicted(sid: str, reason: str) -> None:
         try:
-            await approval_registry.cancel_session(sid)
+            await approval_registry.cancel_session(sid, reason=reason)
         except Exception as exc:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/chronos_gate/app.py` around lines 80 - 90, The _on_session_evicted
function receives a reason parameter but does not forward it to the
approval_registry.cancel_session method call. Modify the cancel_session call to
include the reason parameter as a second argument so that different eviction
reasons are preserved in the approval history instead of always using the
default session_evicted reason.
.github/workflows/sonarcloud.yml (1)

14-35: ⚖️ Poor tradeoff

Pin actions to full SHA hashes for supply chain security.

Using version tags (@v4, @v3, @v5, @master) allows upstream changes to silently affect your workflow. Pin to commit SHAs for reproducible, secure builds.

🔒 Suggested pinning approach
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@<full-sha>  # v4
         with:
           fetch-depth: 0

-      - uses: astral-sh/setup-uv@v3
+      - uses: astral-sh/setup-uv@<full-sha>  # v3
         with:
           version: "latest"

-      - uses: actions/setup-python@v5
+      - uses: actions/setup-python@<full-sha>  # v5
         with:
           python-version: "3.12"

-      - uses: SonarSource/sonarcloud-github-action@master
+      - uses: SonarSource/sonarcloud-github-action@<full-sha>  # v3.x

Retrieve current SHAs from each action's releases page and add a version comment for maintainability.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sonarcloud.yml around lines 14 - 35, Replace all action
version tags with full commit SHA hashes for supply chain security. For each of
the four actions used in the workflow (actions/checkout, astral-sh/setup-uv,
actions/setup-python, and SonarSource/sonarcloud-github-action), replace the
version tag (such as `@v4`, `@v3`, `@v5`, `@master`) with the complete commit SHA
retrieved from each action's releases page. Add a comment next to each pinned
SHA referencing the original version tag for maintainability, so that future
maintainers can easily identify which version is being used without having to
check the commit history.

Source: Linters/SAST tools

src/chronos_gate/policy/models.py (1)

96-103: ⚡ Quick win

Unreachable validation check on lines 101-102.

Since RE_DOS_MAX_LENGTH (4096) is strictly less than MAX_PARAM_LENGTH (1048576), the check on line 101-102 will never trigger - if max_length > RE_DOS_MAX_LENGTH, the error on line 100 is raised first; otherwise max_length is certainly within MAX_PARAM_LENGTH.

This is dead code. Consider removing it or adjusting the logic if MAX_PARAM_LENGTH was intended as a separate, stricter system limit.

         if self.max_length is not None:
             if self.max_length > RE_DOS_MAX_LENGTH:
                 raise ValueError(f"max_length exceeds ReDoS mitigation limit ({RE_DOS_MAX_LENGTH})")
-            if self.max_length > MAX_PARAM_LENGTH:
-                raise ValueError(f"max_length exceeds system limit ({MAX_PARAM_LENGTH})")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/chronos_gate/policy/models.py` around lines 96 - 103, The validation
check comparing max_length against MAX_PARAM_LENGTH is unreachable dead code
because the RE_DOS_MAX_LENGTH check happens first and is stricter (smaller
value). Since RE_DOS_MAX_LENGTH (4096) is less than MAX_PARAM_LENGTH (1048576),
any max_length value that passes the first RE_DOS_MAX_LENGTH constraint will
automatically satisfy the MAX_PARAM_LENGTH constraint. Remove the unreachable
ValueError check for MAX_PARAM_LENGTH on lines 101-102, or if MAX_PARAM_LENGTH
was intended as a separate stricter system limit, reorder the validation logic
to check MAX_PARAM_LENGTH first instead.
.github/workflows/ci.yml (1)

25-27: ⚡ Quick win

Add uv dependency caching to avoid repeated cold installs.

This workflow reinstalls everything on every run; caching uv artifacts will reduce CI time significantly.

Suggested cache step
+      - name: Cache uv artifacts
+        uses: actions/cache@<full-commit-sha>
+        with:
+          path: |
+            ~/.cache/uv
+            .venv
+          key: ${{ runner.os }}-uv-${{ hashFiles('uv.lock') }}
+          restore-keys: |
+            ${{ runner.os }}-uv-
+
       - name: Install dependencies
         run: uv sync --all-extras

As per coding guidelines, **/*.yml: Check GitHub Actions workflow files for security best practices and efficient caching strategies.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 25 - 27, Add a caching step before the
"Install dependencies" step to cache uv artifacts and avoid repeated cold
installs. Use the actions/cache action to cache the uv cache directory
(typically ~/.cache/uv or the directory where uv stores its cache). Configure
the cache with an appropriate key that includes the hash of the lock file or
requirements, and set a restore-keys pattern to allow cache hits from previous
runs with similar dependencies. This will significantly reduce CI runtime by
reusing cached packages across workflow runs.

Source: Coding guidelines

tests/unit/test_chronos_gate_evaluator_settings.py (1)

44-53: ⚡ Quick win

Add coverage for api_account_id alias resolution paths.

The suite currently doesn’t assert that both CHRONOS_EVALUATOR_API_ACCOUNT_ID and CHRONOS_EVALUATOR_CLOUDFLARE_ACCOUNT_ID populate EvaluatorSettings.api_account_id, so alias regressions can slip in undetected.

Proposed test additions
+def test_api_account_id_aliases(monkeypatch: pytest.MonkeyPatch) -> None:
+    monkeypatch.setenv("CHRONOS_EVALUATOR_API_ACCOUNT_ID", "acct-primary")
+    settings = EvaluatorSettings(_env_file=None)  # type: ignore[call-arg]
+    assert isinstance(settings.api_account_id, SecretStr)
+    assert settings.api_account_id.get_secret_value() == "acct-primary"
+
+    monkeypatch.delenv("CHRONOS_EVALUATOR_API_ACCOUNT_ID", raising=False)
+    monkeypatch.setenv("CHRONOS_EVALUATOR_CLOUDFLARE_ACCOUNT_ID", "acct-cf")
+    settings = EvaluatorSettings(_env_file=None)  # type: ignore[call-arg]
+    assert isinstance(settings.api_account_id, SecretStr)
+    assert settings.api_account_id.get_secret_value() == "acct-cf"

As per coding guidelines, “tests/**/*.py: Ensure tests are comprehensive, use pytest fixtures appropriately, and cover both success and error cases.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/test_chronos_gate_evaluator_settings.py` around lines 44 - 53, The
test_extra_env_vars_ignored function does not cover the alias resolution paths
for api_account_id in EvaluatorSettings. Add test coverage that verifies both
CHRONOS_EVALUATOR_API_ACCOUNT_ID and CHRONOS_EVALUATOR_CLOUDFLARE_ACCOUNT_ID
environment variables correctly populate the api_account_id attribute on
EvaluatorSettings. This can be done either by extending the existing
test_extra_env_vars_ignored function or by creating separate test functions that
set each environment variable, instantiate EvaluatorSettings with
_env_file=None, and assert that settings.api_account_id contains the expected
value for both alias paths.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 13-23: Replace all tag-based GitHub Actions references with their
full 40-character commit SHAs to prevent supply-chain attacks. Pin the
`actions/checkout@v4` reference, the `astral-sh/setup-uv@v3` reference, and the
`actions/setup-python@v5` reference to their respective immutable commit SHAs.
Additionally, add `persist-credentials: false` to the `actions/checkout` action
configuration to prevent authentication token exposure to subsequent steps and
reduce security risk from potential step compromise.

In @.github/workflows/codecov.yml:
- Around line 14-33: Replace all GitHub Action version tags with immutable
full-length commit SHAs to prevent supply chain attacks. For the
actions/checkout@v4 step, add persist-credentials: false to the with section.
For astral-sh/setup-uv@v3, actions/setup-python@v5, and
codecov/codecov-action@v4, replace their version tags with the corresponding
commit SHAs by looking up each action's repository to find the SHA that
corresponds to the version tag being used. This ensures the workflow only runs
exact versions of actions and reduces the risk of malicious modifications
through tag repointing.
- Around line 32-39: The "Upload coverage to Codecov" step with the
codecov/codecov-action@v4 action has `fail_ci_if_error: true` which will cause
the CI to fail on fork pull requests because they cannot access the
CODECOV_TOKEN secret. To fix this, add a conditional guard to the step using
`if: github.event.pull_request.head.repo.full_name == github.repository` to skip
the upload for forks, or alternatively change `fail_ci_if_error` from true to
false to allow the job to pass even if the upload fails (Codecov supports
tokenless uploads for public repositories as a fallback).

In @.github/workflows/codeql.yml:
- Around line 23-27: The strategy configuration in the CodeQL workflow file
contains a duplicate matrix key declaration on consecutive lines. Remove the
first occurrence of the `matrix:` key (line 23) so that only one `matrix:` key
remains before the include section. This will resolve the invalid YAML syntax
that is breaking the workflow.

In @.github/workflows/release.yml:
- Around line 15-20: Replace the floating version tags in the release workflow
with pinned commit SHAs for security. Update the `actions/checkout@v4` action to
use the full commit SHA with a version comment, and add `persist-credentials:
false` configuration to the checkout step to prevent unnecessary credential
exposure. Similarly, update `actions/setup-node@v4` to pin it to its specific
commit SHA with a version comment. This prevents potential retargeting attacks
and ensures reproducible, secure GitHub Actions execution.

In @.github/workflows/semgrep.yml:
- Around line 18-28: Replace all mutable container image and action references
with pinned digests or SHAs to prevent supply chain attacks. In the semgrep
workflow, replace the image reference semgrep/semgrep:latest with a specific
image digest (using the `@sha256`:... format), replace the actions/checkout@v4
reference with its full commit SHA, and replace the
github/codeql-action/upload-sarif@v3 reference with its full commit SHA. This
ensures that the exact versions used are locked and cannot be unexpectedly
changed across workflow runs.

In @.github/workflows/sonarcloud.yml:
- Around line 14-16: The actions/checkout@v4 step is missing the
persist-credentials parameter which defaults to true, creating a security risk
by leaving credentials accessible to subsequent workflow steps. Add
persist-credentials: false to the with block of the checkout action alongside
the existing fetch-depth parameter to explicitly disable credential persistence
after checkout completes.
- Around line 34-35: In the SonarCloud Scan step, replace the deprecated and
archived `SonarSource/sonarcloud-github-action@master` action with
`SonarSource/sonarqube-scan-action@v4` in the uses field. Additionally, add an
env section to the step to set the SONAR_TOKEN environment variable using the
secrets.SONAR_TOKEN secret, which is required for the new action to authenticate
properly with SonarCloud.

In @.opencode/plugins/chronos-gate.js:
- Around line 265-270: The git URL in the gatewayArgs array for the `--from`
argument is unpinned and pulls from the default branch, creating a supply-chain
risk. Modify the URL string in the gatewayArgs array to append a commit hash or
tag reference (e.g.,
`git+https://github.com/yohi/chronos-gate.git@<commit-or-tag>`). Consider
allowing this pinned URL to be overridden via an environment variable so
controlled updates can be made when needed.
- Around line 101-104: The searchDirs.push() call at lines 102-103 is using
process.env.HOME directly, but the file already establishes a safer pattern at
lines 33 and 40 using os.homedir() || process.env.HOME || ''. Replace the direct
process.env.HOME references in the searchDirs.push() call (lines 102-103) and
also at lines 236, 277, and 282 with the existing proven safe pattern
os.homedir() || process.env.HOME || '' to ensure consistency and maintainability
throughout the file. This provides a consistent fallback mechanism across all
home directory resolutions.

In `@codecov.yml`:
- Line 18: The codecov.yml file restricts branch coverage enforcement to only
the master branch on lines 18 and 32, but the CI workflow in
.github/workflows/ci.yml is configured to run on both master and main branches.
Update both occurrences of the branches configuration in codecov.yml (the
branches array that currently contains only master) to include both master and
main to align with your CI branch strategy and ensure Codecov status checks
execute on all branches where CI runs.

In `@package.json`:
- Line 19: The package.json specifies a Node engine constraint of >=26.0.0, but
five CI workflows (ci.yml, codecov.yml, codeql.yml, semgrep.yml, sonarcloud.yml)
lack explicit Node version configuration and will use the default Node 22 from
ubuntu-latest, violating the constraint. Add the actions/setup-node@v4 action
with node-version set to '26' to each of these five workflow files after the
checkout step, following the same pattern already established in release.yml.
Alternatively, if Node 22 compatibility is acceptable, relax the engine
constraint in package.json to accommodate the default version, or add a .nvmrc
file with the appropriate Node version for local development guidance.

In `@scripts/chronos-evaluator-hook.sh`:
- Line 3: The `uvx --from` command references the chronos-gate Git repository
without pinning it to a specific commit SHA or version tag, causing it to
resolve to the unpredictable HEAD of the repository. Pin the Git URL to an
immutable reference by appending a commit SHA or version tag (e.g., using
`@commit-sha` or `@v1.0.0` notation depending on the Git ref syntax supported)
to ensure deterministic and secure dependency resolution.

In `@sonar-project.properties`:
- Line 11: The sonar.exclusions property is set to ** which excludes all files
from SonarQube analysis, contradicting the sonar.sources=src configuration.
Remove the sonar.exclusions=** line entirely, or replace it with a specific
exclusion pattern if you only want to exclude certain files or directories (such
as test files or specific node modules). Ensure the exclusion pattern does not
inadvertently exclude the src directory that you intend to analyze.

In `@src/chronos_gate/policy/composite.py`:
- Around line 42-43: The default value for the fallback_when_llm_not_configured
parameter is set to "allow", which auto-approves non-read-only tool calls when
the LLM is unavailable. This creates a security risk during degradation
scenarios. Change the default value from "allow" to "ask" for the
fallback_when_llm_not_configured parameter in the composite.py file.
Additionally, update the corresponding CHRONOS_EVALUATOR_FALLBACK environment
variable default in src/chronos_gate/cli.py from its current value to "ask" to
ensure consistency across the configuration.

In `@src/chronos_gate/policy/engine.py`:
- Around line 142-154: The code accesses the types_map dictionary directly with
expected_type_str at line 148 without validating that the key exists, which will
raise an unhandled KeyError if the policy specifies an unknown type value. Add
validation before accessing types_map to check if expected_type_str is a valid
key, and raise a more meaningful PolicyError with an appropriate message if it
is not found, rather than allowing the KeyError to propagate.

In `@src/chronos_gate/policy/llm_evaluator.py`:
- Around line 177-180: The substring matching logic in the Decision condition is
too simplistic and can misclassify responses like "not safe" as allow because it
only checks for the presence of "safe" without accounting for negation patterns.
Refactor the parsing logic to check for negation keywords like "not" before the
word "safe", or implement a more robust phrase-matching approach that correctly
identifies phrases like "not safe" before applying the simple substring checks.
This will ensure that negated safety statements are properly classified as
unsafe rather than allow.

In `@src/chronos_gate/server.py`:
- Around line 629-637: The self-approval check block that contains the audit.log
call and returns a 403 error response currently references the approval_id
variable before it has been assigned, causing an UnboundLocalError. Move the
entire self-approval validation block (which checks if requester_id is not None
and equals resolver_agent_id) to occur after the request body is parsed and the
approval_id variable is assigned. This ensures approval_id is available when the
self-approval check is performed.

In `@tests/unit/test_approval_models.py`:
- Around line 24-30: The test_enum_values method in the TestResolveOutcome class
is missing test coverage for one of the enum values. Add an assertion to verify
that ResolveOutcome.INVALID_STATUS has the value "invalid_status" alongside the
existing assertions for the other four enum values (OK, NOT_FOUND,
ALREADY_RESOLVED, and FORBIDDEN).

---

Nitpick comments:
In @.github/workflows/ci.yml:
- Around line 25-27: Add a caching step before the "Install dependencies" step
to cache uv artifacts and avoid repeated cold installs. Use the actions/cache
action to cache the uv cache directory (typically ~/.cache/uv or the directory
where uv stores its cache). Configure the cache with an appropriate key that
includes the hash of the lock file or requirements, and set a restore-keys
pattern to allow cache hits from previous runs with similar dependencies. This
will significantly reduce CI runtime by reusing cached packages across workflow
runs.

In @.github/workflows/sonarcloud.yml:
- Around line 14-35: Replace all action version tags with full commit SHA hashes
for supply chain security. For each of the four actions used in the workflow
(actions/checkout, astral-sh/setup-uv, actions/setup-python, and
SonarSource/sonarcloud-github-action), replace the version tag (such as `@v4`,
`@v3`, `@v5`, `@master`) with the complete commit SHA retrieved from each action's
releases page. Add a comment next to each pinned SHA referencing the original
version tag for maintainability, so that future maintainers can easily identify
which version is being used without having to check the commit history.

In `@src/chronos_gate/app.py`:
- Around line 80-90: The _on_session_evicted function receives a reason
parameter but does not forward it to the approval_registry.cancel_session method
call. Modify the cancel_session call to include the reason parameter as a second
argument so that different eviction reasons are preserved in the approval
history instead of always using the default session_evicted reason.

In `@src/chronos_gate/policy/models.py`:
- Around line 96-103: The validation check comparing max_length against
MAX_PARAM_LENGTH is unreachable dead code because the RE_DOS_MAX_LENGTH check
happens first and is stricter (smaller value). Since RE_DOS_MAX_LENGTH (4096) is
less than MAX_PARAM_LENGTH (1048576), any max_length value that passes the first
RE_DOS_MAX_LENGTH constraint will automatically satisfy the MAX_PARAM_LENGTH
constraint. Remove the unreachable ValueError check for MAX_PARAM_LENGTH on
lines 101-102, or if MAX_PARAM_LENGTH was intended as a separate stricter system
limit, reorder the validation logic to check MAX_PARAM_LENGTH first instead.

In `@tests/unit/test_chronos_gate_evaluator_settings.py`:
- Around line 44-53: The test_extra_env_vars_ignored function does not cover the
alias resolution paths for api_account_id in EvaluatorSettings. Add test
coverage that verifies both CHRONOS_EVALUATOR_API_ACCOUNT_ID and
CHRONOS_EVALUATOR_CLOUDFLARE_ACCOUNT_ID environment variables correctly populate
the api_account_id attribute on EvaluatorSettings. This can be done either by
extending the existing test_extra_env_vars_ignored function or by creating
separate test functions that set each environment variable, instantiate
EvaluatorSettings with _env_file=None, and assert that settings.api_account_id
contains the expected value for both alias paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 55837479-efe6-40dc-b374-6b01e8228a41

📥 Commits

Reviewing files that changed from the base of the PR and between d0e11d9 and 0ca15ca.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (81)
  • .coderabbit.yaml
  • .github/dependabot.yml
  • .github/workflows/ci.yml
  • .github/workflows/codecov.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release.yml
  • .github/workflows/semgrep.yml
  • .github/workflows/sonarcloud.yml
  • .gitignore
  • .opencode/plugins/chronos-gate.js
  • README.md
  • codecov.yml
  • intents.example.yaml
  • intents.yaml
  • package.json
  • pyproject.toml
  • scripts/check_evaluator.sh
  • scripts/chronos-evaluator-hook.sh
  • sonar-project.properties
  • src/chronos_gate/__init__.py
  • src/chronos_gate/__main__.py
  • src/chronos_gate/app.py
  • src/chronos_gate/approval/__init__.py
  • src/chronos_gate/approval/models.py
  • src/chronos_gate/approval/notifier.py
  • src/chronos_gate/approval/registry.py
  • src/chronos_gate/approval/sanitize.py
  • src/chronos_gate/audit/__init__.py
  • src/chronos_gate/audit/logger.py
  • src/chronos_gate/auth/__init__.py
  • src/chronos_gate/auth/api_key.py
  • src/chronos_gate/auth/handshake.py
  • src/chronos_gate/auth/headers.py
  • src/chronos_gate/auth/protocol.py
  • src/chronos_gate/auth/session.py
  • src/chronos_gate/cli.py
  • src/chronos_gate/config.py
  • src/chronos_gate/errors.py
  • src/chronos_gate/filters/__init__.py
  • src/chronos_gate/filters/factory.py
  • src/chronos_gate/filters/none_filter.py
  • src/chronos_gate/filters/protocol.py
  • src/chronos_gate/filters/structural_allowlist.py
  • src/chronos_gate/middleware.py
  • src/chronos_gate/policies/intents.example.yaml
  • src/chronos_gate/policy/__init__.py
  • src/chronos_gate/policy/composite.py
  • src/chronos_gate/policy/engine.py
  • src/chronos_gate/policy/llm_evaluator.py
  • src/chronos_gate/policy/loader.py
  • src/chronos_gate/policy/memory_client.py
  • src/chronos_gate/policy/models.py
  • src/chronos_gate/policy/models_evaluator.py
  • src/chronos_gate/py.typed
  • src/chronos_gate/server.py
  • src/chronos_gate/tools/__init__.py
  • src/chronos_gate/tools/proxy.py
  • src/chronos_gate/tools/registry.py
  • src/chronos_gate/upstream/__init__.py
  • src/chronos_gate/upstream/context_store_client.py
  • src/chronos_gate/upstream/timeout_client.py
  • tests/integration/test_evaluator_cli_subprocess.py
  • tests/integration/test_phase2_timeout_integration.py
  • tests/unit/test_approval_models.py
  • tests/unit/test_approval_registry.py
  • tests/unit/test_approval_sanitize.py
  • tests/unit/test_build_app_hidden_tools.py
  • tests/unit/test_chronos_gate.py
  • tests/unit/test_chronos_gate_cli.py
  • tests/unit/test_chronos_gate_composite.py
  • tests/unit/test_chronos_gate_evaluator_models.py
  • tests/unit/test_chronos_gate_evaluator_settings.py
  • tests/unit/test_chronos_gate_llm_evaluator.py
  • tests/unit/test_chronos_gate_memory_client.py
  • tests/unit/test_notifier_sanitization.py
  • tests/unit/test_param_constraint.py
  • tests/unit/test_session_eviction_hook.py
  • tests/unit/test_session_management.py
  • tests/unit/test_settings_ingestion_mode.py
  • tests/unit/test_tool_registry_hidden.py
  • tests/unit/test_upstream_timeout.py

Comment thread .github/workflows/ci.yml Outdated
Comment thread .github/workflows/codecov.yml Outdated
Comment thread .github/workflows/codecov.yml
Comment thread .github/workflows/codeql.yml Outdated
Comment thread .github/workflows/release.yml Outdated
Comment thread src/chronos_gate/policy/composite.py Outdated
Comment thread src/chronos_gate/policy/engine.py Outdated
Comment thread src/chronos_gate/policy/llm_evaluator.py
Comment thread src/chronos_gate/server.py Outdated
Comment thread tests/unit/test_approval_models.py
@yohi

yohi commented Jun 19, 2026

Copy link
Copy Markdown
Owner Author

@greptileai

Comment thread src/chronos_gate/server.py Outdated
Comment thread src/chronos_gate/policy/composite.py Outdated
Comment thread src/chronos_gate/server.py Outdated
@codecov

codecov Bot commented Jun 19, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

ℹ️ You can also turn on project coverage checks and project coverage reporting on Pull Request comment

Thanks for integrating Codecov - We've got you covered ☂️

@yohi

yohi commented Jun 19, 2026

Copy link
Copy Markdown
Owner Author

@greptileai

@yohi

yohi commented Jun 19, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai ignore

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

Comment thread .github/workflows/sonarcloud.yml Fixed
Comment thread .github/workflows/sonarcloud.yml Fixed
Comment thread .github/workflows/sonarcloud.yml Fixed
Comment thread .github/workflows/sonarcloud.yml Fixed
@yohi

yohi commented Jun 19, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai resume

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews resumed.

@yohi

yohi commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
.github/workflows/sonarcloud.yml (1)

35-35: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pin Sonar scan action to a full commit SHA.

Line 35 uses a mutable tag (@v8.2.0). Please pin to a 40-char commit SHA to preserve immutable workflow execution and satisfy unpinned-action policy checks.

Suggested change
-      - name: SonarCloud Scan
-        uses: SonarSource/sonarqube-scan-action@v8.2.0
+      - name: SonarCloud Scan
+        uses: SonarSource/sonarqube-scan-action@<FULL_40_CHAR_SHA> # v8.2.0
#!/bin/bash
set -euo pipefail

echo "Current reference:"
rg -n 'sonarqube-scan-action@' .github/workflows/sonarcloud.yml

echo
echo "Resolve SHA for v8.2.0:"
git ls-remote https://github.com/SonarSource/sonarqube-scan-action refs/tags/v8.2.0
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/sonarcloud.yml at line 35, Replace the mutable version tag
with a full 40-character commit SHA for the SonarSource/sonarqube-scan-action in
the sonarcloud.yml workflow file. Change the uses directive from the current
`SonarSource/sonarqube-scan-action@v8.2.0` to pin it to its corresponding commit
SHA by running the provided git command to resolve the SHA for tag v8.2.0, then
update the action reference to use that full commit hash instead of the version
tag.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In @.github/workflows/sonarcloud.yml:
- Line 35: Replace the mutable version tag with a full 40-character commit SHA
for the SonarSource/sonarqube-scan-action in the sonarcloud.yml workflow file.
Change the uses directive from the current
`SonarSource/sonarqube-scan-action@v8.2.0` to pin it to its corresponding commit
SHA by running the provided git command to resolve the SHA for tag v8.2.0, then
update the action reference to use that full commit hash instead of the version
tag.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3a364a49-4c19-4837-b11a-162938ec9c9f

📥 Commits

Reviewing files that changed from the base of the PR and between 0ca15ca and 78f3357.

📒 Files selected for processing (39)
  • .github/workflows/ci.yml
  • .github/workflows/codecov.yml
  • .github/workflows/codeql.yml
  • .github/workflows/release.yml
  • .github/workflows/semgrep.yml
  • .github/workflows/sonarcloud.yml
  • .opencode/plugins/chronos-gate.js
  • codecov.yml
  • coverage.xml
  • intents.yaml
  • scripts/chronos-evaluator-hook.sh
  • sonar-project.properties
  • src/chronos_gate/__main__.py
  • src/chronos_gate/app.py
  • src/chronos_gate/approval/notifier.py
  • src/chronos_gate/approval/registry.py
  • src/chronos_gate/audit/logger.py
  • src/chronos_gate/cli.py
  • src/chronos_gate/config.py
  • src/chronos_gate/filters/none_filter.py
  • src/chronos_gate/middleware.py
  • src/chronos_gate/policy/_composite_llm.py
  • src/chronos_gate/policy/composite.py
  • src/chronos_gate/policy/engine.py
  • src/chronos_gate/policy/llm_evaluator.py
  • src/chronos_gate/policy/memory_client.py
  • src/chronos_gate/policy/models.py
  • src/chronos_gate/policy/models_evaluator.py
  • src/chronos_gate/server.py
  • tests/integration/test_phase2_timeout_integration.py
  • tests/unit/conftest.py
  • tests/unit/test_approval_models.py
  • tests/unit/test_approval_registry.py
  • tests/unit/test_chronos_gate.py
  • tests/unit/test_chronos_gate_cli.py
  • tests/unit/test_chronos_gate_composite.py
  • tests/unit/test_chronos_gate_evaluator_models.py
  • tests/unit/test_chronos_gate_evaluator_settings.py
  • tests/unit/test_chronos_gate_llm_evaluator.py
💤 Files with no reviewable changes (1)
  • sonar-project.properties
✅ Files skipped from review due to trivial changes (3)
  • tests/unit/conftest.py
  • tests/unit/test_approval_models.py
  • coverage.xml
🚧 Files skipped from review as they are similar to previous changes (25)
  • .github/workflows/codecov.yml
  • .github/workflows/codeql.yml
  • .github/workflows/ci.yml
  • scripts/chronos-evaluator-hook.sh
  • src/chronos_gate/filters/none_filter.py
  • codecov.yml
  • intents.yaml
  • src/chronos_gate/main.py
  • tests/unit/test_chronos_gate_evaluator_settings.py
  • tests/unit/test_approval_registry.py
  • tests/unit/test_chronos_gate_llm_evaluator.py
  • src/chronos_gate/config.py
  • tests/unit/test_chronos_gate_evaluator_models.py
  • src/chronos_gate/policy/engine.py
  • src/chronos_gate/approval/registry.py
  • src/chronos_gate/policy/models.py
  • src/chronos_gate/cli.py
  • src/chronos_gate/policy/memory_client.py
  • .opencode/plugins/chronos-gate.js
  • src/chronos_gate/approval/notifier.py
  • src/chronos_gate/audit/logger.py
  • tests/integration/test_phase2_timeout_integration.py
  • src/chronos_gate/policy/llm_evaluator.py
  • tests/unit/test_chronos_gate_composite.py
  • src/chronos_gate/server.py

@yohi

yohi commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai ignore

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
✅ Action performed

Reviews paused.

Comment thread .github/workflows/sonarcloud.yml Fixed
Comment thread .github/workflows/sonarcloud.yml Fixed
@sonarqubecloud

Copy link
Copy Markdown

@yohi
yohi merged commit 6765fba into master Jun 20, 2026
10 checks passed
@yohi
yohi deleted the feature/separate-gate branch June 20, 2026 05:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants