From bdc94e54656c69d40b2bc1ce10d0795b6834d785 Mon Sep 17 00:00:00 2001 From: Matthew Meszaros Date: Wed, 7 Oct 2026 15:24:22 +0000 Subject: [PATCH] feat: verify recipient filing never incurs tampering strikes and document all twelve deliverability controls with explicit external validation gates --- docs/content/docs/development/send-safety.mdx | 21 ++++++++++++++++++- .../app/consumer/warmup_retention_test.go | 9 +++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/docs/content/docs/development/send-safety.mdx b/docs/content/docs/development/send-safety.mdx index 87668708d..6f9cc0622 100644 --- a/docs/content/docs/development/send-safety.mdx +++ b/docs/content/docs/development/send-safety.mdx @@ -89,6 +89,25 @@ Rollback refuses unresolved reservations, explicit participation state, diagnost ## Verification and limits -R1 stop/consent, R2 shared budgets, R3 recovery and transactional hooks, R5 bounded actual-message DKIM, R7 disclosed coherent content, and R11 calendar/pacing controls have separate deterministic and live PostgreSQL fixtures. Upgrade fixtures start at the released 265 schema and preserve legacy IDs/state. Mixed campaign/warmup/placement/manual contenders prove shared capacity and unknown reservation retention; worker fixtures exercise replay, envelope binding, current consent and old JSON/Avro readability. Provider MIME fixtures test mutation, forged headers, timeout and bounds without provider access. +### Research coverage and external gates + +The twelve research proposals have different evidence requirements. Implemented controls and local fixtures are not substitutes for provider approval, native-language review or a real-recipient experiment. + +| Proposal | Implemented path and regression coverage | Remaining external verification | +|---|---|---| +| R1: consent and complete stop | Mailbox and Cloud participation, final action authority; `review_corrections_live_test.go` and lifecycle/Cloud UI-model fixtures | Drain old accepted commands; verify every deployed control plane and worker before relying on cancellation | +| R2: shared admission | `send_admission.go`, immutable attempt ledger, mixed-lane concurrency and failed-attempt fixtures | Operators must reserve headroom for other mail clients and configure known applicable provider limits; their traffic is not automatically metered here | +| R3: errors and recovery | Native provider classification, durable holds, transactional accounting and outbox; recovery and legacy JSON/Avro fixtures | Reconcile ambiguous native outcomes with real provider evidence; external notifications remain at least once | +| R4: measurement provenance | Separate receipt/folder/authentication observations, unknown categories and placement denominators; observation-evidence upgrade fixtures | Real provider/dashboard coverage and missingness remain measured inputs, not inferred success | +| R5: message authentication and unsubscribe | Authorized bounded Gmail/Graph/IMAP DKIM and exact-domain alignment; cryptographic/raw-MIME fixtures and existing scanner-safe unsubscribe | SPF, DMARC, receiving-hop TLS and delivered RFC 8058 signer coverage require actual evidence; provider enrollment and route remediation remain operator tasks | +| R6: exact-parent lifecycle | Durable token/receipt ancestry, stable subject/References and one successor; `warmup_lineage_live_test.go` and dispatch fixtures | Canary the actual deployed queue/provider path; ambiguous legacy ancestry never becomes a reply grant | +| R7: coherent content | Versioned vetted scenarios and final canonical rendering; `content_quality_test.go` and generation fixtures | Human and native-language quality benchmarks have not been run; prose never proves a real provider outcome | +| R8: effective generation controls | Settings round-trip, effective settings and credential-independent stop; warmup-content control/batch and upgrade fixtures | Configured model visibility is not Batch/structured-output support; actual provider submission must confirm capability | +| R9: trust and Cloud reconciliation | Current role/tier/standing gates, durable consent and restrictive history; managed-consent fault/import fixtures | Upgrade all Cloud replicas before correlated operations; local alias unlink is not global native-mailbox revocation | +| R10: queue and diagnostic parity | SQL-bound callbacks, replay fencing, untouched first-folder evidence and seed isolation; lineage, worker and placement fixtures | Actual hosted/local queue fleets and fixed-panel coverage require rollout verification; missing reports remain unknown | +| R11: legitimate response-adaptive pacing | Conservative cold ceiling uses fresh distinct campaign replies, with negative feedback and configured caps; cold-ramp/projection fixtures | Adequate real-recipient coverage, provider-stratified holdouts and a preregistered controlled evaluation are required before any efficacy claim | +| R12: readiness and claims | DNS discovery is not authentication; operational health is not reputation; UI/docs explain diagnostic scope and unknowns | No guaranteed inbox or universal safe-volume claim; marketing benefits require replicated real-recipient evidence | + +Upgrade fixtures start at the released 265 schema and preserve legacy IDs/state. Mixed campaign/warmup/placement/manual contenders prove shared capacity and unknown reservation retention; worker fixtures exercise replay, envelope binding, current consent and old JSON/Avro readability. Provider MIME fixtures test mutation, forged headers, timeout and bounds without provider access. These checks establish local engineering behavior, not production efficacy, provider consent, real delivery, all-provider authentication, signed RFC 8058 headers or exactly-once external notification delivery. They perform no live sends, browser proof or production reads. diff --git a/internal/app/consumer/warmup_retention_test.go b/internal/app/consumer/warmup_retention_test.go index 317b95d65..85fdf66ff 100644 --- a/internal/app/consumer/warmup_retention_test.go +++ b/internal/app/consumer/warmup_retention_test.go @@ -280,11 +280,8 @@ func TestRecheckTamperingSearchesEachOldStrike(t *testing.T) { } } -// Gmail reports Delete as gaining the TRASH label. That is the owner's act -// and is judged on the same freshness rule. A spam label charges nobody on -// sight: a move after arrival is held for attribution, and the label on mail -// that arrived in spam is the filter's own and is not even held. -func TestFlagsAddJudgesGmailTrashOnFreshness(t *testing.T) { +// Recipient filing never earns a strike; later spam moves retain sender attribution. +func TestFlagsAddPreservesSenderAttributionWithoutPenalizingRecipientFiling(t *testing.T) { landedSpam := receivedAgo(time.Second) landedSpam.LandedSpam = true cases := []struct { @@ -294,7 +291,7 @@ func TestFlagsAddJudgesGmailTrashOnFreshness(t *testing.T) { want []string held int }{ - {"trashed an hour after arrival", receivedAgo(time.Hour), []string{"TRASH"}, []string{"deletion"}, 0}, + {"trashed an hour after arrival", receivedAgo(time.Hour), []string{"TRASH"}, nil, 0}, {"trashed a month after arrival", receivedAgo(30 * 24 * time.Hour), []string{"TRASH"}, nil, 0}, {"moved to spam a month after arrival is held", receivedAgo(30 * 24 * time.Hour), []string{"SPAM"}, nil, 1}, {"spam label on mail that arrived in spam", landedSpam, []string{"SPAM"}, nil, 0},