Config policies (16 files): alert_routing, architecture_pressure, backlog, cost_weights, data_governance, incident_escalation, incident_intelligence, network_allowlist, nodes_registry, observability_sources, rbac_tools_matrix, release_gate, risk_attribution, risk_policy, slo_policy, tool_limits, tools_rollout Ops (22 files): Caddyfile, calendar compose, grafana voice dashboard, deployments/incidents logs, runbooks for alerts/audit/backlog/incidents/sofiia/voice, cron jobs, scripts (alert_triage, audit_cleanup, migrate_*, governance, schedule), task_registry, voice alerts/ha/latency/policy Docs (30+ files): HUMANIZED_STEPAN v2.7-v3 changelogs and runbooks, NODA1/NODA2 status and setup, audit index and traces, backlog, incident, supervisor, tools, voice, opencode, release, risk, aistalk, spacebot Made-with: Cursor
7.9 KiB
Tool Governance
Система керування інструментами DAARION.city
Версія: 2.0 | Нода: NODE2 (розробка) + NODA1 (production)
Огляд
Tool Governance — єдина система контролю над усіма tool-викликами агентів.
Складається з чотирьох компонентів:
| Компонент | Файл | Що робить |
|---|---|---|
| Rollout Policy | config/tools_rollout.yml |
Визначає, які tools отримує кожен агент за роллю |
| RBAC Matrix | config/rbac_tools_matrix.yml |
Матриця tool → action → entitlement → role |
| Safety Middleware | services/router/tool_governance.py |
Limits, redaction, allowlist, audit |
| Release Gate | ops/task_registry.yml + services/router/release_check_runner.py |
Єдиний release verdict |
1. Global Tools Rollout
1.1 Merge Policy
effective_tools = unique(DEFAULT_TOOLS_BY_ROLE ∪ FULL_STANDARD_STACK ∪ agent.specialized_tools)
Кожен агент автоматично отримує набір tools відповідно до ролі — без необхідності явно вказувати їх.
1.2 Конфіг (config/tools_rollout.yml)
# Групи tools
default_tools_read:
- repo_tool
- kb_tool
- oncall_tool
- observability_tool
...
cto_tools:
- pr_reviewer_tool
- contract_tool
- config_linter_tool
- threatmodel_tool
- job_orchestrator_tool
# Ролі → групи
role_map:
agent_default:
tools: ["@default_tools_read", "@content_tools"]
agent_cto:
tools: ["@default_tools_read", "@cto_tools", "@content_tools", "@media_tools"]
agent_oncall:
tools: ["@default_tools_read", "job_orchestrator_tool"]
# Агент → роль
agent_roles:
sofiia: agent_cto
helion: agent_oncall
alateya: agent_media
1.3 Ролі
| Роль | Хто | Набір |
|---|---|---|
agent_cto |
sofiia, yaromir | Все: read + cto + content + media |
agent_oncall |
helion | Read + job_orchestrator |
agent_media |
alateya, nutra, agromatrix, greenfood... | Read + content + media |
agent_default |
всі інші / нові агенти | Read + content |
1.4 Розширення груп (@group)
@group_name у конфігу розгортається рекурсивно. Підтримуються вкладені групи:
my_super_group:
- "@cto_tools"
- "@media_tools"
- custom_tool
1.5 Як перевірити tools агента
from agent_tools_config import get_agent_tools, get_agent_role
tools = get_agent_tools("sofiia") # → список всіх tools
role = get_agent_role("sofiia") # → "agent_cto"
Acceptance: новий агент без явного tools отримує read-набір автоматично.
2. RBAC Matrix
2.1 Структура (config/rbac_tools_matrix.yml)
tools:
pr_reviewer_tool:
actions:
review:
entitlements: ["tools.pr_review.use"]
gate:
entitlements: ["tools.pr_review.gate"]
role_entitlements:
agent_cto:
- tools.pr_review.use
- tools.pr_review.gate
...
agent_default:
- tools.repo.read
- tools.kb.read
...
2.2 Enforcement Flow
execute_tool(tool, action, agent_id)
→ get_agent_role(agent_id) → "agent_cto"
→ get_role_entitlements(role) → ["tools.pr_review.use", ...]
→ get_required_entitlements(tool, action) → ["tools.pr_review.gate"]
→ missing = required - agent_ents
→ if missing: DENY
2.3 Entitlement схема
tools.<tool_short>.<scope>
Приклади:
tools.repo.read
tools.oncall.incident_write
tools.pr_review.gate
tools.jobs.run.deploy
2.4 Перевірка вручну
from tool_governance import check_rbac
ok, reason = check_rbac("sofiia", "pr_reviewer_tool", "gate")
# → (True, "")
ok, reason = check_rbac("helion", "pr_reviewer_tool", "gate")
# → (False, "Missing entitlements: ['tools.pr_review.gate']")
Acceptance: всі tool handlers використовують матрицю — жодного хардкоду прав у коді.
3. Tool Safety Middleware
Реалізовано у services/router/tool_governance.py.
Застосовується автоматично до кожного execute_tool(...) виклику.
3.1 Limits (config/tool_limits.yml)
| Параметр | Опис |
|---|---|
timeout_ms |
Максимальний час виконання |
max_chars_in |
Максимальна довжина вхідного тексту |
max_bytes_out |
Максимальний розмір відповіді |
rate_limit_rpm |
Запитів на хвилину |
concurrency |
Паралельних викликів |
Приклад:
pr_reviewer_tool:
timeout_ms: 60000 # 60s
max_chars_in: 409600 # 400KB
rate_limit_rpm: 10
3.2 Redaction
Модуль redact(text) у tool_governance.py маскує:
- API ключі (
api_key=***REDACTED***) - Токени (
token=***REDACTED***) - Паролі (
password=***REDACTED***) - Bearer tokens, JWT, OAuth secrets, private keys
Застосовується до:
- Evidence/snippets у результатах pr_reviewer_tool
- Evidence у config_linter_tool
- Log lines у observability_tool
Включено за замовчуванням. Вимкнути: ToolGovernance(enable_redaction=False).
3.3 Network Allowlist (config/network_allowlist.yml)
Tools, що роблять HTTP-запити, обмежені allowlist:
from tool_governance import check_url_allowed
ok, reason = check_url_allowed("oncall_tool", "http://localhost:9102/health")
# → (True, "")
ok, reason = check_url_allowed("oncall_tool", "http://evil.com/steal")
# → (False, "Host 'evil.com' not in allowlist for tool 'oncall_tool'")
web_extract та crawl4ai_scrape мають allow_any_public: true але блокують private IPs (RFC1918/loopback).
3.4 Audit Events
На кожен tool-виклик емітується structured event у log:
{
"ts": "2026-02-23T12:00:00Z",
"req_id": "abc123def456",
"tool": "pr_reviewer_tool",
"action": "review",
"workspace_id": "default",
"user_id": "user_123",
"agent_id": "sofiia",
"status": "pass",
"duration_ms": 234.5,
"limits_applied": {"timeout_ms": 60000, "max_chars_in": 409600},
"input_hash": "a1b2c3d4e5f6",
"input_chars": 1024,
"output_size_bytes": 2048
}
Payload не логується — тільки hash та розміри.
Log prefix: TOOL_AUDIT.
3.5 Integration у execute_tool
# В tool_manager.py, автоматично:
governance = get_governance()
pre = governance.pre_call(tool, action, agent_id, user_id, workspace_id, input_text)
if not pre.allowed:
return ToolResult(success=False, error=pre.reason)
result = await _handler(args) # actual tool execution
governance.post_call(pre.call_ctx, result.result, error=result.error)
4. Налаштування та Hot-Reload
# Force reload конфігів (без перезапуску)
from agent_tools_config import reload_rollout_config
from tool_governance import _reload_yaml_cache
reload_rollout_config()
_reload_yaml_cache()
5. Acceptance Criteria
- ✅ Новий агент без явного
toolsотримує read-набір автоматично - ✅ Sofiia/CTO має повний набір через роль
agent_cto - ✅ Будь-який tool call проходить через middleware (limits/redaction/audit)
- ✅ RBAC денить без entitlement, без хардкоду в коді
- ✅ Allowlist блокує довільні URL для HTTP-tools
- ✅ 31/31 тест проходить