feat(core): define sanctions screening gate contract
This commit is contained in:
@@ -6,9 +6,19 @@ import unittest
|
||||
|
||||
from govoplan_core.core.sanctions import (
|
||||
CAPABILITY_CONNECTORS_SANCTIONS_SNAPSHOTS,
|
||||
CAPABILITY_RISK_COMPLIANCE_SANCTIONS_SCREENING,
|
||||
SanctionsScreeningEvidence,
|
||||
SanctionsScreeningFreshness,
|
||||
SanctionsScreeningFreshnessRequest,
|
||||
SanctionsScreeningPolicy,
|
||||
SanctionsScreeningProvider,
|
||||
SanctionsScreeningRequest,
|
||||
SanctionsScreeningResult,
|
||||
SanctionsScreeningSubject,
|
||||
SanctionsSnapshotPayload,
|
||||
SanctionsSnapshotProvider,
|
||||
SanctionsSnapshotReference,
|
||||
sanctions_screening_provider,
|
||||
sanctions_snapshot_provider,
|
||||
)
|
||||
|
||||
@@ -38,6 +48,27 @@ class _Registry:
|
||||
return self.provider if self.has_capability(name) else None
|
||||
|
||||
|
||||
class _ScreeningProvider:
|
||||
def request_screening(self, session, principal, request):
|
||||
del session, principal, request
|
||||
raise NotImplementedError
|
||||
|
||||
def check_freshness(self, session, principal, request):
|
||||
del session, principal, request
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class _ScreeningRegistry:
|
||||
def __init__(self, provider):
|
||||
self.provider = provider
|
||||
|
||||
def has_capability(self, name):
|
||||
return name == CAPABILITY_RISK_COMPLIANCE_SANCTIONS_SCREENING
|
||||
|
||||
def capability(self, name):
|
||||
return self.provider if self.has_capability(name) else None
|
||||
|
||||
|
||||
class SanctionsContractTests(unittest.TestCase):
|
||||
def test_snapshot_evidence_is_versioned_and_bounded(self) -> None:
|
||||
content = b"<CONSOLIDATED_LIST/>"
|
||||
@@ -74,6 +105,66 @@ class SanctionsContractTests(unittest.TestCase):
|
||||
sanctions_snapshot_provider(_Registry(provider)),
|
||||
)
|
||||
|
||||
def test_screening_evidence_and_freshness_are_versioned(self) -> None:
|
||||
subject = SanctionsScreeningSubject(
|
||||
subject_type="person",
|
||||
primary_name="Example Person",
|
||||
)
|
||||
policy = SanctionsScreeningPolicy(failure_policy="review")
|
||||
request = SanctionsScreeningRequest(
|
||||
list_snapshot_id="snapshot-1",
|
||||
idempotency_key="request-1",
|
||||
subject=subject,
|
||||
policy=policy,
|
||||
)
|
||||
evidence = SanctionsScreeningEvidence(
|
||||
ref="risk-screening:run-1",
|
||||
run_id="run-1",
|
||||
outcome="clear",
|
||||
candidate_count=0,
|
||||
list_snapshot_id=request.list_snapshot_id,
|
||||
source_version="2026-07-30",
|
||||
subject_fingerprint="a" * 64,
|
||||
matcher_version="matcher-v1",
|
||||
normalization_version="normalization-v1",
|
||||
policy_version="policy-v1",
|
||||
completed_at=datetime.now(timezone.utc),
|
||||
)
|
||||
freshness_request = SanctionsScreeningFreshnessRequest(
|
||||
evidence_ref=evidence.ref,
|
||||
current_subject=subject,
|
||||
policy=policy,
|
||||
)
|
||||
freshness = SanctionsScreeningFreshness(
|
||||
evidence=evidence,
|
||||
fresh=True,
|
||||
reasons=(),
|
||||
checked_at=datetime.now(timezone.utc),
|
||||
current_list_snapshot_id=request.list_snapshot_id,
|
||||
gate_decision="allow",
|
||||
gate_reasons=("screening_clear",),
|
||||
)
|
||||
result = SanctionsScreeningResult(
|
||||
evidence=evidence,
|
||||
freshness=freshness,
|
||||
created=True,
|
||||
)
|
||||
provider = _ScreeningProvider()
|
||||
|
||||
self.assertEqual(evidence.ref, freshness_request.evidence_ref)
|
||||
self.assertTrue(result.freshness.fresh)
|
||||
self.assertIsInstance(provider, SanctionsScreeningProvider)
|
||||
self.assertIs(
|
||||
provider,
|
||||
sanctions_screening_provider(
|
||||
_ScreeningRegistry(provider)
|
||||
),
|
||||
)
|
||||
|
||||
def test_screening_contract_rejects_ambiguous_subjects(self) -> None:
|
||||
with self.assertRaises(ValueError):
|
||||
SanctionsScreeningSubject(subject_type="entity")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user