Consume governed recipients and add operational checks

This commit is contained in:
2026-07-31 22:48:07 +02:00
parent fa4eb39e0b
commit 82ddc0c34c
15 changed files with 354 additions and 14 deletions
+18
View File
@@ -0,0 +1,18 @@
from __future__ import annotations
from unittest.mock import patch
from govoplan_campaign.backend.operational_checks import generated_eml_storage_check
def test_generated_eml_probe_reports_node_local_boundary(tmp_path) -> None:
with patch(
"govoplan_campaign.backend.operational_checks.BUILD_OUTPUT_DIR",
tmp_path,
):
result = generated_eml_storage_check()
assert result.state == "warning"
assert "node-local" in result.detail
assert list(tmp_path.rglob("*.probe")) == []
+52
View File
@@ -78,6 +78,58 @@ class CampaignPartialValidationTests(unittest.TestCase):
self.assertTrue(response.available)
self.assertEqual(response.candidates[0].email, "ada@example.local")
def test_address_source_snapshot_preserves_governance_exclusions(self) -> None:
class RecipientSourceCapability:
def snapshot(self, _session, _principal, **kwargs):
self.kwargs = kwargs
return {
"source_id": "addresses:address_book:book-1",
"source_label": "Residents",
"source_kind": "local",
"source_revision": "revision-2",
"generated_at": "2026-07-31T10:00:00+00:00",
"purpose": "campaign_delivery",
"recipients": [
{
"contact_id": "contact-1",
"display_name": "Ada Lovelace",
"email": "ada@example.local",
"fields": {},
"provenance": {"channel_decision": {"governance_state": "opted_in"}},
}
],
"excluded": [
{
"contact_id": "contact-2",
"display_name": "Grace Hopper",
"channel": "email",
"target": "grace@example.local",
"status": "suppressed",
"reason_code": "addresses.channel.opted_out",
"provenance": {"channel_decision": {"governance_state": "opted_out"}},
}
],
"provenance": {"governance_applied": True},
}
capability = RecipientSourceCapability()
payload = router.CampaignRecipientAddressSourceSnapshotRequest(
source_id="addresses:address_book:book-1"
)
with patch.object(router, "_get_campaign_for_principal", return_value=None), patch.object(
router, "_registry_capability", return_value=capability
):
response = router.snapshot_campaign_recipient_address_source(
"campaign-1", payload, session=object(), principal=object()
)
self.assertEqual(capability.kwargs["purpose"], "campaign_delivery")
self.assertEqual(capability.kwargs["requested_channels"], ("email",))
self.assertEqual(response.included_count, 1)
self.assertEqual(response.excluded_count, 1)
self.assertEqual(response.excluded[0].reason_code, "addresses.channel.opted_out")
self.assertTrue(response.provenance["governance_applied"])
class CampaignSemanticValidationTests(unittest.TestCase):
def test_send_mode_requires_campaign_owned_sender_for_each_inline_entry(self) -> None: