Implement governed hybrid campaign delivery

This commit is contained in:
2026-08-02 13:58:37 +02:00
parent b38597f2be
commit 7733265cc8
40 changed files with 2531 additions and 122 deletions
@@ -22,8 +22,8 @@ from govoplan_campaign.backend.campaign.mail_profile_boundary import (
from govoplan_campaign.backend.integrations import MailProfileError, files_integration, mail_integration
from govoplan_campaign.backend.path_security import CampaignPathSecurityError, assert_server_safe_campaign_paths
SNAPSHOT_VERSION = "7"
SUPPORTED_SNAPSHOT_VERSIONS = {"6", SNAPSHOT_VERSION}
SNAPSHOT_VERSION = "8"
SUPPORTED_SNAPSHOT_VERSIONS = {"6", "7", SNAPSHOT_VERSION}
class ExecutionSnapshotError(RuntimeError):
@@ -61,6 +61,7 @@ class ExecutionSnapshot(BaseModel):
imap_transport_revision: str | None = None
uses_mail: bool = True
uses_postbox: bool = False
uses_print: bool = False
delivery: DeliveryConfig
@@ -162,6 +163,8 @@ def _policy_fingerprint(
if snapshot_version == "6":
delivery_payload.pop("channel_policy", None)
delivery_payload.pop("postbox", None)
if snapshot_version in {"6", "7"}:
delivery_payload.pop("print", None)
return _sha256(
{
"validation_policy": raw_json.get("validation_policy"),
@@ -207,6 +210,13 @@ def _job_execution_input_payload(
),
}
)
if snapshot_version not in {"6", "7"}:
payload["delivery_provenance_sha256"] = _sha256(
getattr(job, "delivery_provenance", None) or {}
)
payload["resolved_print_output_sha256"] = _sha256(
getattr(job, "resolved_print_output", None) or {}
)
return payload
@@ -268,6 +278,7 @@ def create_execution_snapshot(
}
uses_mail = any(policy.uses_mail for policy in channel_policies)
uses_postbox = any(policy.uses_postbox for policy in channel_policies)
uses_print = any(policy.uses_print for policy in channel_policies)
for job in job_list:
job.execution_input_sha256 = job_execution_input_hash(
job,
@@ -304,6 +315,7 @@ def create_execution_snapshot(
imap_transport_revision=imap_transport_revision,
uses_mail=uses_mail,
uses_postbox=uses_postbox,
uses_print=uses_print,
created_at=datetime.now(timezone.utc).isoformat(),
delivery=delivery,
).model_dump(mode="json")