Release govoplan-campaign v0.1.28: stabilize saving, review and delivery recovery
Module Package Release / publish-packages (push) Successful in 12s
Module Package Release / publish-packages (push) Successful in 12s
This commit is contained in:
@@ -30,9 +30,24 @@ been validated, built, reviewed, and locked.
|
||||
for attempts, outcomes, and reconciliation.
|
||||
- Confirm the effective Send now recipient-job limit. The safe default is 25;
|
||||
use Queue for workers for ordinary batches or any run above that limit.
|
||||
System administrators can explicitly configure 0–500 under Administration →
|
||||
SYSTEM → Campaign delivery; an explicit deployment ceiling remains binding,
|
||||
and TENANT policy may only narrow the inherited limit. This setting affects
|
||||
one synchronous request, not campaign size. It is audited and never sends
|
||||
messages; large interactive requests may encounter proxy timeouts.
|
||||
|
||||
## Deliverability Preflight
|
||||
|
||||
The Mail server connection test checks that selected server and credential. It
|
||||
does not authorize the campaign's sender, recipients, or resource selection.
|
||||
SMTP runtime checks require the selected SMTP credential when policy forbids
|
||||
inheritance, independently of IMAP. Sent-folder append checks IMAP credentials
|
||||
independently; full campaign validation still checks both required selections.
|
||||
Preflight errors distinguish Mail profile/credential policy, SMTP configuration,
|
||||
authentication, and connectivity. Do not change TLS or credential policies merely
|
||||
because a campaign preflight failed. A preflight rejection leaves staged jobs
|
||||
uncommitted and starts no message delivery.
|
||||
|
||||
Before the first live send for a sender domain or mail-server profile:
|
||||
|
||||
- Confirm the selected SMTP identity matches the visible From/envelope sender
|
||||
@@ -50,18 +65,25 @@ Before the first live send for a sender domain or mail-server profile:
|
||||
|
||||
## Queue And Send
|
||||
|
||||
1. Validate the version with file checks enabled.
|
||||
1. Link all required managed files, then validate the version with file checks
|
||||
enabled. Locking waits for a fresh attachment preview and asks for explicit
|
||||
**Link and lock** confirmation when matches are not linked. A locked version
|
||||
cannot change attachment links: use an editable version and repeat validation,
|
||||
build and review rather than assuming unlinked files were included.
|
||||
2. Build the version and inspect all blocking review items.
|
||||
3. Queue only after the selected version is the intended immutable execution
|
||||
version. Select **Queue for workers**, then verify the committed and
|
||||
published counts.
|
||||
4. Use **Send now** only if the exact eligible count is non-zero and at or below
|
||||
the effective deployment/tenant limit shown on the page.
|
||||
the effective deployment/system/tenant limit shown on the page.
|
||||
5. In worker mode, verify queue counters move from queued/claimed/sending to a
|
||||
terminal SMTP state.
|
||||
6. If a synchronous request is used, keep Review and send open: it polls the
|
||||
durable counters while the request runs. A rejection occurs before SMTP and
|
||||
directs oversized runs to workers.
|
||||
6. If a synchronous request is used, keep its blocking progress dialog open.
|
||||
Only its small version-scoped persisted counters refresh; the workspace,
|
||||
recipient list, attachment preview and full summary stay unchanged. Read-only
|
||||
refresh failure retains the last counters and does not prove delivery failed.
|
||||
A disconnected request may still be executing; never repeat it blindly.
|
||||
Oversized initial runs are rejected before SMTP and directed to workers.
|
||||
7. Review the SMTP batch line. `ready` means DNS/connectivity/TLS/auth preflight
|
||||
succeeded. Connection and reconnect counts explain reuse. `paused` means a
|
||||
systemic transport failure stopped the remaining jobs before their SMTP
|
||||
@@ -97,9 +119,10 @@ unknown provider attempt merely to repair the other layer's state.
|
||||
unavailable connectivity affect the batch rather than one recipient.
|
||||
- `outcome_unknown`: Do not retry directly. Check SMTP logs, mailbox evidence, or
|
||||
provider control panels, then reconcile as accepted or not sent.
|
||||
- `claimed` or `sending` that does not progress: treat as a worker interruption.
|
||||
Re-run worker handling or reconcile if SMTP may already have accepted the
|
||||
message.
|
||||
- `claimed` or `sending` that does not progress: investigate the owning runtime.
|
||||
Duplicate worker handling leaves active state unchanged. Never infer from
|
||||
elapsed time alone that SMTP did not accept the message. Use the fenced
|
||||
**Recover interrupted claim** action described below when it is available.
|
||||
- IMAP `appending`: A worker owns the durable append claim. Do not start a
|
||||
second append; if the worker cannot finish, reconcile only after checking the
|
||||
mailbox.
|
||||
@@ -117,6 +140,65 @@ unknown provider attempt merely to repair the other layer's state.
|
||||
- Add a note that identifies the evidence used, for example SMTP log line,
|
||||
provider message ID, or operator ticket.
|
||||
|
||||
For pure-Mail SMTP and channel-specific IMAP operations, reconciliation updates
|
||||
the original Campaign attempt, matching Campaign recovery operation and audit
|
||||
record atomically under a fresh lease. A SMTP-only decision cannot resolve an
|
||||
entire compound Mail/Postbox/Print operation; that ledger remains separately
|
||||
unresolved until all of its effects are established. Campaign does
|
||||
not rewrite Mail-owned nested provider-effect operations: those remain Mail's
|
||||
separate evidence and operational responsibility. A failed audit or conflicting
|
||||
claim must leave the prior unknown state intact.
|
||||
|
||||
### Recovery without workers
|
||||
|
||||
The Report offers explicit inline retry and continuation when workers are not
|
||||
configured. Retry uses `campaigns:campaign:retry` plus
|
||||
`campaigns:campaign:send`; continuation uses `campaigns:campaign:queue` plus
|
||||
`campaigns:campaign:send`. Both use the canonical immutable jobs and ordinary
|
||||
attempt ledger, not a separate one-message resend. Current Mail authorization,
|
||||
review/approval, execution integrity, retry limits and rate limits still apply.
|
||||
Each call is bounded by the effective synchronous recipient-job limit and
|
||||
reports remaining eligible work. Continue explicitly until none remains; it
|
||||
never selects accepted, excluded, active, uncertain or known failed jobs.
|
||||
Known failures have their own explicit retry action. These actions do not
|
||||
turn a long HTTP request into a background worker or guarantee exactly-once
|
||||
SMTP when a provider acknowledgement is lost.
|
||||
|
||||
For an abandoned active SMTP or IMAP claim, the report exposes recovery only
|
||||
after the original durable lease expires **and** the runtime registry proves
|
||||
that its owner stopped or was replaced. A stale heartbeat is insufficient.
|
||||
The opaque claim revision and original recovery evidence are rechecked under a
|
||||
fresh lease. Recovery records the effect as **outcome unknown**, never not sent.
|
||||
Then separately inspect external evidence and reconcile with a factual note
|
||||
before any retry. This requires `campaigns:campaign:reconcile`. If the original
|
||||
lease, evidence, or stopped-owner proof is missing, preserve the records and
|
||||
investigate through Ops; do not edit delivery rows or force a lease expiry in
|
||||
a real installation.
|
||||
|
||||
### Progress totals and Sent-folder batching
|
||||
|
||||
For each channel, **processed** includes successful, failed, uncertain and
|
||||
cancelled outcomes. **In progress** is separate from pending, so the currently
|
||||
sending/appending message remains visible. Paused SMTP work is also separate.
|
||||
Excluded/non-requested channel work is outside the denominator. The endpoint
|
||||
requires campaign read and object access and returns no recipient addresses,
|
||||
message bodies, attachments or credentials. It is not the privacy-thresholded
|
||||
aggregate Reports view and does not grant that view recipient access.
|
||||
|
||||
Append-to-Sent targets the selected campaign version, not all historical
|
||||
versions. Each message remains a separately fenced, sequential IMAP APPEND.
|
||||
Mail reuses the authenticated session and resolved folder for at most 100
|
||||
messages or 300 seconds by default, then rotates the connection. Current
|
||||
authorization, frozen transport revisions, credentials and recovery checks
|
||||
still run for every message. A stale idle connection is checked before another
|
||||
APPEND; an uncertain APPEND is never replayed. This removes repeated
|
||||
connect/login/folder-list round trips, not the time needed to upload each EML.
|
||||
It is not an atomic MULTIAPPEND transaction or parallel delivery.
|
||||
|
||||
SMTP and IMAP use the same progress dialog. An acknowledged operation remains
|
||||
successful even if loading its follow-up diagnostics fails: use Reload to
|
||||
refresh display, not to repeat the external effect.
|
||||
|
||||
## Fault Injection Checklist
|
||||
|
||||
Use mock infrastructure first, then repeat against the non-production real test
|
||||
@@ -141,17 +223,21 @@ deliberately excluded.
|
||||
|
||||
The runner also terminates a dedicated OS process executing the registered
|
||||
Campaign send task after complete DATA, then invokes the task in a fresh
|
||||
process. The unfinished durable attempt must become `outcome_unknown` and the
|
||||
endpoint must observe no second connection or DATA transaction. This covers
|
||||
the worker task/process boundary but not a broker or daemon.
|
||||
process. Redelivery must leave the active claim unchanged and the endpoint
|
||||
must observe no second connection or DATA transaction. Only a subsequent
|
||||
explicit, fenced recovery with test-fixture stopped-owner and expired-lease
|
||||
proof may change the unfinished attempt to `outcome_unknown`. This covers the
|
||||
worker task/process boundary but not a broker or daemon.
|
||||
|
||||
Run `dev/mail-testbed/run_celery_redelivery_acceptance.py` for the maintained
|
||||
Redis/Celery delivery and broker redelivery boundary. It starts an isolated
|
||||
Redis Compose service and real Celery workers, kills the first solo worker after complete DATA while the
|
||||
late-ack task is unacknowledged, and requires the same task identity to reach a
|
||||
replacement worker after Redis visibility recovery. Passing evidence also
|
||||
requires durable `outcome_unknown`, an empty broker queue/unacked set, and
|
||||
exactly one SMTP connection and DATA transaction. Raw worker logs and task,
|
||||
requires unchanged active state on duplicate delivery, followed by explicit
|
||||
fenced recovery to `outcome_unknown`, an empty broker queue/unacked set, and
|
||||
exactly one SMTP connection and DATA transaction. Lease expiration is simulated
|
||||
only in the isolated fixture after its owner was stopped. Raw worker logs and task,
|
||||
database, endpoint, and credential identifiers are never retained.
|
||||
|
||||
That second runner proves local runner-supervised process replacement, not the
|
||||
@@ -190,6 +276,11 @@ and retention.
|
||||
|
||||
## Reporting Checks
|
||||
|
||||
- The recipient-aware report shows every frozen To/Cc/Bcc address in authored
|
||||
order, with a primary-address fallback only for old rows without that snapshot.
|
||||
SMTP envelope evidence, not the old primary-only UI, establishes how many
|
||||
recipients were actually offered to the provider. SMTP and IMAP diagnostics
|
||||
use list filters and consistent translated labels.
|
||||
- Partial delivery must show accepted, failed, and unknown counts separately.
|
||||
- Excluded messages must show SMTP and IMAP as `skipped`, with skipped counts
|
||||
and filters separate from unattempted or failed delivery.
|
||||
|
||||
+218
-5
@@ -186,6 +186,11 @@ configured timeout. Opening the link never completes the Workflow.
|
||||
password generator keeps its candidate separate from the form until **Use
|
||||
password** is explicitly confirmed. Copying a candidate does not save or
|
||||
submit it.
|
||||
If legacy transport data is reported, choose **Migrate selected Mail
|
||||
profile**, including when the existing profile selection is unchanged.
|
||||
Follow a locked version's supported unlock or editable-successor action
|
||||
before migration. Migration is explicit and audited, never sends mail, and
|
||||
requires validation, build, and review again.
|
||||
6. Save the editable version, validate the relevant sections, and resolve every
|
||||
blocking issue. Warnings remain explicit review decisions.
|
||||
7. Build the exact messages and inspect recipient, addressing, template,
|
||||
@@ -195,11 +200,77 @@ If a selected optional module is absent, Campaign remains loadable and explains
|
||||
which function is unavailable. It must not fail startup because Mail, Files, or
|
||||
Addresses is not installed.
|
||||
|
||||
Opening or leaving Template without editing does not change the saved HTML or
|
||||
mark the page dirty. Visual/source inspection and read-only changes likewise
|
||||
do not require a save. Actual saves send only client-owned editor metadata. Review
|
||||
and approval evidence remains server-owned and cannot be overwritten by an
|
||||
ordinary editor save. Omitting that readable evidence from a save does not
|
||||
delete it; normal version-lock and invalidation rules remain authoritative.
|
||||
|
||||
### Preserve recipient address order
|
||||
|
||||
In an individual or global address dialog, use the up/down actions to arrange
|
||||
the addresses, then choose **Save** in the dialog. The campaign draft keeps that
|
||||
order; saving no longer alphabetically sorts it. Duplicate email addresses keep
|
||||
their first position, and pasted addresses append in their entered order.
|
||||
The first individual To address is also the primary name/email shown in the
|
||||
recipient row. Use the page's **Save** to persist the campaign draft. A rejected
|
||||
page save keeps the reordered draft for an explicit retry. **Cancel** in the
|
||||
dialog discards only its unconfirmed changes.
|
||||
|
||||
### Permit Legacy ZipCrypto as an explicit compatibility exception
|
||||
|
||||
AES remains the secure default. Campaign **Settings**, **Policies**, and
|
||||
**Attachments** expose the effective archive policy, configuration links for
|
||||
authorized administrators, and **Reload archive policy**.
|
||||
|
||||
1. A policy administrator opens **Administration → SYSTEM → Campaign archive
|
||||
encryption**, enables **Legacy ZipCrypto**, and saves. The controls work
|
||||
before the first system override exists; opening defaults alone does not
|
||||
create an override or unsaved changes. Changing this global ceiling requires
|
||||
both `system:settings:write` and `admin:policies:write`; tenant policy
|
||||
authority alone cannot loosen it.
|
||||
2. Check tenant and owner policy restrictions. Lower scopes may narrow, never
|
||||
loosen, inherited methods and password-delivery channels.
|
||||
3. The Campaign actor also needs `campaigns:archive:use_legacy_zipcrypto` and
|
||||
edit access to the selected version. Policy administration does not replace
|
||||
that dedicated permission.
|
||||
4. Return to Campaign, reload archive policy, and select **Legacy ZipCrypto**
|
||||
under **Attachments → ZIP attachments**. Acknowledge weak encryption, enter
|
||||
an operational reason of at least 10 characters, and select an allowed
|
||||
separate password-delivery channel.
|
||||
5. Save, validate, build, and review. Policy/configuration saves never send
|
||||
mail; delivery remains a separate action.
|
||||
|
||||
Legacy remains blocked while Policy is unavailable. Neither an encryption
|
||||
error nor an incompatible client causes automatic fallback from AES to
|
||||
ZipCrypto. The build retains policy and acknowledgement evidence but never the
|
||||
password; see the manifest topic `campaigns.archive-encryption-governance`.
|
||||
|
||||
Mail migration and ZIP corrections can be saved in either order. A Mail-only
|
||||
migration preserves unchanged ZIP settings without granting permission to use
|
||||
them or adding acknowledgement evidence. An archive correction with unchanged
|
||||
Mail references preserves legacy transport server-side until its separate,
|
||||
explicit migration. Changes to ZIP settings still require the current policy
|
||||
and any dedicated legacy permission; changes to Mail references still require
|
||||
authorized migration. Validate, build and review again after both repairs.
|
||||
|
||||
A save and the following workspace refresh are separate operations. A failed
|
||||
refresh does not undo a committed save or clear the last usable workspace.
|
||||
Keep any newer unsaved edits, inspect the refresh error, and use Reload to fetch
|
||||
the current state. Responses for an earlier campaign, version or signed-in
|
||||
identity cannot overwrite the current workspace.
|
||||
|
||||
### Review and complete review
|
||||
|
||||
The reviewer should verify the immutable candidate that will be delivered, not
|
||||
just the authoring form:
|
||||
|
||||
If a legacy Mail migration notice appears, follow **Open Mail settings** for
|
||||
that exact version, complete migration, and validate and build again. Review
|
||||
stays read-only until migration is resolved and does not repeatedly request
|
||||
an attachment preview that the legacy transport boundary must reject.
|
||||
|
||||
1. Confirm purpose, owner, selected version, and recipient count.
|
||||
2. Inspect blocking errors, warnings, exclusions, and recipients requiring
|
||||
review.
|
||||
@@ -223,6 +294,67 @@ the required action, the responsible role, and the workspace to open. The
|
||||
review summary keeps reviewed and remaining counts visible; a completed review
|
||||
acknowledges the group items and remains bound to the current build token.
|
||||
|
||||
Save each individual acceptance to persist its reason and reviewed state before
|
||||
completing the entire review. Wait for acknowledgement; reloading then resumes
|
||||
that build's saved progress. If saving fails or conflicts, the pending note
|
||||
remains available for an explicit retry rather than becoming a false success.
|
||||
This small save only loads the selected persisted jobs: it does not rebuild
|
||||
messages, materialize attachments, or reload the whole workspace. Another
|
||||
reviewer's existing decisions and attribution remain intact. Partial progress
|
||||
does not enable delivery; final completion still checks the complete build.
|
||||
|
||||
Use **Accept similar review conditions** to record the same decision for a
|
||||
counted selection of currently loaded matching messages. The server defines
|
||||
eligible categories from the complete combination of overridable conditions;
|
||||
the UI does not interpret a warning badge as permission to override. Select
|
||||
one category, inspect the listed recipients, deselect any exceptions and enter
|
||||
a common reason (required for attachment exceptions). A submission contains
|
||||
at most 200 explicit message IDs. When more remain, save this selection and
|
||||
reopen the dialog; the counts never imply acceptance of unloaded messages or
|
||||
other categories. The reason is recorded separately against each selected
|
||||
message's frozen evidence. A failed save retains the selection and reason for
|
||||
an explicit retry, while a changed build prevents stale acceptance. This
|
||||
action neither sends messages nor completes the final review gate. Hard
|
||||
blockers cannot be accepted this way. Deliberate policy exclusions and
|
||||
attachment rules that explicitly permit zero matches remain informational
|
||||
and do not require review decisions.
|
||||
|
||||
An optional rule with explicit `missing_behavior: continue` may yield no files
|
||||
without creating review work; that outcome remains informational evidence.
|
||||
Required attachment and hard-block policies cannot be weakened by this setting.
|
||||
The separate policy for sending a wholly attachment-free message still applies.
|
||||
Rebuild existing messages after changing attachment policy; historical build
|
||||
evidence is not rewritten.
|
||||
|
||||
The incremental review API uses `merge_progress: true`, the acknowledged
|
||||
`base_revision`, and `build_token` set to the public `review_build_token`.
|
||||
It merges exact reviewed keys/decision job IDs for the current build, with an
|
||||
optional `decision_category_key` to bind a grouped acceptance. The safe review
|
||||
reference is available without diagnostic access; raw build tokens remain
|
||||
diagnostic data. Stale build/revision or simultaneous writes return HTTP 409
|
||||
without overwriting progress. Normal review authorization and audit apply.
|
||||
|
||||
Accepted or expected attachment conditions remain satisfied in **Confirm and
|
||||
send** for the same build. Raw missing/ambiguous source counts remain visible
|
||||
for context; they are not a second approval gate. Reviewed-stage mock delivery
|
||||
uses `use_reviewed_build: true`: it verifies the existing execution seal,
|
||||
completed review, frozen job issues and EML integrity, and current Mail transport
|
||||
before capturing anything in the mock mailbox. It uses those stored messages,
|
||||
not freshly rendered replacements, and never mutates Campaign delivery state.
|
||||
Stale review, changed inputs, changed bytes or changed transport stop the test
|
||||
before captures or requested mailbox clearing. The authoring/mock-preview API
|
||||
keeps its existing transient-build default; `include_needs_review` does not
|
||||
bypass frozen review checks.
|
||||
|
||||
Validation details and repeated-file lists use the shared DataGrid pagination
|
||||
controls so every item is reachable. Related missing-rule causes and their
|
||||
attachment-free policy outcomes appear together, with the technical evidence
|
||||
still expandable. Built messages have four operational states: **Ready**,
|
||||
**Needs review**, **Blocked**, and **Excluded**, plus an explanatory column.
|
||||
Accepted explicit decisions are Ready; warnings awaiting acknowledgment remain
|
||||
Needs review. This presentation does not remove or rewrite frozen issues or
|
||||
audit evidence.
|
||||
|
||||
This evidence is the Campaign input to separation-of-duties policy. Generic
|
||||
approve/reject chains, delegation, substitutions, escalation, and signatures
|
||||
belong to the optional Approvals capability. Campaign must not claim an
|
||||
@@ -279,7 +411,7 @@ At a minimum:
|
||||
ordinary batches; the durable progress remains visible after leaving and
|
||||
returning to Review and send.
|
||||
2. Use **Send now** only when the exact persisted eligible build is within the
|
||||
effective synchronous limit shown by the UI. The default deployment limit
|
||||
effective synchronous limit shown by the UI. The unchanged default limit
|
||||
is 25 recipient jobs. The backend repeats the count and preflights every
|
||||
message and the Mail profile revision before contacting SMTP.
|
||||
3. Treat `smtp_accepted` as protected from ordinary retry.
|
||||
@@ -302,10 +434,24 @@ Pause stops new eligible work but cannot undo a provider effect already in
|
||||
progress. Cancel marks work that has not yet produced a protected SMTP outcome;
|
||||
it cannot recall accepted mail.
|
||||
|
||||
The deployment ceiling is configured with
|
||||
`GOVOPLAN_CAMPAIGN_SYNCHRONOUS_SEND_MAX_RECIPIENTS` (0 disables Send now; the
|
||||
accepted range is 0–500). A tenant may only narrow that ceiling with
|
||||
`tenant.settings.campaign_delivery_policy.synchronous_send_max_recipients`.
|
||||
Configure **Administration → SYSTEM → Campaign delivery** with
|
||||
`system:settings:read/write`. The default stays 25, but an administrator may
|
||||
explicitly choose 0–500, for example 200 for a 183-recipient-job run. Zero disables
|
||||
Send now. **TENANT → Campaign delivery** uses `admin:policies:read/write` and may
|
||||
only narrow the inherited system policy. Clearing an override restores
|
||||
inheritance. An explicitly configured deployment ceiling
|
||||
`GOVOPLAN_CAMPAIGN_SYNCHRONOUS_SEND_MAX_RECIPIENTS` remains authoritative; the
|
||||
implicit default does not prevent a system administrator choosing a larger
|
||||
bounded value. Save changes only this setting, preserves unrelated settings,
|
||||
checks a revision token including inherited policy, and records before/after
|
||||
configuration history and audit. Failed saves retain the draft; conflicting
|
||||
saves require explicit reload/reconciliation. Policy edits never send mail or
|
||||
change existing reviews or approval requirements.
|
||||
|
||||
This limit applies to one interactive Send now request, not campaign size or
|
||||
worker batching. Larger interactive requests run longer and can meet proxy
|
||||
timeouts. Queue for workers is independent and requires enabled, healthy
|
||||
Redis/Celery infrastructure; changing the numeric limit does not start workers.
|
||||
The effective value and source are returned by the protected delivery-options
|
||||
API, recorded for successful/rejected synchronous commands, and stated in the
|
||||
configured handbook topic.
|
||||
@@ -466,6 +612,73 @@ create an editable successor.
|
||||
|
||||
## Operations and recovery
|
||||
|
||||
### Interactive delivery and Sent-folder progress
|
||||
|
||||
Send now and workerless Report retry/continue use a compact blocking progress
|
||||
dialog, as does inline append-to-Sent. It refreshes saved counters only, not the
|
||||
whole campaign behind the overlay. Successful, pending, in-progress, failed,
|
||||
uncertain and excluded messages are shown separately; a currently sending or
|
||||
appending message therefore does not disappear between totals. Read errors keep
|
||||
the last known counters. After a connection interruption, processing may still
|
||||
be running; inspect saved evidence before repeating any action. A successful
|
||||
write is not reclassified as failed when its later display refresh fails.
|
||||
|
||||
The recipient-aware Report shows all frozen To, Cc and Bcc addresses, not only
|
||||
the primary row identity. Address order and recipient-read authorization remain
|
||||
unchanged. SMTP/IMAP diagnostics use translated status-list filters.
|
||||
|
||||
Without workers, explicitly retry eligible failures or continue unattempted
|
||||
jobs through Report. Each request uses the canonical job/attempt recovery
|
||||
boundary and is limited by the effective synchronous policy. Accepted and
|
||||
uncertain SMTP outcomes remain protected. Active abandoned claims require an
|
||||
expired durable lease, proven stopped/replaced owner, current revision and
|
||||
valid original evidence before recovery can mark them unknown. A separate
|
||||
evidence-note reconciliation is required before retrying. A timeout alone is
|
||||
never proof of non-delivery. See the delivery runbook for required permissions
|
||||
and operational limitations.
|
||||
|
||||
Append-to-Sent is scoped to the selected version and reuses a bounded Mail-owned
|
||||
connection/folder resolution (default 100 messages or 300 seconds), while
|
||||
performing one sequential APPEND and all current checks per message. Uncertain
|
||||
appends are never automatically repeated, and repairing Sent never resends SMTP.
|
||||
|
||||
Link required files before locking. Lock and validate waits for attachment
|
||||
matches, rechecks them immediately before locking, and asks for Link and lock
|
||||
confirmation if new unlinked files are found. A locked version cannot acquire
|
||||
new attachment links; use an editable version and validate/build/review again.
|
||||
|
||||
### Fortschritt, Wiederherstellung und Dateiverknüpfungen
|
||||
|
||||
Jetzt senden, synchrone Wiederholung/Fortsetzung im Bericht und Kopieren nach
|
||||
Gesendet verwenden einen kompakten sperrenden Fortschrittsdialog. Nur gespeicherte
|
||||
Zähler werden aktualisiert, nicht der Arbeitsbereich im Hintergrund. Erfolgreich,
|
||||
ausstehend, in Bearbeitung, fehlgeschlagen, ungewiss und ausgeschlossen bleiben
|
||||
getrennt sichtbar. Bei Lesefehlern bleiben die letzten Werte erhalten. Nach einer
|
||||
getrennten Verbindung kann die Verarbeitung weiterlaufen; prüfen Sie Nachweise,
|
||||
bevor Sie erneut handeln. Ein bestätigter Versand wird durch einen nachfolgenden
|
||||
Anzeigefehler nicht nachträglich als fehlgeschlagen dargestellt.
|
||||
|
||||
Der empfängerbezogene Bericht zeigt alle eingefrorenen An-, Cc- und Bcc-Adressen
|
||||
in ihrer Reihenfolge. Leseberechtigungen bleiben unverändert. SMTP und IMAP
|
||||
verwenden übersetzte Zustandslisten zum Filtern.
|
||||
|
||||
Ohne Worker können bekannte Fehler ausdrücklich wiederholt und unversuchte
|
||||
Aufträge begrenzt fortgesetzt werden. Die wirksame synchrone Grenze, gespeicherte
|
||||
Aufträge, Prüfungen, Freigaben und Wiederherstellungsnachweise bleiben verbindlich.
|
||||
Angenommene und ungewisse SMTP-Ergebnisse werden nicht blind wiederholt. Die
|
||||
Wiederherstellung aktiver, verlassener Aufträge benötigt eine abgelaufene Sperre,
|
||||
nachweislich gestoppte/ersetzte Laufzeit und gültige ursprüngliche Nachweise. Sie
|
||||
setzt ausschließlich auf ungewiss; vor Wiederholung sind externe Nachweise und
|
||||
ein getrennter Abgleich mit Notiz erforderlich. Zeitablauf allein genügt nicht.
|
||||
|
||||
Kopieren nach Gesendet betrifft nur die ausgewählte Version. Mail verwendet die
|
||||
Verbindung und Ordnerauflösung begrenzt wieder (Standard: 100 Nachrichten oder
|
||||
300 Sekunden), prüft aber jede Nachricht erneut und führt APPEND nacheinander
|
||||
aus. Ungewisse Ergebnisse werden nicht automatisch wiederholt. Verknüpfen Sie
|
||||
benötigte Dateien vor dem Sperren; eine frische Prüfung fragt bei unverknüpften
|
||||
Treffern nach Verknüpfen und sperren. Gesperrte Versionen benötigen zum Ändern
|
||||
eine bearbeitbare Version mit erneuter Validierung, Build und Prüfung.
|
||||
|
||||
### Health to observe
|
||||
|
||||
- database and migration health;
|
||||
|
||||
@@ -68,7 +68,9 @@ material and does not delete or rewrite the stored audit rows automatically:
|
||||
`mail_profile_migration_required` marker.
|
||||
- validation, build, queue, retry, and delivery fail closed with an actionable
|
||||
profile-migration error;
|
||||
- unrelated edits cannot silently scrub the legacy fields;
|
||||
- unrelated edits preserve the exact stored legacy server object when the
|
||||
submitted public Mail references are unchanged; they cannot silently scrub,
|
||||
edit, or re-submit legacy fields or credentials;
|
||||
- an editable version is migrated only through an explicit Mail-settings save
|
||||
with an authorized profile; and
|
||||
- a locked version remains unchanged. Creating its editable successor records
|
||||
@@ -81,6 +83,63 @@ database as a whole; the product does not define a separate historical-JSON or
|
||||
inline-secret recovery workflow. A restored legacy row remains inert and
|
||||
fail-closed under the same rules.
|
||||
|
||||
### Migrate from the Campaign UI
|
||||
|
||||
Open **Mail settings** from the migration notice for the selected version.
|
||||
Select an authorized Mail profile and choose **Migrate selected Mail profile**.
|
||||
The migration action is available even when that profile was already selected
|
||||
and the draft has no other unsaved changes. If the version is locked, first use
|
||||
its supported unlock or editable-successor action; protected source evidence is
|
||||
not rewritten. Reopen the settings and confirm that the migration notice has
|
||||
gone, then validate, build, and review before separately authorizing delivery.
|
||||
Migration itself never sends mail.
|
||||
|
||||
Mail migration and ZIP policy repairs can be saved in either order. An exact,
|
||||
unchanged ZIP configuration does not require a new acknowledgement merely to
|
||||
save a Mail migration, even if the existing ZIP policy or actor's permission is
|
||||
no longer valid. No actor, timestamp, or consent is invented. Any ZIP change
|
||||
still requires the complete current archive policy and, for ZipCrypto, the
|
||||
dedicated permission and reasoned acknowledgement. Conversely, saving an
|
||||
archive correction with unchanged public Mail references retains the exact
|
||||
legacy transport server-side, without using or reauthorizing the old profile.
|
||||
The migration notice remains until the explicit authorized migration succeeds.
|
||||
Changing any Mail profile, server, or credential reference is not an unrelated
|
||||
repair. Inline transport is rejected even if a caller echoes stored values.
|
||||
The same edit-time separation applies after migration: retaining an unchanged
|
||||
Mail selection does not invoke use-policy while saving an unrelated correction,
|
||||
even if a later policy requires an explicit credential. Selecting a new resource
|
||||
or explicitly migrating still checks Mail permission and current policy; actual
|
||||
validation and delivery always recheck them, regardless of save history.
|
||||
Both repair orders invalidate build/execution evidence; validation, build,
|
||||
review and delivery remain blocked until all outstanding conditions are valid.
|
||||
|
||||
Successful saves and subsequent refreshes are separate outcomes. A committed
|
||||
save is not undone by a failed workspace refresh. The workspace retains its
|
||||
last usable same-campaign/version data and displays the refresh error; retry
|
||||
Reload to fetch the current server state. Obsolete responses from an earlier
|
||||
campaign, version, signed-in identity, or reload cannot replace newer data.
|
||||
|
||||
The normal profile selector requests only campaign-authorized profiles. The
|
||||
administrative profile catalogue is requested separately on **Mail policy**;
|
||||
failure or lack of authority there does not empty the usable profile selector.
|
||||
Profile-list errors remain visible next to the affected settings.
|
||||
|
||||
While migration is required, **Review and send** remains read-only and links to
|
||||
the exact version's Mail settings. It does not repeatedly attempt incompatible
|
||||
attachment-preview requests. These UI affordances do not relax backend
|
||||
validation, build, queue, retry, or delivery enforcement.
|
||||
|
||||
### Editor metadata and trusted evidence
|
||||
|
||||
Read responses may contain server-owned `review_send` and `approval_gate`
|
||||
evidence. Ordinary version mutations send only client-owned `created_from`,
|
||||
`field_overrides`, and `opt_ins` editor metadata. The client omits review and
|
||||
approval evidence; the server rejects attempts to write it through an editor
|
||||
mutation and preserves its existing trusted value during metadata updates.
|
||||
Supported unlock, successor-version, and build invalidation rules still remove
|
||||
stale evidence when required. Opening or leaving the Template editor must not
|
||||
require manually deleting server review metadata.
|
||||
|
||||
## Operator checks
|
||||
|
||||
Before live delivery, confirm that:
|
||||
|
||||
Reference in New Issue
Block a user