Skip to content

38 — TestimonialRequestEvent Model & Delivery Event Stream (Blueprint §5.6)

Cursor-ready plan for request-event logging, provider event ingestion, timeline semantics, deduplication, and Requests Log integration.

38 — TestimonialRequestEvent Model & Delivery Event Stream (Blueprint §5.6)

Section titled “38 — TestimonialRequestEvent Model & Delivery Event Stream (Blueprint §5.6)”

Source: 02-Implementation-Blueprint.md§5.6 New model: TestimonialRequestEvent.

This document is a build spec only. No code changes are implied until a task references this file.

Related: 07 (delivery pipeline), 13 (requests log screen), 32 (operational workflow), 34 (daily analytics rollups), 20 (schema).


Implement TestimonialRequestEvent as a reliable, append-only timeline of messaging events so delivery observability, troubleshooting, and analytics are accurate and auditable.


Blueprint §5.6 fields:

  • id String @id @default(uuid())
  • shopId String @map("shop_id")
  • requestId String @map("request_id")
  • eventType String @map("event_type") // queued | sent | delivered | opened | clicked | failed
  • eventAt DateTime @default(now()) @map("event_at")
  • providerMessageId String? @map("provider_message_id")
  • payload Json?

Index:

  • @@index([requestId, eventAt])

  • event model + migration
  • event write helper contract
  • provider webhook event ingestion mapping
  • event dedupe rules
  • requests log timeline usage
  • cross-provider normalization for every vendor-specific edge case
  • external event bus integration

Base events from blueprint:

  • queued
  • sent
  • delivered
  • opened
  • clicked
  • failed

Optional internal events (if needed):

  • scheduled (if you want pre-queue observability)
  • submitted (mirrors request status transition after form submit)
  • retrying

Keep a central enum/constants module for event types used by sender, webhook callbacks, and UI.


Create a shared helper:

appendRequestEvent({ shopId, requestId, eventType, eventAt?, providerMessageId?, payload? })

Rules:

  1. request must belong to shopId.
  2. event rows are append-only.
  3. if eventAt omitted, default now.
  4. payload should be compact and sanitized (no secrets).

Use this helper everywhere to avoid inconsistent event writes.


  • queued when worker picks due request
  • sent when provider accepts send
  • failed when provider call errors
  • clicked when token page is opened (if using event stream in addition to clickedAt)

Webhook/callback handlers map provider statuses into canonical events:

  • provider delivered -> delivered
  • provider open -> opened
  • provider click -> clicked (if tracked at provider level)
  • provider bounce/reject -> failed

Store original provider payload in payload with redaction as needed.


Provider callbacks can replay. Add dedupe logic:

Before insert, check recent duplicate by:

  • requestId
  • eventType
  • providerMessageId (when present)
  • near-identical eventAt window

Add unique constraint on a synthetic hash column (future) if duplicate volume becomes a problem.

Duplicate event should be no-op and still return success response to provider.


Requests log (13) and support tooling should treat events as timeline, not single status source.

  • last event by eventAt can be used for “Last event timestamp”.
  • TestimonialRequest.status remains primary operational status.
  • event stream provides detailed audit and provider-level context.

payload Json guidelines:

  • include provider response identifiers and normalized metadata
  • exclude secrets/API keys
  • truncate oversized payloads if needed
  • redact personal data not needed for debugging

Keep payload size manageable to avoid DB bloat.


where: { requestId, shopId } ordered eventAt desc.

Use grouped counts by eventType + day (UTC), or rely on TestimonialDailyAnalytics rollup jobs.

Filter by:

  • eventType=failed
  • date range
  • campaign/request ids

  1. 07 sender worker writes queued/sent/failed.
  2. 06 token page can write clicked event.
  3. provider callback route writes delivered/opened/clicked.
  4. 13 requests log displays last event + event timeline.
  5. 34 rollup job consumes events (optional for clicked/opened counts).

  • Every send attempt writes at least one event row.
  • Provider callback events map to canonical event types.
  • Duplicate callback replay does not create duplicate timeline entries.
  • Requests log can show accurate last-event timestamp.
  • Event payloads are present but sanitized.

12) Suggested implementation order (for Cursor)

Section titled “12) Suggested implementation order (for Cursor)”
  1. Add Prisma model and migration for TestimonialRequestEvent.
  2. Implement shared append helper.
  3. Integrate helper into sender worker.
  4. Implement provider callback mapping and dedupe.
  5. Add timeline view in requests log.
  6. Add event-based analytics rollup hooks if needed.

  • 02-Implementation-Blueprint.md — §5.6
  • 07-email-sms-request-delivery-pipeline.md
  • 13-requests-log-blueprint-screen-10.md
  • 32-email-sms-operational-detail-blueprint-section-4.md
  • 34-testimonial-daily-analytics-model-blueprint-section-5-11.md

This folder already includes 05 through 37 plans. This file is 38-....