Problem/Motivation
created records receipt time, and suppression windows use that value. BouncedAt and other provider timestamps are discarded, so a delayed or replayed soft bounce starts a new window even when the underlying bounce is older than the configured period.
Evidence and scope
Reviewed 1.0.0-alpha1, source commit 02fd9d36af5237e712cecb7155d79725f7824880. Location: src/Controller/PostmarkWebhookController.php:89.
Kernel reproduction: a SoftBounce with BouncedAt 60 days ago still suppresses under the default 30-day window.
Proposed resolution
Store occurrence and receipt times separately. Establish validation, missing-time fallback, future-clock tolerance and ordering rules. State changes should not let stale events overwrite newer evidence. Coordinate schema work with durable suppression state.
Acceptance criteria
Test delayed delivery, out-of-order events, equal timestamps, future and invalid timestamps, legacy rows and retry behavior. Make the chosen time basis visible in operator diagnostics.
Comments
Comment #2
jmcerdaImplemented with the durable-state work in #3621121 and shared policy in #3621126. Occurrence and receipt times are separate; delayed events cannot extend old windows or overwrite newer evidence. Invalid dates and excessive future skew are rejected; smaller skew is explicitly marked clamped. Drupal 10 and 11 PostgreSQL tests cover delayed, out-of-order, equal-time, legacy, invalid and future cases. The implementation is under review and is not yet integrated into public 1.x.
Comment #3
jmcerdaOccurrence-time handling is now integrated into 1.x at d3c5d94, with the durable-state and validation prerequisite (#3621121 and #3621122). The PostgreSQL suites pass on Drupal 10.3/PHP 8.3 and Drupal 11/PHP 8.4 (39 tests, 226 assertions each), covering delayed and out-of-order events, equal times, invalid dates, future clamping, and legacy receipt-time fallback.
Fixed on the development branch; no release tag or deployment has been made.