system-prompts-and-models-o.../dealix/tests/unit/test_compliance_os.py
2026-05-01 14:03:52 +03:00

297 lines
9.7 KiB
Python

"""Smoke tests for Compliance OS v2."""
from __future__ import annotations
from datetime import datetime, timedelta, timezone
import pytest
from auto_client_acquisition.compliance_os.consent_ledger import (
ALL_BASES,
LawfulBasis,
latest_state,
record_consent,
record_opt_out,
)
from auto_client_acquisition.compliance_os.contactability import check_contactability
from auto_client_acquisition.compliance_os.data_subject_requests import (
DSR_TYPES,
DSRStatus,
SLA_DAYS,
dsr_dashboard,
is_overdue,
open_dsr,
process_dsr,
)
from auto_client_acquisition.compliance_os.risk_engine import score_campaign_risk
from auto_client_acquisition.compliance_os.ropa import (
DEFAULT_ACTIVITIES,
build_ropa,
)
from auto_client_acquisition.compliance_os.vendor_registry import (
DEFAULT_VENDORS,
Vendor,
VendorStatus,
register_vendor,
vendors_summary,
)
# ── Consent Ledger ───────────────────────────────────────────────
def test_lawful_basis_constants_known():
for b in (
LawfulBasis.CONSENT, LawfulBasis.LEGITIMATE_INTEREST,
LawfulBasis.CONTRACT, LawfulBasis.LEGAL_OBLIGATION,
):
assert b in ALL_BASES
def test_record_consent_validates_basis():
with pytest.raises(ValueError):
record_consent(customer_id="c", contact_id="x", lawful_basis="bogus", purpose="x")
def test_latest_state_no_records():
s = latest_state([])
assert s["has_consent"] is False
assert s["is_opted_out"] is False
def test_latest_state_after_consent():
rec = record_consent(
customer_id="c", contact_id="x",
lawful_basis=LawfulBasis.LEGITIMATE_INTEREST,
purpose="b2b_outreach",
)
s = latest_state([rec])
assert s["has_consent"] is True
assert s["lawful_basis"] == LawfulBasis.LEGITIMATE_INTEREST
def test_opt_out_overrides_prior_consent():
rec1 = record_consent(
customer_id="c", contact_id="x",
lawful_basis=LawfulBasis.CONSENT, purpose="x",
occurred_at=datetime(2026, 1, 1),
)
rec2 = record_opt_out(customer_id="c", contact_id="x", occurred_at=datetime(2026, 2, 1))
s = latest_state([rec1, rec2])
assert s["is_opted_out"] is True
assert s["has_consent"] is False
def test_expired_consent_not_active():
rec = record_consent(
customer_id="c", contact_id="x",
lawful_basis=LawfulBasis.CONSENT, purpose="x",
expires_at=datetime(2020, 1, 1), # past
)
s = latest_state([rec])
assert s["has_consent"] is False
# ── Contactability ───────────────────────────────────────────────
def test_contactability_safe_with_consent():
rec = record_consent(
customer_id="c", contact_id="x",
lawful_basis=LawfulBasis.LEGITIMATE_INTEREST, purpose="x",
)
s = check_contactability(
contact_id="x", consent_records=[rec],
messages_sent_this_week=0, current_riyadh_hour=12,
)
assert s.can_contact is True
assert s.reason_code == "safe"
def test_contactability_blocks_opted_out():
rec = record_opt_out(customer_id="c", contact_id="x")
s = check_contactability(contact_id="x", consent_records=[rec])
assert s.can_contact is False
assert s.reason_code == "opted_out"
def test_contactability_blocks_no_consent():
s = check_contactability(contact_id="x", consent_records=[])
assert s.can_contact is False
assert s.reason_code == "no_consent"
def test_contactability_blocks_freq_cap():
rec = record_consent(
customer_id="c", contact_id="x",
lawful_basis=LawfulBasis.LEGITIMATE_INTEREST, purpose="x",
)
s = check_contactability(
contact_id="x", consent_records=[rec],
messages_sent_this_week=2, weekly_cap=2,
)
assert s.can_contact is False
assert s.reason_code == "freq_cap"
def test_contactability_blocks_quiet_hours():
rec = record_consent(
customer_id="c", contact_id="x",
lawful_basis=LawfulBasis.LEGITIMATE_INTEREST, purpose="x",
)
s = check_contactability(
contact_id="x", consent_records=[rec], current_riyadh_hour=23,
)
assert s.can_contact is False
assert s.reason_code == "quiet_hours"
# ── DSR ──────────────────────────────────────────────────────────
def test_dsr_types_known():
assert "access" in DSR_TYPES
assert "delete" in DSR_TYPES
def test_open_dsr_validates_type():
with pytest.raises(ValueError):
open_dsr(customer_id="c", data_subject_id="x", request_type="invalid")
def test_open_dsr_assigns_sla():
r = open_dsr(customer_id="c", data_subject_id="x", request_type="delete")
assert r.status == DSRStatus.OPEN
expected_due = r.received_at + timedelta(days=SLA_DAYS["delete"])
assert abs((r.sla_due_at - expected_due).total_seconds()) < 1
def test_process_dsr_completion():
r = open_dsr(customer_id="c", data_subject_id="x", request_type="access")
process_dsr(r, action_taken="completed", handled_by="dpo@x.sa", artifact_url="https://...")
assert r.status == DSRStatus.COMPLETED
assert r.completed_at is not None
assert r.artifacts.get("export_url") == "https://..."
def test_process_dsr_rejection_requires_reason():
r = open_dsr(customer_id="c", data_subject_id="x", request_type="object")
with pytest.raises(ValueError):
process_dsr(r, action_taken="rejected", handled_by="x")
process_dsr(r, action_taken="rejected", handled_by="x", rejection_reason="duplicate")
assert r.status == DSRStatus.REJECTED
def test_dsr_overdue_detection():
r = open_dsr(
customer_id="c", data_subject_id="x", request_type="access",
received_at=datetime(2025, 1, 1),
)
assert is_overdue(r, now=datetime(2026, 1, 1)) is True
def test_dsr_dashboard():
rs = [
open_dsr(customer_id="c", data_subject_id="a", request_type="access"),
open_dsr(customer_id="c", data_subject_id="b", request_type="delete"),
]
process_dsr(rs[0], action_taken="completed", handled_by="x", artifact_url="...")
d = dsr_dashboard(rs)
assert d["n_total"] == 2
assert d["by_status"][DSRStatus.COMPLETED] == 1
# ── Risk Engine ──────────────────────────────────────────────────
def test_clean_campaign_is_safe():
r = score_campaign_risk(
target_count=100,
contacts_with_consent=100,
contacts_opted_out=0,
contacts_no_lawful_basis=0,
template_body="مرحباً، نقدم حلول مبيعات B2B سعودية.",
template_subject="نموذج",
channel="email",
has_unsubscribe_link=True,
)
assert r.risk_band == "safe"
assert r.contacts_safe == 100
def test_risky_phrase_increases_score():
r = score_campaign_risk(
target_count=100, contacts_with_consent=100,
contacts_opted_out=0, contacts_no_lawful_basis=0,
template_body="عرض ضمان 100% نتائج مضمونة!",
)
assert r.risk_score > 30
def test_no_unsubscribe_blocks_email():
r = score_campaign_risk(
target_count=100, contacts_with_consent=100,
contacts_opted_out=0, contacts_no_lawful_basis=0,
template_body="x", channel="email", has_unsubscribe_link=False,
)
assert any("Unsubscribe" in b or "List" in b for b in r.blockers)
def test_pii_in_body_blocks():
r = score_campaign_risk(
target_count=100, contacts_with_consent=100,
contacts_opted_out=0, contacts_no_lawful_basis=0,
template_body="ارسل لنا رقم الهوية",
)
assert any("PII" in b or "حساسة" in b for b in r.blockers)
def test_low_safe_coverage_flags_issue():
r = score_campaign_risk(
target_count=100, contacts_with_consent=20,
contacts_opted_out=20, contacts_no_lawful_basis=60,
template_body="ok",
)
assert any("منخفضة" in i or "50%" in i for i in r.issues)
# ── RoPA ─────────────────────────────────────────────────────────
def test_default_ropa_has_required_activities():
activities = {a.activity_id for a in DEFAULT_ACTIVITIES}
for required in ("discovery", "enrichment", "outreach"):
assert required in activities
def test_build_ropa_returns_json():
r = build_ropa(customer_id="c", customer_name="Test Co.", dpo_name="x", dpo_email="x@x.sa")
j = r.to_json()
assert j["customer_id"] == "c"
assert j["n_activities"] >= 6
assert all("lawful_basis" in a for a in j["activities"])
def test_ropa_csv_rows():
r = build_ropa(customer_id="c", customer_name="Test")
rows = r.to_csv_rows()
assert len(rows) == len(DEFAULT_ACTIVITIES)
assert "name_ar" in rows[0]
# ── Vendor Registry ──────────────────────────────────────────────
def test_default_vendors_registered():
ids = {v.vendor_id for v in DEFAULT_VENDORS}
assert "anthropic" in ids
assert "moyasar" in ids
def test_register_vendor_assigns_id_and_timestamp():
v = Vendor(
vendor_id="",
name="Custom",
purpose_ar="x",
data_accessed=["x"],
region="SA",
)
out = register_vendor(v)
assert out.vendor_id.startswith("vnd_")
assert out.onboarded_at is not None
def test_vendors_summary():
s = vendors_summary()
assert s["total"] == len(DEFAULT_VENDORS)
assert s["with_dpa"] >= 0
assert s["dpa_coverage_pct"] >= 0