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:
Apple
2026-03-03 07:14:53 -08:00
parent 129e4ea1fc
commit 67225a39fa
102 changed files with 20060 additions and 0 deletions

View File

@@ -0,0 +1,275 @@
# data_governance_tool — Data Governance & Privacy
**Категорія:** Security / Privacy / Compliance
**RBAC:** `tools.data_gov.read` (scan_repo, scan_audit, retention_check, policy), `tools.data_gov.gate` (gate)
**Ролі:** `agent_cto` (read + gate), `agent_oncall` (read)
**Timeout:** 30 s
**Rate limit:** 5 rpm
---
## Призначення
`data_governance_tool` — детермінований, read-only сканер для виявлення:
- **PII в коді/доках** (email, телефон, кредитні картки, паспорти)
- **Хардкоджених секретів** (API keys, private keys, токени)
- **Ризиків логування** (sensitive fields у logger calls, raw payload в audit records)
- **Відсутності retention/TTL** при збереженні даних
- **Аномалій в audit-стрімі** (PII у metadata, аномально великі outputs)
- **Наявності cleanup-механізмів** (task_registry.yml, runbooks)
**Перший рівень — warning-only**: gate `privacy_watch` завжди `pass=True`, але генерує конкретні рекомендації.
---
## Actions
### `scan_repo` — статичний аналіз файлів
```json
{
"action": "scan_repo",
"mode": "fast",
"max_files": 200,
"paths_include": ["services/", "config/", "ops/"],
"paths_exclude": ["**/node_modules/**", "**/*.lock"],
"focus": ["pii", "secrets", "logging", "retention"]
}
```
**Режими:**
- `fast` (default): `.py`, `.yml`, `.yaml`, `.json`, `.sh` — оптимізовано для CI
- `full`: всі розширення з `config/data_governance_policy.yml`
**Категорії перевірок:**
| ID | Категорія | Severity | Опис |
|----|-----------|----------|------|
| `DG-PII-001` | pii | warning | Email address |
| `DG-PII-002` | pii | warning | Phone number |
| `DG-PII-003` | pii | **error** | Credit card |
| `DG-PII-004` | pii | warning | Passport-like ID |
| `DG-SEC-000` | secrets | **error** | Secret value (inherited from governance) |
| `DG-SEC-001` | secrets | **error** | Private key block |
| `DG-LOG-001` | logging | warning | Sensitive field in logger call |
| `DG-AUD-001` | logging | **error** | Raw payload near audit/log write |
| `DG-RET-001` | retention | warning | Storage write без TTL/retention |
**Відповідь:**
```json
{
"pass": true,
"summary": "Scanned 87 files (fast mode). Found 0 errors, 3 warnings, 1 info.",
"stats": { "errors": 0, "warnings": 3, "infos": 1, "files_scanned": 87 },
"findings": [
{
"id": "DG-LOG-001",
"category": "logging",
"severity": "warning",
"title": "Potential sensitive field logged in auth.py",
"evidence": { "path": "services/router/auth.py", "lines": "L42-L46", "details": "token=***REDACTED***" },
"recommended_fix": "Apply redact() before logging. Log hash+last4 for identifiers."
}
],
"recommendations": ["Review logger calls for sensitive fields. Apply redact()..."]
}
```
---
### `scan_audit` — аналіз audit-стріму
```json
{
"action": "scan_audit",
"backend": "jsonl",
"time_window_hours": 24,
"max_events": 50000
}
```
**Перевірки:**
| ID | Опис |
|----|------|
| `DG-AUD-101` | PII-like pattern в полях метадата audit event (user_id, workspace_id) |
| `DG-AUD-102` | Аномально великий `out_size` (>64KB за замовчуванням) |
---
### `retention_check` — перевірка cleanup-механізмів
```json
{
"action": "retention_check",
"check_audit_cleanup_task": true,
"check_jsonl_rotation": true,
"check_memory_retention_docs": true,
"check_logs_retention_docs": true
}
```
| ID | Severity | Опис |
|----|----------|------|
| `DG-RET-201` | warning | Не знайдено cleanup task або runbook для audit |
| `DG-RET-202` | info | Cleanup/rotation задокументовано |
| `DG-RET-203` | info | JSONL rotation реалізовано |
| `DG-RET-204` | warning | JSONL rotation не підтверджено |
| `DG-RET-205` | info | Memory retention policy не знайдено |
| `DG-RET-206` | info | Log retention не задокументовано |
---
### `policy` — поточні політики
```json
{ "action": "policy" }
```
Повертає конфіг `config/data_governance_policy.yml`: retention, pii_patterns, logging_rules, severity_behavior.
---
## Evidence masking
**Всі evidence snippets маскуються** перед поверненням:
1. Через `redact()` з `tool_governance` (успадковані `_SECRET_PATTERNS`)
2. Truncate до 200 символів
3. Ніяких raw значень у відповіді
---
## Інтеграція в release_check (privacy_watch gate)
`privacy_watch`**warning-only gate**: завжди `pass=true`, додає рекомендації.
```yaml
# ops/task_registry.yml (release_check inputs)
run_privacy_watch: true # вмикає gate (default: true)
privacy_watch_mode: "fast" # fast|full
privacy_audit_window_hours: 24 # вікно для scan_audit
```
**Gate output:**
```json
{
"name": "privacy_watch",
"status": "pass",
"errors": 0,
"warnings": 2,
"infos": 1,
"top_findings": [
{ "id": "DG-LOG-001", "title": "...", "severity": "warning" }
],
"note": "3 finding(s): 0 error(s), 2 warning(s)",
"recommendations": ["Review logger calls for sensitive fields."]
}
```
Якщо `data_governance_tool` недоступний → `skipped: true`, реліз не блокується.
---
## Конфігурація: `config/data_governance_policy.yml`
```yaml
retention:
audit_jsonl_days: 30
audit_postgres_days: 90
large_output_bytes: 65536 # threshold для DG-AUD-102
pii_patterns:
email: { severity: "warning", ... }
credit_card: { severity: "error", ... }
logging_rules:
forbid_logging_fields: [password, token, secret, api_key, ...]
raw_payload_indicators: [payload, prompt, messages, transcript, ...]
redaction_calls: [redact, mask, sanitize, ...]
severity_behavior:
gate_mode: "warning_only" # або "strict" (блокує на error)
```
---
## RBAC
```yaml
data_governance_tool:
actions:
scan_repo: { entitlements: ["tools.data_gov.read"] }
scan_audit: { entitlements: ["tools.data_gov.read"] }
retention_check: { entitlements: ["tools.data_gov.read"] }
policy: { entitlements: ["tools.data_gov.read"] }
gate: { entitlements: ["tools.data_gov.gate"] }
role_entitlements:
agent_cto: [..., tools.data_gov.read, tools.data_gov.gate]
agent_oncall: [..., tools.data_gov.read]
```
---
## Limits
```yaml
data_governance_tool:
timeout_ms: 30000 # 30s (file I/O + regex)
max_chars_in: 3000 # params only
max_bytes_out: 1MB
rate_limit_rpm: 5
concurrency: 1 # serial (filesystem-bound)
```
---
## Security
- **Read-only**: ніяких записів, змін, видалень
- **Path traversal protection**: всі шляхи перевіряються проти `repo_root`
- **Evidence masking**: `redact()` + truncation — raw secrets ніколи не повертаються
- **Never-scan list**: `.env`, `.pem`, `.key` файли не читаються
- **Lock files excluded** (за замовчуванням): `*.lock` — запобігає false positives від hash-рядків у lock-файлах
---
## Тести
`tests/test_data_governance.py` (22 тести):
| Тест | Перевірка |
|------|-----------|
| `test_scan_repo_detects_pii_logging` | Email у logger call → DG-PII-001 |
| `test_scan_repo_detects_logging_forbidden_field` | `token=` у logger → DG-LOG-001 |
| `test_scan_repo_detects_secret` | Hardcoded API key → DG-SEC-000, masked |
| `test_scan_repo_detects_private_key` | `-----BEGIN RSA PRIVATE KEY-----` → error |
| `test_scan_repo_detects_credit_card` | 16-digit number → DG-PII-003 error |
| `test_scan_repo_no_findings_clean` | Clean code → 0 error findings |
| `test_scan_audit_detects_pii_in_meta` | Email у user_id → DG-AUD-101 |
| `test_scan_audit_detects_large_output` | 200KB out_size → DG-AUD-102 |
| `test_scan_audit_no_findings_for_clean_events` | Normal events → 0 findings |
| `test_retention_check_missing_cleanup` | No runbook → DG-RET-201 |
| `test_retention_check_with_cleanup` | Runbook mentions cleanup → DG-RET-202 |
| `test_scan_repo_raw_payload_audit_write` | `payload` near logger → DG-AUD-001 |
| `test_release_check_privacy_watch_integration` | Gate pass=True, adds recs |
| `test_privacy_watch_skipped_on_tool_error` | Tool exception → skipped=True |
| `test_rbac_deny` | alateya (agent_media) → denied |
| `test_rbac_allow` | sofiia (agent_cto) → allowed |
| `test_policy_action` | Returns structured policy |
| `test_path_traversal_protection` | `../../etc/passwd` → None |
| `test_scan_repo_excludes_lock_files` | `*.lock` excluded |
| `test_mask_evidence_redacts_secrets` | key=value → masked |
| `test_mask_evidence_truncates` | 500 chars → ≤120 |
| `test_unknown_action_returns_error` | Invalid action → error dict |
---
## Наступні кроки
1. **`strict` mode** — увімкнути для `credit_card` + `private_key` (блокувати реліз)
2. **AST-based analysis** — замість regex: точніший аналіз Python AST для logging calls
3. **Git history scan** — перевіряти, чи не були secrets раніше в git history
4. **GDPR retention report** — автоматичний звіт для DPO про час зберігання PII по системах
5. **Integration з incident_triage** — DG findings у RCA якщо є privacy-related incident