fix(campaign): sanitize synchronous send results
This commit is contained in:
@@ -40,6 +40,51 @@ CAMPAIGN_DIAGNOSTIC_RESPONSE_KEYS = frozenset(
|
||||
}
|
||||
)
|
||||
|
||||
_SEND_NOW_RESULT_KEYS = (
|
||||
"campaign_id",
|
||||
"version_id",
|
||||
"attempted_count",
|
||||
"sent_count",
|
||||
"failed_count",
|
||||
"outcome_unknown_count",
|
||||
"skipped_count",
|
||||
"preflight_count",
|
||||
"delivery_mode",
|
||||
"dry_run",
|
||||
)
|
||||
_SEND_NOW_JOB_RESULT_KEYS = (
|
||||
"campaign_id",
|
||||
"version_id",
|
||||
"job_id",
|
||||
"status",
|
||||
"attempt_number",
|
||||
"dry_run",
|
||||
"queued_count",
|
||||
"skipped_count",
|
||||
"blocked_count",
|
||||
"enqueued_count",
|
||||
"delivery_mode",
|
||||
"worker_queue_available",
|
||||
)
|
||||
_SYNCHRONOUS_POLICY_KEYS = (
|
||||
"max_recipient_jobs",
|
||||
"source",
|
||||
"deployment_max_recipient_jobs",
|
||||
"tenant_max_recipient_jobs",
|
||||
)
|
||||
_VALIDATION_SUMMARY_KEYS = ("ok", "error_count", "warning_count")
|
||||
_BUILD_SUMMARY_KEYS = (
|
||||
"built_count",
|
||||
"build_failed_count",
|
||||
"ready_count",
|
||||
"warning_count",
|
||||
"needs_review_count",
|
||||
"blocked_count",
|
||||
"excluded_count",
|
||||
"inactive_count",
|
||||
"queueable_count",
|
||||
)
|
||||
|
||||
|
||||
def public_campaign_payload(value: Any, *, include_diagnostics: bool = False) -> Any:
|
||||
"""Return a detached payload without infrastructure-only locators."""
|
||||
@@ -83,6 +128,59 @@ def public_delivery_result_message(
|
||||
return "Delivery recorded a warning; an operator can inspect restricted diagnostics."
|
||||
|
||||
|
||||
def public_send_campaign_now_result(
|
||||
value: dict[str, Any],
|
||||
*,
|
||||
validation_summary: dict[str, Any],
|
||||
build_summary: dict[str, Any],
|
||||
) -> dict[str, Any]:
|
||||
"""Project synchronous delivery into its recipient-authorized public contract.
|
||||
|
||||
Per-job provider messages are deliberately omitted. They can contain SMTP
|
||||
diagnostics or refused envelope addresses and belong only in restricted
|
||||
diagnostics backed by persisted job state.
|
||||
"""
|
||||
|
||||
result = _selected_payload(value, _SEND_NOW_RESULT_KEYS)
|
||||
policy = value.get("synchronous_send_policy")
|
||||
result["synchronous_send_policy"] = _selected_payload(
|
||||
policy if isinstance(policy, dict) else {},
|
||||
_SYNCHRONOUS_POLICY_KEYS,
|
||||
)
|
||||
rows = value.get("results")
|
||||
if isinstance(rows, list):
|
||||
result["results"] = [
|
||||
_selected_payload(row, _SEND_NOW_JOB_RESULT_KEYS)
|
||||
for row in rows
|
||||
if isinstance(row, dict)
|
||||
]
|
||||
else:
|
||||
result["results"] = []
|
||||
result["validation"] = _selected_payload(validation_summary, _VALIDATION_SUMMARY_KEYS)
|
||||
result["build"] = _selected_payload(build_summary, _BUILD_SUMMARY_KEYS)
|
||||
return result
|
||||
|
||||
|
||||
def send_campaign_now_audit_details(value: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Return aggregate-only evidence for a synchronous Campaign send audit."""
|
||||
|
||||
details = _selected_payload(value, _SEND_NOW_RESULT_KEYS)
|
||||
policy = value.get("synchronous_send_policy")
|
||||
details["synchronous_send_policy"] = _selected_payload(
|
||||
policy if isinstance(policy, dict) else {},
|
||||
_SYNCHRONOUS_POLICY_KEYS,
|
||||
)
|
||||
return details
|
||||
|
||||
|
||||
def _selected_payload(value: dict[str, Any], keys: tuple[str, ...]) -> dict[str, Any]:
|
||||
return {
|
||||
key: copy.deepcopy(value[key])
|
||||
for key in keys
|
||||
if key in value
|
||||
}
|
||||
|
||||
|
||||
def public_campaign_configuration(value: Any) -> Any:
|
||||
"""Return campaign JSON without infrastructure locators or mail secrets.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user