docs(platform): add policy configs, runbooks, ops scripts and platform documentation
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
This commit is contained in:
277
docs/tools/governance.md
Normal file
277
docs/tools/governance.md
Normal file
@@ -0,0 +1,277 @@
|
||||
# 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`)
|
||||
|
||||
```yaml
|
||||
# Групи 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` у конфігу розгортається рекурсивно. Підтримуються вкладені групи:
|
||||
|
||||
```yaml
|
||||
my_super_group:
|
||||
- "@cto_tools"
|
||||
- "@media_tools"
|
||||
- custom_tool
|
||||
```
|
||||
|
||||
### 1.5 Як перевірити tools агента
|
||||
|
||||
```python
|
||||
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`)
|
||||
|
||||
```yaml
|
||||
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 Перевірка вручну
|
||||
|
||||
```python
|
||||
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` | Паралельних викликів |
|
||||
|
||||
Приклад:
|
||||
```yaml
|
||||
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:
|
||||
|
||||
```python
|
||||
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:
|
||||
|
||||
```json
|
||||
{
|
||||
"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`
|
||||
|
||||
```python
|
||||
# В 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
|
||||
|
||||
```python
|
||||
# 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 тест проходить
|
||||
Reference in New Issue
Block a user