mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-06-19 07:49:34 +00:00
194 lines
5.7 KiB
Python
194 lines
5.7 KiB
Python
"""
|
|
Vendor / Subprocessor registry — PDPL Article on subprocessors.
|
|
|
|
Every external service that touches data must be registered + assessed.
|
|
Required for SDAIA / DPO inspection. Maintains vendor risk tier + DPA status.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import uuid
|
|
from dataclasses import dataclass, field
|
|
from datetime import datetime, timezone
|
|
from typing import Any
|
|
|
|
|
|
class VendorStatus:
|
|
APPROVED = "approved"
|
|
PENDING_DPA = "pending_dpa"
|
|
PENDING_REVIEW = "pending_review"
|
|
SUSPENDED = "suspended"
|
|
|
|
|
|
@dataclass
|
|
class Vendor:
|
|
vendor_id: str
|
|
name: str
|
|
purpose_ar: str
|
|
data_accessed: list[str] # types of data
|
|
region: str # SA / GCC / US / EU / Global
|
|
has_dpa_signed: bool = False
|
|
iso27001: bool = False
|
|
soc2: bool = False
|
|
risk_tier: str = "medium" # low / medium / high
|
|
status: str = VendorStatus.PENDING_REVIEW
|
|
contact_email: str | None = None
|
|
onboarded_at: datetime | None = None
|
|
|
|
|
|
# ── Default vendor registry — services Dealix uses ───────────────
|
|
DEFAULT_VENDORS: tuple[Vendor, ...] = (
|
|
Vendor(
|
|
vendor_id="anthropic",
|
|
name="Anthropic (Claude)",
|
|
purpose_ar="LLM للتصنيف والتلخيص — لا يستخدم البيانات للتدريب",
|
|
data_accessed=["communication_content_redacted"],
|
|
region="US",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=True,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="groq",
|
|
name="Groq",
|
|
purpose_ar="Inference سريع لتصنيف الردود",
|
|
data_accessed=["communication_content_redacted"],
|
|
region="US",
|
|
has_dpa_signed=True,
|
|
iso27001=False,
|
|
soc2=True,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="green_api",
|
|
name="Green API",
|
|
purpose_ar="WhatsApp gateway provider",
|
|
data_accessed=["business_contact_phone"],
|
|
region="Global",
|
|
has_dpa_signed=True,
|
|
iso27001=False,
|
|
soc2=False,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="ultramsg",
|
|
name="Ultramsg",
|
|
purpose_ar="WhatsApp gateway fallback",
|
|
data_accessed=["business_contact_phone"],
|
|
region="Global",
|
|
has_dpa_signed=True,
|
|
iso27001=False,
|
|
soc2=False,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="meta_whatsapp_cloud",
|
|
name="Meta WhatsApp Business Cloud API",
|
|
purpose_ar="Official WhatsApp Business sender",
|
|
data_accessed=["business_contact_phone"],
|
|
region="Global",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=True,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="gmail_oauth",
|
|
name="Gmail (Google Workspace OAuth)",
|
|
purpose_ar="إرسال إيميل تجاري via customer's own account",
|
|
data_accessed=["business_contact_email"],
|
|
region="Global",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=True,
|
|
risk_tier="low",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="moyasar",
|
|
name="Moyasar",
|
|
purpose_ar="Saudi payment gateway للـ billing",
|
|
data_accessed=["billing_metadata"],
|
|
region="SA",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=False,
|
|
risk_tier="low",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="apollo",
|
|
name="Apollo.io",
|
|
purpose_ar="Lead enrichment provider",
|
|
data_accessed=["business_contact"],
|
|
region="US",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=True,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="zoominfo",
|
|
name="ZoomInfo",
|
|
purpose_ar="Lead enrichment alternative",
|
|
data_accessed=["business_contact"],
|
|
region="US",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=True,
|
|
risk_tier="medium",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
Vendor(
|
|
vendor_id="railway",
|
|
name="Railway (hosting)",
|
|
purpose_ar="Application hosting (data hosted in same region as customer)",
|
|
data_accessed=["all"],
|
|
region="Global",
|
|
has_dpa_signed=True,
|
|
iso27001=True,
|
|
soc2=True,
|
|
risk_tier="high",
|
|
status=VendorStatus.APPROVED,
|
|
),
|
|
)
|
|
|
|
|
|
def register_vendor(vendor: Vendor) -> Vendor:
|
|
"""Add a custom vendor to the registry — assigns onboarded_at."""
|
|
if not vendor.vendor_id:
|
|
vendor.vendor_id = f"vnd_{uuid.uuid4().hex[:16]}"
|
|
if vendor.onboarded_at is None:
|
|
vendor.onboarded_at = datetime.now(timezone.utc).replace(tzinfo=None)
|
|
return vendor
|
|
|
|
|
|
def vendors_summary(vendors: tuple[Vendor, ...] | None = None) -> dict[str, Any]:
|
|
"""Aggregate counts for the Trust Center vendor tile."""
|
|
pool = vendors or DEFAULT_VENDORS
|
|
by_status: dict[str, int] = {}
|
|
by_tier: dict[str, int] = {}
|
|
by_region: dict[str, int] = {}
|
|
n_with_dpa = 0
|
|
for v in pool:
|
|
by_status[v.status] = by_status.get(v.status, 0) + 1
|
|
by_tier[v.risk_tier] = by_tier.get(v.risk_tier, 0) + 1
|
|
by_region[v.region] = by_region.get(v.region, 0) + 1
|
|
if v.has_dpa_signed:
|
|
n_with_dpa += 1
|
|
return {
|
|
"total": len(pool),
|
|
"with_dpa": n_with_dpa,
|
|
"dpa_coverage_pct": round(n_with_dpa / len(pool) * 100, 1) if pool else 0,
|
|
"by_status": by_status,
|
|
"by_risk_tier": by_tier,
|
|
"by_region": by_region,
|
|
}
|