feat(platform): add new services, tools, tests and crews modules
New router intelligence modules (26 files): alert_ingest/store, audit_store, architecture_pressure, backlog_generator/store, cost_analyzer, data_governance, dependency_scanner, drift_analyzer, incident_* (5 files), llm_enrichment, platform_priority_digest, provider_budget, release_check_runner, risk_* (6 files), signature_state_store, sofiia_auto_router, tool_governance New services: - sofiia-console: Dockerfile, adapters/, monitor/nodes/ops/voice modules, launchd, react static - memory-service: integration_endpoints, integrations, voice_endpoints, static UI - aurora-service: full app suite (analysis, job_store, orchestrator, reporting, schemas, subagents) - sofiia-supervisor: new supervisor service - aistalk-bridge-lite: Telegram bridge lite - calendar-service: CalDAV calendar service with reminders - mlx-stt-service / mlx-tts-service: Apple Silicon speech services - binance-bot-monitor: market monitor service - node-worker: STT/TTS memory providers New tools (9): agent_email, browser_tool, contract_tool, observability_tool, oncall_tool, pr_reviewer_tool, repo_tool, safe_code_executor, secure_vault New crews: agromatrix_crew (10 modules: depth_classifier, doc_facts, doc_focus, farm_state, light_reply, llm_factory, memory_manager, proactivity, reflection_engine, session_context, style_adapter, telemetry) Tests: 85+ test files for all new modules Made-with: Cursor
This commit is contained in:
413
tests/test_config_linter_tool.py
Normal file
413
tests/test_config_linter_tool.py
Normal file
@@ -0,0 +1,413 @@
|
||||
"""
|
||||
Tests for Config Linter Tool
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
from services.router.tool_manager import ToolManager, ToolResult
|
||||
|
||||
|
||||
class TestConfigLinterTool:
|
||||
"""Test config linter tool functionality"""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_detect_api_key_in_diff(self):
|
||||
"""Test that API keys in diff are detected as blocking"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/api.yaml b/config/api.yaml
|
||||
--- a/config/api.yaml
|
||||
+++ b/config/api.yaml
|
||||
@@ -1,3 +1,4 @@
|
||||
api:
|
||||
- url: https://api.example.com
|
||||
+ url: https://api.example.com
|
||||
+ api_key: sk-1234567890abcdefghijklmnop
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
},
|
||||
"options": {
|
||||
"mask_evidence": True
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
assert result.result is not None
|
||||
assert result.result["stats"]["blocking_count"] > 0
|
||||
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-003" in blocking_ids or "CFL-006" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_detect_private_key_blocking(self):
|
||||
"""Test that private keys are detected as blocking"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/keys/service.key b/keys/service.key
|
||||
--- /dev/null
|
||||
+++ b/keys/service.key
|
||||
@@ -0,0 +1,4 @@
|
||||
+-----BEGIN RSA PRIVATE KEY-----
|
||||
+MIIEpAIBAAKCAQEA0Z3VsF3r...
|
||||
+-----END RSA PRIVATE KEY-----
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-001" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_detect_debug_true(self):
|
||||
"""Test DEBUG=true is detected"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/app.yml b/config/app.yml
|
||||
--- a/config/app.yml
|
||||
+++ b/config/app.yml
|
||||
@@ -1,2 +1,3 @@
|
||||
app:
|
||||
- name: myapp
|
||||
+ name: myapp
|
||||
+ debug: true
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-101" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_detect_cors_wildcard(self):
|
||||
"""Test CORS wildcard is detected"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/cors.yaml b/config/cors.yaml
|
||||
--- a/config/cors.yaml
|
||||
+++ b/config/cors.yaml
|
||||
@@ -1,2 +1,3 @@
|
||||
cors:
|
||||
- allowed_origins:
|
||||
+ allowed_origins:
|
||||
+ - "*"
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-103" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_detect_auth_bypass(self):
|
||||
"""Test auth bypass is detected"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/auth.yaml b/config/auth.yaml
|
||||
--- a/config/auth.yaml
|
||||
+++ b/config/auth.yaml
|
||||
@@ -1,2 +1,3 @@
|
||||
auth:
|
||||
- enabled: true
|
||||
+ enabled: true
|
||||
+ skip_auth: true
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-104" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_detect_docker_compose_privileged(self):
|
||||
"""Test privileged container in docker-compose is detected"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/docker-compose.yml b/docker-compose.yml
|
||||
--- a/docker-compose.yml
|
||||
+++ b/docker-compose.yml
|
||||
@@ -1,3 +1,5 @@
|
||||
services:
|
||||
app:
|
||||
- image: myapp:latest
|
||||
+ image: myapp:latest
|
||||
+ privileged: true
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
finding_ids = [f["id"] for f in result.result["blocking"] + result.result["findings"]]
|
||||
assert "CFL-302" in finding_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_evidence_is_masked(self):
|
||||
"""Test that evidence is masked when mask_evidence=true"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/.env b/.env
|
||||
--- a/.env
|
||||
+++ b/.env
|
||||
@@ -1,2 +1,3 @@
|
||||
DATABASE_URL=postgres://localhost
|
||||
+API_KEY=sk-secret123456789
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
},
|
||||
"options": {
|
||||
"mask_evidence": True
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
for finding in result.result["blocking"]:
|
||||
assert "sk-s*" in finding["evidence"] or "***" in finding["evidence"]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_path_traversal_blocked(self):
|
||||
"""Test that path traversal attempts are blocked"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "paths",
|
||||
"paths": ["../../../etc/passwd", "config/app.yml"]
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-999" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_strict_mode_fails_on_medium(self):
|
||||
"""Test that strict mode converts medium to blocking"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/app.yml b/config/app.yml
|
||||
--- a/config/app.yml
|
||||
+++ b/config/app.yml
|
||||
@@ -1,2 +1,3 @@
|
||||
app:
|
||||
- name: myapp
|
||||
+ name: myapp
|
||||
+ allowed_hosts: ["*"]
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
},
|
||||
"options": {
|
||||
"strict": True
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-106" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_max_chars_limit(self):
|
||||
"""Test that max_chars limit is enforced"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
large_diff = "a" * 500000
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": large_diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is False
|
||||
assert "max_chars" in result.error.lower()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_clean_diff_no_findings(self):
|
||||
"""Test that clean diff has no findings"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/README.md b/README.md
|
||||
--- a/README.md
|
||||
+++ b/README.md
|
||||
@@ -1,2 +1,3 @@
|
||||
# My Project
|
||||
+
|
||||
+New feature added
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
assert result.result["stats"]["blocking_count"] == 0
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_deterministic_ordering(self):
|
||||
"""Test that findings are in deterministic order"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/a.yml b/config/a.yml
|
||||
--- a/config/a.yml
|
||||
+++ b/config/a.yml
|
||||
@@ -1,3 +1,4 @@
|
||||
+debug: true
|
||||
+api_key: sk-test123
|
||||
+password: admin
|
||||
+auth_disabled: true
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert ids == sorted(ids)
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_github_token_detection(self):
|
||||
"""Test GitHub token detection"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/.env b/.env
|
||||
--- a/.env
|
||||
+++ b/.env
|
||||
@@ -1,2 +1,3 @@
|
||||
TOKEN=ghp_1234567890abcdefghijklmnopqrstuvwxyz
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-007" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_aws_key_detection(self):
|
||||
"""Test AWS key detection"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/aws.yaml b/config/aws.yaml
|
||||
--- a/config/aws.yaml
|
||||
+++ b/config/aws.yaml
|
||||
@@ -1,2 +1,3 @@
|
||||
aws:
|
||||
access_key: AKIAIOSFODNN7EXAMPLE
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-009" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_weak_password_detection(self):
|
||||
"""Test weak password detection"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/config/db.yaml b/config/db.yaml
|
||||
--- a/config/db.yaml
|
||||
+++ b/config/db.yaml
|
||||
@@ -1,2 +1,3 @@
|
||||
db:
|
||||
password: root
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
blocking_ids = [f["id"] for f in result.result["blocking"]]
|
||||
assert "CFL-011" in blocking_ids
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_container_root_user(self):
|
||||
"""Test container root user detection"""
|
||||
tool_mgr = ToolManager({})
|
||||
|
||||
diff = """diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml
|
||||
--- a/k8s/deployment.yaml
|
||||
+++ b/k8s/deployment.yaml
|
||||
@@ -1,3 +1,4 @@
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
+ user: root
|
||||
"""
|
||||
|
||||
result = await tool_mgr._config_linter_tool({
|
||||
"source": {
|
||||
"type": "diff_text",
|
||||
"diff_text": diff
|
||||
}
|
||||
})
|
||||
|
||||
assert result.success is True
|
||||
finding_ids = [f["id"] for f in result.result["blocking"] + result.result["findings"]]
|
||||
assert "CFL-301" in finding_ids
|
||||
Reference in New Issue
Block a user