CEO and technical release review · updated 12 July 2026 · private WREA work

Email Campaign Studio: complete system and path to operation

The CEO view of what is built and what happens next, followed by a cold-start implementation and PR brief for Felix.

Important release correction · 12 July 2026

This earlier GO report is superseded. Do not merge or deploy from it.

A fresh independent audit found application defects that the earlier review and green test suite missed. The database migrations passed a production-shaped MySQL rehearsal, but the branch is not release-ready because it can affect existing scheduled agent digests, wrongly suppress a vendor from an ordinary preference save, fail to enrol Rescue contacts, change an approved Utility audience, and stall a large launch.

Use the canonical replacement: Fresh Pre-Production Audit and Release Decision.

Executive Summary

The entire Email Nurture system is built and tested on an isolated branch. It includes the marketing safety layer, suppression register, Fast Rescue foundation, utility/nurture foundation, editable email library, shared header, footer and unsubscribe section, exact-recipient previews, owner-only tests, final review, controlled launch, monitoring and contact-level journey visibility.

605 / 1,832local tests / assertions passed
3real owner-only test emails accepted
15editable starter email ideas
0production writes or customer sends

Latest safety and usability review

Fresh-audit correction: the intended purpose model is sound, but the normal scheduled-agent-digest path currently passes a queue row that is mistaken for a mass-email marker. Scheduled agent digests are therefore at risk of marketing suppression and frequency limits until that discriminator and its real scheduler-path test are fixed.
A real deployment blocker was found before release and removed. Production is MySQL 8.0.44 and its 1.11-million-row email-history table has a full-text search index. MySQL will not allow the originally proposed instant column additions on that type of table. Nothing had been deployed, so production was never changed. Campaign attribution now goes into a new, separate table linked to each email. The CRM gets the same reporting and safety behaviour without rebuilding, locking or changing email history.

Exactly what changes for existing email

Existing sendSendGrid IPCRM purposeNew suppression applies?What this means
Direct agent digestMarketingIntended operationalAT RISKDirect calls are operational, but the normal scheduled queue-backed path is currently misclassified as marketing. Do not deploy until the scheduler-path regression passes.
Staff operational emailMarketing or transactionalOperationalNOInvoice follow-up and genuine service communication remain available. The marketing-IP case is now regression-tested.
Vendor or partner digestMarketingMarketingYESStops for valid marketing suppression evidence. Transactional messages are separate and continue.
Staff mass emailMarketingMarketingYESEvery recipient is checked before send and again when the queued job runs.
36 active production workflow email actionsCurrently transactionalUnclassified legacyNO CHANGEAll 5,969 currently pending workflow rows retain existing behaviour. Seller Guide uses the transactional IP but is still technically unclassified.
New Campaign Studio campaignsMarketingMarketingYESRescue and Nurture receive the full safety checks by design.

What staff now see

The campaign page has a six-step assistant. Green means the CRM has evidence that the step is complete, blue is the next action, and grey comes later. A dedicated Nurture Email Library manages reusable emails plus the separately editable shared header, footer and unsubscribe section. Staff can change the unsubscribe wording and styling, but the CRM rejects a blank, missing, duplicated, unlinked or commented-out secure unsubscribe placeholder. The campaign list has a Duplicate button. Audience Preview has a View Email button beside each sample contact; it opens the exact subject and fully populated email for that person without sending anything. Final send still has one plain-English review page, and editing anything invalidates final approval.

Normal Nurture process

Yes: create one fresh draft for each monthly update or major event. Pick an existing library idea, update its facts, date and links, choose the CRM list and timing, preview, test, then send. Do not keep adding monthly emails to one old campaign. Rescue is different: set it up once and leave it active so qualifying recent enquiries enter automatically.

Repeating an issue is now simple: use Duplicate on the campaign list. The CRM creates a separate draft with independent email copies and no audience, test, send or approval history. For Nurture it deliberately removes the old send date, market-information date and content checksum so stale facts cannot be approved by accident.

Production health observed read-only

0 readyrelevant default queue backlog
5default queue workers running
~100%recent peak RDS CPU
79/hourrecent peak CRM email creation

The relevant default queue was healthy: zero ready, 39 intentionally delayed, zero buried and five workers. The global 1,175 ready count came from stale non-default tubes and is not the nurture queue. The application host had low load and about 5.75 GB memory available. The database averaged only 6.9% CPU across seven days, but had short peaks near 100% and periods of low free memory.

Warm IP does not prove CRM capacity: SendGrid deliverability history is established, so this is not an IP warm-up. However, the CRM recently created at most 79 email records in an hour. Use a one-time controlled first edition at 500–1,000/hour, watch CRM and RDS health, then raise later editions toward the configurable 10,000/hour ceiling. Nurture now also pauses automatically if 500 ordinary CRM jobs are waiting, and resumes on a later tick.

Your normal campaign workflow

The interface is designed around the job you are trying to do, not an internal policy system. Safety is still enforced underneath, but staff do not have to manage separate staged-audience records.

1

Create

Name the campaign and choose Rescue or Nurture. Saving creates a draft and cannot send.

2

Choose audience

Pick existing CRM marketing lists for Nurture, or enquiry source and current stage for Rescue.

3

Write

Start with an editable library idea or write your own subject and email. The CRM makes a private campaign copy.

4

Set timing

Choose date, local send time and hourly ceiling. Rescue remains fixed at +24 and +72 hours.

5

Preview and test

Calculate exactly who qualifies, then send a rendered example only to one of your approved inboxes.

6

Final send

Review the live count, audience, email, sender and timing together. Tick two clear confirmations, then start the campaign. You can see preparation, sends and results, or pause it.

What “final send” actually does: the CRM recalculates the live counts and stops if they changed while you were reviewing. It records one attributed final-review snapshot, freezes the eligible audience in the background, shows how many are scheduled or excluded, then activates the campaign only when preparation is complete. If preparation is interrupted, a visible retry button safely continues without duplicating people.

What has been built

Nurture Email Library with editable header, footer and protected unsubscribe section
Every shared email section is editableHeader, ordinary footer and unsubscribe wording are managed separately. The destination placeholder is structurally protected, then replaced with each recipient's signed unsubscribe address.
Email Nurture campaign list with Duplicate actions
Duplicate without copying live stateEach campaign can become a new draft. Audience journeys, send attempts, tests, launches and approvals are never copied.
Fully populated recipient email preview modal
See exactly what one person would receiveThe popup shows contact, recipient address, personalised subject and full email. It is sandboxed, sends nothing and disables unsubscribe actions.
Six-step campaign workflow assistant
The next action is obviousGreen steps are complete, blue is what staff do now, and grey comes later. The CRM calculates these colours from real campaign evidence.
Audience preview followed by internal test
Preview comes before testStaff first calculate who would receive or be excluded, then render a real example only to an approved owner inbox.
Final campaign review showing audience, email, timing and two confirmations
One informed final decisionThe page states what happens next, who would receive, the named audience, subject, sender, timing, test status and exclusions. The blocked grey button here correctly shows this draft still needs a current internal test.
CRM campaign list
Campaign homeSee Rescue and Nurture campaigns, status, activity, upcoming sends and the next action.
Audience and timing controls
Audience and timing in the same formChoose familiar CRM lists, the send date, local time and volume. Short explanations sit below unfamiliar fields.
Campaign email editor
Editable email and starter libraryPick an idea, then change every word. The campaign owns its copy, so editing cannot alter an old workflow email.
Internal test send and history
Internal Test Send and visible historyChoose the email, approved inbox and a real-looking example. The history shows when, where and whether it was sent.
Two rescue emails and timings
Rescue is already structuredEmail 1 is due 24 hours after the enquiry; Email 2 is due at 72 hours only if the seller is still relevant.
Campaign review and checklist
One clear release checklistThe final-send button stays unavailable until the audience and internal test are confirmed.

Open the latest library and recipient-preview walkthrough · Open the assistant walkthrough · Open the original full Studio walkthrough

The starting campaigns and content

Fast Rescue

Email 1, +24 hours: “Still looking for the right local agent?”
Email 2, +72 hours: one practical question to ask before choosing an agent. The phrase “This is the final rescue email” has been removed.

Seller Nurture

One useful issue at a chosen date and local time. It starts with the monthly local-market context email, but you can replace that issue with any library idea or your own email.

15 editable ideas in the Nurture Library

GroupIdeas ready to editHow to use them
RescueStill looking for the right agent; one useful question before choosingAlready connected to the two-email Rescue draft.
Repeatable contextMonthly local-market update; major interest-rate or market eventAdd two or three current, dated facts before sending.
Seasonal property momentsSpring; end of year; start of year; autumn before winterChoose the relevant issue rather than running an automatic sequence.
Decision insightsHighest appraisal trap; commission versus net result; comparable sales; marketing spend; local track record; auction versus private sale; exclusive agency agreementEvergreen education that helps sellers make a better agent decision.
Important: these are useful first drafts, not automatically current market commentary. Any issue containing market facts has a visible “information current at” date and must be updated before approval.

What the real test proved

SentMonthly Sunbury market context to personal Gmail
SentRescue Email 1 to personal Gmail
AcceptedRescue Email 2 to WREA work email
Nonecustomers, CCs, journeys or CRM activity

The two personal-Gmail messages were found in the inbox immediately after SendGrid accepted them. The work-address message was accepted by SendGrid, but that separate mailbox is not connected for independent inbox reading in this session.

The Test Send boundary held: the server allows only trpersonal@gmail.com and thomasroberts@whichrealestateagent.com.au; it adds [TEST], sends no CC, creates no customer journey, creates no normal CRM email activity and uses only a campaign-owned template.

Will deployment disrupt existing CRM email?

I cannot honestly promise zero deployment risk. The code has been designed so installing it does not start a campaign, but the complete branch also adds the Phase 0 marketing-safety layer. The correct answer is therefore “low and controlled risk”, not “nothing could possibly happen”.

EventWhat happensExisting email impactRelease position
Deploy code and migrationsAdds new screens/tables, suppression capture, marketing send checks, journey panels and an idle 10-minute campaign worker.Transactional email and direct agent digests remain operational and ungated. Vendor digests and mass emails classified as marketing can now stop for a real unsubscribe, complaint, bounce, blacklist or frequency cap. That is intended.STAGED DEPLOY
Run starter installerCreates 15 library templates and two draft campaigns.No enrolments, queue rows or sends. Exact CRM list/source names must resolve or the whole setup stops.SAFE AFTER DEPLOY
Send internal testSends one rendered example to an owner allowlist address.No customer, CC, normal CRM email record or campaign journey.OWNER ONLY
Activate final campaignFreezes the previewed audience and permits scheduled sends.This is the first point at which customer campaign email can occur.SEPARATE APPROVAL

The main deployment risk is database load, not accidental sending

The current production email-history table has about 1.11 million rows, a four-column full-text search index and roughly 514 MiB of data plus indexes. The corrected release does not alter that table at all. It creates a separate attribution table for Campaign Studio metadata. The only sizeable existing-table change left is one non-blocking search index on entity_tags, currently about 924,000 rows, to keep large audience previews efficient.

Still deploy off-peak: every Email Nurture schema change now sets a 60-second database-lock limit. If production is too busy, deployment stops clearly instead of waiting indefinitely. The corrected migration was rolled back and reapplied on MySQL 8.0.45 with the same full-text email-table shape as production; the email-history table remained unchanged. Felix should still watch RDS load and CRM latency while the entity_tags index is created.

Remaining operational checks before the first customer activation

The exact path from here to live and operational

The path is now a controlled release sequence, not more product design. Merge and CI first; staged deployment switches on the protections but creates no campaign audience; operational gates then prove production data and delivery; only after those gates do you use the Studio to start a campaign.

OrderActionOwnerProof required before continuingCan customers receive email?
1Review the open PR, run normal CI and merge only when it is green.Felix + reviewerCI green; corrected companion-table migrations and classification boundaries reviewed; no unresolved PR finding.NO
2Deploy code and migrations off-peak. Do not run the starter installer yet.FelixMigration completes without lock/latency incident; CRM, existing workflow email, direct agent digests and queue workers remain healthy.NO CAMPAIGN
3Re-run the production workflow inventory and compare it with the known baseline of 36 active unclassified actions and 5,969 pending rows.FelixNo unexpected marketing classification; no legacy workflow silently moved behind suppression.NO
4Run suppression backfill in preview mode, reconcile totals and samples, then execute the controlled backfill.Felix, reviewed by ThomasUnsubscribe, complaint, bounce and invalid-address counts make sense; suppression register is visible in CRM.NO CAMPAIGN
5Confirm SendGrid webhook signature, sender/from/reply-to settings, scheduler and queue-worker health.FelixSigned event path works; five workers healthy; default queue below the 500-job nurture brake.NO
6Install the 15 library ideas and two starter campaigns as drafts.FelixTwo drafts, zero enrolments, zero send attempts, zero queued nurture email.NO
7Thomas edits Rescue and the first Nurture issue in Campaign Studio, previews the exact audience and opens named-contact email previews.ThomasContent, personalisation, audience, exclusions, date, sender and local timing look correct.NO
8Send internal tests only to the two approved owner addresses and test Gmail/Outlook, links and unsubscribe end to end.Thomas + FelixEvery current campaign email has a successful test matching its latest fingerprint.OWNER ONLY
9Open Final Review, confirm the recalculated count and email/sender/timing, then tick the two informed checkboxes.ThomasThe final page states exactly which email, audience, volume and time will run. Any drift forces refresh.AFTER FINAL ACTION
10Start with the small Rescue pilot; run the first large Nurture issue at 500–1,000/hour and monitor CRM/RDS before increasing later issues.Thomas + FelixDelivery, unsubscribe, complaint, queue, CRM latency and conversion results remain within agreed limits.YES
What “deployment switches on the protections” means: the Phase 0 safety checks begin protecting messages already identified as marketing, such as vendor digests and staff mass email. Transactional, operational and currently unclassified workflow email retain their existing route. Deployment does not install, activate or enrol either starter campaign.
Important precision: it would be misleading to say deployment is literally unable to affect any existing CRM email. It intentionally stops an existing marketing-class send when the address has valid suppression evidence. What is proven is the boundary: direct agent digests, operational staff messages, transactional messages and all currently unclassified workflow actions remain outside that new gate, while no Campaign Studio customer send can happen merely because code was deployed.

Felix: cold-start feature and PR brief

Purpose: WREA needs a simple staff-operated system for two different jobs: (1) an always-on, two-step rescue for recent stalled seller enquiries and (2) one-off useful seller emails for market context, major events, seasonal moments and decision insights. The feature is deliberately separate from the legacy workflow engine so marketing safety, audience preview, attribution and launch evidence are consistent.

What is in the branch

Phase 0: safety layer

Central communication-purpose classification; address-level suppression register; SendGrid event projection; one-click unsubscribe; pre-send and queued-job rechecks; configurable marketing frequency cap; audit/backfill commands; transactional/operational exclusions.

Phase 1: Fast Rescue

Recent stalled enquiry cohort, +24h and +72h messages, 20% stable measurement holdout, 14-day staff-touch protection, live relevance recheck, 07:00–21:00 property-local window, journey status and campaign reporting.

Phase 2 foundation

Named CRM marketing-list audience, zero utility holdout, one issue per campaign, current-information date, local send time, hourly throttle, shared-queue brake, 15 starter ideas and a draft-only installer.

Campaign Studio and Library

Six-step assistant; campaign create/edit/duplicate; independently owned template copies; editable shared header/footer/unsubscribe snapshot; exact audience and recipient previews; owner-only tests; two-checkbox final review; launch retry; pause/resume; results and journey visibility.

Core architecture and invariants

AreaImplementation shapeInvariant Felix should verify
Purpose boundaryEmailSendContext classifies marketing versus operational/unclassified independently of SendGrid IP pool.Marketing IP never implies marketing purpose. Direct agent digest and staff operational paths remain ungated.
Eligibility and suppressionOne suppression service normalises addresses and checks unsubscribe, complaint, bounce, invalid, blacklist, frequency and campaign-specific context.Campaign Studio checks before preparation and again immediately before provider send; transactional/operational email is not blocked.
AudienceRescue and Utility audience services build bounded cohorts in bulk. Preview explains receive, holdout and exclusion outcomes.No N+1 contact preview path; launch freezes the same recalculated cohort and fails on count/fingerprint drift.
Content ownershipLibrary templates are starting points. Campaign creation/selection makes a campaign-owned copy.Editing/deleting a library idea cannot mutate an existing campaign or legacy workflow template.
Layout renderingNurtureEmailLayoutService snapshots header, footer, unsubscribe HTML and checksum. NurtureEmailRenderer is shared by preview, test and delivery.Legacy SimpleBody callers retain the original fallback. The editable section must contain exactly one visible linked @UNSUBSCRIBE_URL@; the real signed URL is escaped and inserted after merge-tag parsing.
Test evidenceEach successful internal test stores campaign, step, template, recipient, rendered body and a full campaign fingerprint.Any audience, settings, template or layout change invalidates the old test and final review.
LaunchFinal review stores attributed audience/count/content evidence. Preparation is transactional and retry-safe; activation follows completed preparation.No draft, test send, deployment or installer operation can create a customer send. Retry does not duplicate enrolments.
Runtimeemail-nurture:tick wakes every ten minutes, finds due work and honours local send windows, per-hour limits and queue capacity.“Every ten minutes” is a scheduler check, not a ten-minute email cadence. Provider-boundary ambiguity stops for reconciliation instead of blind retry.
AttributionCampaign/step/enrolment/attempt metadata is stored in the new email_message_attributions companion table and custom arguments round-trip through SendGrid events; rendered HTML remains in normal CRM email history.msg_emails is never altered. Reporting can still connect send, delivery/event evidence and campaign journey without subject-line parsing.

Locked product assumptions

PR review checklist for Felix

  1. Confirm the branch is based on pre_production, the implementation is split into clear atomic commits, and generated review artifacts are absent from the product repository.
  2. Inspect every changed legacy send call site and confirm direct agent digest/operational classification tests match its real business purpose.
  3. Review the MySQL 8.0.44 correction: no Email Nurture migration may alter msg_emails; attribution belongs in the companion table; all DDL uses the 60-second metadata-lock guard; the entity_tags index remains online and off-peak.
  4. Trace one Rescue and one Utility message through preview → test → final review → launch → tick → SendGrid event → report.
  5. Verify the unsubscribe webhook/signature route, list-unsubscribe headers, suppression backfill idempotence and lift-suppression audit trail.
  6. Verify no installer, migration, scheduler tick or deployment path creates enrolments for a draft campaign.
  7. Run full CI in addition to the green local result of 605 tests / 1,832 assertions. The formerly missing local scraper fixture was restored and the complete feature suite now passes without an exclusion.
  8. Do not combine workflow reclassification, copy approval or customer campaign activation into this PR/deployment decision.

Deployment and rollback notes

Deploy application code and migrations off-peak, then stop before the starter installer. If migration or smoke evidence is unhealthy, roll back the application release before any drafts or enrolments exist; do not run destructive down-migrations against large production tables as the first response. Once the safety layer is healthy, use email-nurture:audit-workflows --production --dry-run, run email-nurture:backfill-suppressions without --execute, reconcile, then execute in a controlled run. The starter installer must use exact production names and --execute; it fails closed and creates drafts only.

Recommended next steps

  1. Recommended now: complete PR and CI review only. The branch and production-compatibility correction are pushed to the open PR. This does not approve merge, deployment or customer email.
  2. After CI and Felix's cold-start review are green, approve the off-peak staged deployment. Stop after smoke checks.
  3. Complete the workflow audit, suppression backfill reconciliation, webhook/sender verification and queue-health gates.
  4. Install only the draft library and starter campaigns. Thomas then reviews content and exact audience previews inside the CRM.
  5. Run owner-only Test Sends, verify rendering and unsubscribe, then return to Final Review for the separate first-pilot decision.
The boundary remains explicit: built and tested is not deployed; deployed is not an active campaign; an active campaign still requires your separate final-send action.

Caveats and assumptions

The screenshots use a sanitised isolated test database and deliberately fake names. The personal Gmail receipt check covers the two messages sent there, not the separate WREA inbox. The production infrastructure figures are point-in-time and recent-window observations, not a load test. The complete local result is 605 tests / 1,832 assertions: 357 unit tests / 948 assertions and 248 feature tests / 884 assertions. The MySQL migration was also rolled back and reapplied against a production-shaped local MySQL 8.0.45 schema with the full-text email index intact and none of the rejected columns present. The earlier Claude GO applied before the fresh release audit and is withdrawn; the current joint Codex and Claude verdict is NO-GO. The branch and correction are pushed to PR #4464, but nothing has been merged or deployed; no production database write or customer send occurred.