feat: harden campaign delivery and editing

This commit is contained in:
2026-07-30 14:27:04 +02:00
parent 4a120e8009
commit cd223cbb95
34 changed files with 3370 additions and 165 deletions
+17 -1
View File
@@ -58,6 +58,9 @@ class CampaignVersionUpdateRequest(BaseModel):
source_filename: str | None = None
source_base_path: str | None = None
migrate_legacy_mail_settings: bool = False
base_revision: int | None = Field(default=None, ge=1)
reconciliation_kind: Literal["none", "auto_merge", "manual"] = "none"
resolved_conflict_paths: list[str] = Field(default_factory=list, max_length=100)
@field_validator("editor_state")
@classmethod
@@ -92,6 +95,8 @@ class CampaignVersionResponse(BaseModel):
id: str
campaign_id: str
version_number: int
edit_revision: int = 1
strong_etag: str = ""
schema_version: str
source_filename: str | None = None
workflow_state: str = "editing"
@@ -440,11 +445,21 @@ class CampaignSendUnattemptedRequest(BaseModel):
class CampaignSendJobRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
kind: Literal["test", "single_send", "single_resend"]
idempotency_key: str = Field(min_length=1, max_length=200)
reason: str | None = Field(default=None, max_length=2000)
context: dict[str, Any] = Field(default_factory=dict)
include_warnings: bool = True
dry_run: bool = False
use_rate_limit: bool = True
enqueue_imap_task: bool = False
@model_validator(mode="after")
def require_resend_reason(self):
self.reason = (self.reason or "").strip() or None
if self.kind == "single_resend" and not self.reason:
raise ValueError("single_resend requires a reason")
return self
class CampaignResolveOutcomeRequest(BaseModel):
model_config = ConfigDict(extra="forbid")
@@ -626,6 +641,7 @@ class ReportEmailRequest(BaseModel):
attach_jobs_csv: bool = False
attach_report_json: bool = False
dry_run: bool = False
idempotency_key: str | None = Field(default=None, min_length=1, max_length=200)
@field_validator("to")
@classmethod