security: harden Campaign delivery effects and reconciliation

This commit is contained in:
2026-07-21 17:14:33 +02:00
parent 057e660b17
commit 09c63de813
25 changed files with 2079 additions and 708 deletions

View File

@@ -4,6 +4,8 @@ import copy
from pathlib import Path, PureWindowsPath
from typing import Any
from govoplan_campaign.backend.campaign.mail_profile_boundary import public_campaign_mail_server
# These fields locate process-local or storage-backend resources, or authorize
# a worker claim. They are useful for tightly controlled diagnostics but are
@@ -39,6 +41,29 @@ def public_campaign_payload(value: Any) -> Any:
return copy.deepcopy(value)
def public_delivery_result_message(
*,
last_error: Any,
send_status: Any,
imap_status: Any,
) -> str | None:
"""Map persisted provider text to a stable business-safe explanation."""
if not last_error:
return None
clean_send_status = str(send_status or "")
clean_imap_status = str(imap_status or "")
if clean_send_status == "outcome_unknown":
return "SMTP delivery outcome requires operator reconciliation."
if clean_send_status in {"failed_temporary", "failed_permanent"}:
return "SMTP delivery failed; an operator can inspect restricted diagnostics."
if clean_imap_status in {"outcome_unknown", "appending"}:
return "Sent-folder append outcome requires operator reconciliation."
if clean_imap_status in {"failed", "skipped"}:
return "Sent-folder append did not complete; an operator can inspect restricted diagnostics."
return "Delivery recorded a warning; an operator can inspect restricted diagnostics."
def public_campaign_configuration(value: Any) -> Any:
"""Return campaign JSON without infrastructure locators or mail secrets.
@@ -49,18 +74,8 @@ def public_campaign_configuration(value: Any) -> Any:
payload = public_campaign_payload(value)
if not isinstance(payload, dict):
return payload
server = payload.get("server")
if isinstance(server, dict):
for protocol in ("smtp", "imap"):
config = server.get(protocol)
if isinstance(config, dict):
config.pop("password", None)
credentials = server.get("credentials")
if isinstance(credentials, dict):
for protocol in ("smtp", "imap"):
config = credentials.get(protocol)
if isinstance(config, dict):
config.pop("password", None)
if "server" in payload:
payload["server"] = public_campaign_mail_server(payload)
_sanitize_configuration_paths(payload)
return payload