feat: complete postbox access evidence

This commit is contained in:
2026-07-30 14:26:59 +02:00
parent 28b60782de
commit bdc161e889
10 changed files with 858 additions and 96 deletions
+120 -1
View File
@@ -49,7 +49,7 @@ from govoplan_postbox.backend.db.models import (
PostboxTemplate,
PostboxTemplateRevision,
)
from govoplan_postbox.backend.service import PostboxService
from govoplan_postbox.backend.service import PostboxError, PostboxService
POSTBOX_TABLES = (
@@ -915,6 +915,12 @@ class PostboxServiceTests(unittest.TestCase):
actor=self.actor,
state="acknowledged",
)
receipt_summary = service.delivery_receipt_summaries(
session,
tenant_id="tenant-1",
producer_module="campaigns",
delivery_ids=(first.delivery_id,),
)[first.delivery_id]
session.commit()
self.assertFalse(first.duplicate)
@@ -922,6 +928,20 @@ class PostboxServiceTests(unittest.TestCase):
self.assertEqual(first.message_id, second.message_id)
self.assertIsNotNone(marked.read_at)
self.assertIsNotNone(marked.acknowledged_at)
self.assertTrue(receipt_summary.currently_readable)
self.assertEqual(1, receipt_summary.current_holder_count)
self.assertEqual(1, receipt_summary.read_receipt_count)
self.assertEqual(1, receipt_summary.acknowledged_receipt_count)
self.assertEqual(0, receipt_summary.withdrawn_message_count)
self.assertEqual(
{},
service.delivery_receipt_summaries(
session,
tenant_id="tenant-1",
producer_module="another-module",
delivery_ids=(first.delivery_id,),
),
)
self.assertEqual(
1,
session.query(PostboxMessage).count(),
@@ -971,6 +991,95 @@ class PostboxServiceTests(unittest.TestCase):
[event.type for event in events],
)
def test_withdrawn_and_expired_messages_keep_metadata_but_hide_content(
self,
) -> None:
self.idm.assignments.append(self.assignment)
with Session(self.engine) as session:
postbox = self._create_exact(session)
withdrawn = self.service.deliver(
session,
PostboxDeliveryRequest(
tenant_id="tenant-1",
target=PostboxTargetRef(postbox_id=postbox.id),
producer_module="campaigns",
producer_resource_type="campaign_recipient",
producer_resource_id="recipient-withdrawn",
idempotency_key="withdrawn-message",
subject="Withdrawn decision",
body_text="Sensitive withdrawn content",
),
)
expired = self.service.deliver(
session,
PostboxDeliveryRequest(
tenant_id="tenant-1",
target=PostboxTargetRef(postbox_id=postbox.id),
producer_module="campaigns",
producer_resource_type="campaign_recipient",
producer_resource_id="recipient-expired",
idempotency_key="expired-message",
subject="Expired decision",
body_text="Sensitive expired content",
expires_at=utc_now() - timedelta(minutes=1),
),
)
withdrawn_model = session.get(PostboxMessage, withdrawn.message_id)
assert withdrawn_model is not None
withdrawn_model.withdrawn_at = utc_now()
session.flush()
withdrawn_ref = self.service.get_message(
session,
tenant_id="tenant-1",
message_id=withdrawn.message_id,
actor=self.actor,
)
expired_ref = self.service.get_message(
session,
tenant_id="tenant-1",
message_id=expired.message_id,
actor=self.actor,
)
assert withdrawn_ref is not None
assert expired_ref is not None
self.assertEqual("withdrawn", withdrawn_ref.availability)
self.assertIsNone(withdrawn_ref.body_text)
self.assertEqual((), withdrawn_ref.attachments)
self.assertEqual("expired", expired_ref.availability)
self.assertIsNone(expired_ref.body_text)
with self.assertRaisesRegex(PostboxError, "withdrawn"):
self.service.mark_message(
session,
tenant_id="tenant-1",
message_id=withdrawn.message_id,
actor=self.actor,
state="read",
)
with self.assertRaisesRegex(PostboxError, "expired"):
self.service.mark_message(
session,
tenant_id="tenant-1",
message_id=expired.message_id,
actor=self.actor,
state="acknowledged",
)
summaries = self.service.delivery_receipt_summaries(
session,
tenant_id="tenant-1",
producer_module="campaigns",
delivery_ids=(withdrawn.delivery_id, expired.delivery_id),
)
self.assertFalse(summaries[withdrawn.delivery_id].currently_readable)
self.assertEqual(
1,
summaries[withdrawn.delivery_id].withdrawn_message_count,
)
self.assertFalse(summaries[expired.delivery_id].currently_readable)
self.assertEqual(1, summaries[expired.delivery_id].expired_message_count)
def test_hierarchy_linked_copy_snapshots_path_and_independent_state(
self,
) -> None:
@@ -1023,6 +1132,16 @@ class PostboxServiceTests(unittest.TestCase):
session.commit()
receipts = session.query(PostboxMessageReceipt).all()
self.assertEqual([route.target_message_id], [item.message_id for item in receipts])
summary = service.delivery_receipt_summaries(
session,
tenant_id="tenant-1",
producer_module="campaigns",
delivery_ids=(result.delivery_id,),
)[result.delivery_id]
self.assertEqual(2, summary.message_count)
self.assertEqual(1, summary.routed_message_count)
self.assertEqual(1, summary.read_receipt_count)
self.assertEqual({"accepted": 1}, summary.route_status_counts)
def test_hierarchy_dry_run_explains_gates_depth_and_parallel_structure(
self,