feat(B-SENS): Sensitive Data Boundary + AI/Data Exposure Policy + AIProvider Compliance
Check Cross-Plugin Imports / check (push) Has been cancelled

B-SENS: app/core/sensitive_data.py (NEU) — zentrale Sensitive-Field-Verwaltung
- SENSITIVE_FIELDS dict für contact/user/mail_account/system_settings
- is_sensitive(), sanitize_dict(), register_sensitive_fields()
- Integration: errors.py (Log-Redaction), audit.py (Audit-Masking), export_service.py (Export-Filter), embedding.py (Index-Filter)

B-DATA-POL: AI/Data Exposure Policy
- DATA_EXPOSURE_POLICY: pro Entity+Field welche Systeme erlaubt (llm_context/search/embeddings/rag/agent_memory/export)
- filter_for_llm_context/search/embeddings/export/rag/agent_memory()

B-AIPROV-COMP: AIProvider Compliance Metadata
- Migration 0119: 7 neue Spalten an ai_providers (region, hosting_type, dpa_status, retention_policy, training_on_customer_data, transfer_notice, allowed_data_classes)
- llm_client.py: get_provider_compliance() + check_data_class_allowed()

B-PRIV-TEST: 76 Tests in test_sensitive_data.py — alle grün
- Sensitive Fields, Exposure Policy, Provider Compliance, Secrets-always-blocked
- Keine Regression: 39 LLM-Client Tests grün
This commit is contained in:
Agent Zero
2026-08-13 20:39:32 +02:00
parent bb36378494
commit b231c2d0d3
10 changed files with 939 additions and 15 deletions
+27 -2
View File
@@ -31,7 +31,12 @@ _SENSITIVE_PATTERNS = re.compile(
def _sanitize_context(context: Any, max_depth: int = 3, _depth: int = 0) -> Any:
"""Recursively remove sensitive keys and limit depth/size of context data."""
"""Recursively remove sensitive keys and limit depth/size of context data.
Combines regex-based pattern matching with the central
:mod:`app.core.sensitive_data` module to ensure entity-specific
sensitive fields are also redacted.
"""
if _depth > max_depth:
return "[truncated]"
if isinstance(context, dict):
@@ -49,6 +54,23 @@ def _sanitize_context(context: Any, max_depth: int = 3, _depth: int = 0) -> Any:
return context
def _sanitize_entity_context(context: dict[str, Any]) -> dict[str, Any]:
"""Sanitize context dict using both pattern matching and entity-aware redaction.
If the context contains an ``entity_type`` key, uses :func:`sanitize_dict`
from :mod:`app.core.sensitive_data` to redact entity-specific sensitive
fields. Falls back to pattern-based sanitization otherwise.
"""
from app.core.sensitive_data import sanitize_dict
entity_type = context.get("entity_type") or context.get("type")
if entity_type:
sanitized = sanitize_dict(context, str(entity_type))
else:
sanitized = dict(context)
return _sanitize_context(sanitized)
# -- Request schema --
class ErrorReport(BaseModel):
@@ -77,7 +99,10 @@ async def report_error(error: ErrorReport, request: Request) -> Response:
return Response(status_code=status.HTTP_429_TOO_MANY_REQUESTS)
# Sanitize context to prevent leaking sensitive data
sanitized_context = _sanitize_context(error.context) if error.context else None
if error.context:
sanitized_context = _sanitize_entity_context(error.context)
else:
sanitized_context = None
# Log with structured info
logger.error(