Skip to main content

Acceptance Spec — Email / Leads / Sales Funnel

Property: cwa · Registry suite: email-funnel · Created: 2026-06-13 Origin: the 2026-06-13 funnel audit found four silent regressions (From-brand collision, dead delivered_at, no reply capture, invisible engagement). This spec defines what "correct" means at each stage so it stays fixed. Full design + test plan: churchwiseai-web/docs/EMAIL_FUNNEL_SPEC_AND_TESTPLAN.md.

Funnel stages

SOURCE → SEND → DELIVERED → OPENED → CLICKED → DEMO VIEWED → ENGAGED (chat/voice) → REPLIED / BOOKED → CLAIMED → ONBOARDED → PAID

Two parallel models, same stages:

  • Churchoutreach_contacts (one row per prospect).
  • Local business (wiseaiagency)leads + campaign_members.

Correctness invariants (MUST hold)

  1. From / Reply-To isolation — each campaign resolves its sender from its OWN env var; brands never collide:
    • Church → OUTREACH_DEMO_FROM (john@churchwiseai.com)
    • Local-biz → LOCALBIZ_OUTREACH_FROM (hi@wiseaiagency.com)
    • SermonWise → SERMONWISE_OUTREACH_FROM (john@sermonwise.ai)
  2. One Resend webhook, account-level, subscribed to email.delivered/opened/clicked/bounced/complained. Handler stamps the matching model (church first; local-biz campaign_members only on a church miss) — church path must stay byte-for-byte unchanged. Idempotent; HTTP 200 no-match / 401 bad-sig / 500 DB-error.
  3. Open/click tracking per sending domain — open-tracking ON for churchwiseai.com, sermonwise.ai, wiseaiagency.com (founder dashboard toggle; opens stay 0 until enabled).
  4. Replies auto-captured — gmail-poll matches inbound sender → prospect, stamps replied_at for both models. (Local-biz reachability depends on hi@wiseaiagency.com forwarding into the connected Gmail.)
  5. Demo engagement persisted/s/[slug] view + chat/voice stamp the prospect row (church RPC; local-biz → campaign_members.demo_data).
  6. Deliverability — every batch send is hard-blocked unless every row has a NeverBounce DELIVERABLE result (campaign-preflight.ts). SPF/DKIM/DMARC + custom tracking subdomain per sending domain.
  7. CASL — founder presses every real send; no cron auto-sends to prospects; working unsubscribe + physical address on every campaign email; suppressed/bounced/unsubscribed rows excluded.
  8. Visibility — engagement is surfaced: church Warm Leads tab (outreach-engine) and Local Biz funnel tab (GCC /growth/local-biz), ranked Hot/Warm/Reached.

Enforcement

The unit suites listed under the email-funnel registry entry run in the blocking test CI job on every PR. They must not be deleted or skipped. Changes to the listed code_files should keep all suites green.

Definition of done (operating)

All invariants hold AND the founder-only steps are complete: open-tracking toggled on for all three domains, hi@wiseaiagency.com reply-forwarding confirmed, and sends are founder-initiated.