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
9.7 KiB
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 — статичний аналіз файлів
{
"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— оптимізовано для CIfull: всі розширення з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 |
Відповідь:
{
"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-стріму
{
"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-механізмів
{
"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 — поточні політики
{ "action": "policy" }
Повертає конфіг config/data_governance_policy.yml: retention, pii_patterns, logging_rules, severity_behavior.
Evidence masking
Всі evidence snippets маскуються перед поверненням:
- Через
redact()зtool_governance(успадковані_SECRET_PATTERNS) - Truncate до 200 символів
- Ніяких raw значень у відповіді
Інтеграція в release_check (privacy_watch gate)
privacy_watch — warning-only gate: завжди pass=true, додає рекомендації.
# 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:
{
"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
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
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
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 |
Наступні кроки
strictmode — увімкнути дляcredit_card+private_key(блокувати реліз)- AST-based analysis — замість regex: точніший аналіз Python AST для logging calls
- Git history scan — перевіряти, чи не були secrets раніше в git history
- GDPR retention report — автоматичний звіт для DPO про час зберігання PII по системах
- Integration з incident_triage — DG findings у RCA якщо є privacy-related incident