Skip to main content

CRM & Marketing Platform Specification

Version: 2.0 Date: December 2024 Status: Draft


Table of Contents

  1. Executive Summary
  2. Goals & Non-Goals
  3. Architecture Overview
  4. Core Concepts
  5. Identity Resolution
  6. Activity Timeline
  7. Engagement Scoring
  8. Segmentation
  9. Campaign Management
  10. Marketing Automation
  11. Social Integration
  12. Event Promotion
  13. Event Integration
  14. API Design
  15. Data Model Summary
  16. Security & Privacy
  17. Performance Requirements
  18. Rollout Plan

1. Executive Summary

What is the CRM & Marketing Platform?

A unified customer intelligence and marketing platform that:

  1. Aggregates customer data from SCL (membership), TeeTime (golf), and Messaging (communications)
  2. Enables smart segmentation using cross-service data
  3. Automates marketing campaigns and customer journeys
  4. Publishes content to social media platforms
  5. Promotes events and tournaments across all channels

The Four Pillars

┌─────────────────────────────────────────────────────────────────────────────┐
│ CRM & MARKETING PLATFORM │
├─────────────────┬─────────────────┬─────────────────┬─────────────────────┤
│ CUSTOMER │ MARKETING │ CAMPAIGN │ SOCIAL │
│ INTELLIGENCE │ AUTOMATION │ MANAGER │ INTEGRATION │
├─────────────────┼─────────────────┼─────────────────┼─────────────────────┤
│ • Unified │ • Journeys │ • Segments │ • FB/IG/Twitter │
│ Profiles │ • Triggers │ • Targeting │ • Event Promotion │
│ • Timeline │ • Scheduling │ • A/B Testing │ • Content Calendar │
│ • Scoring │ • Sequences │ • Analytics │ • Engagement │
└─────────────────┴─────────────────┴─────────────────┴─────────────────────┘

Why Build It?

Current ProblemPlatform Solution
Member in SCL ≠ Player in TeeTime ≠ Contact in MessagingUnified CustomerProfile with identity resolution
Staff manually cross-reference systemsSingle API/UI for 360° view
No way to identify at-risk membersEngagement scoring + churn prediction
Basic segmentation on Contact data onlySmart segments using cross-service data
Manual campaign creation and sendsAutomated journeys and triggers
Separate tools for social mediaIntegrated social publisher
Manual tournament promotionAuto-promotion to all channels

Key Design Decision: Service Boundaries

ServiceResponsibilityOwns
CRM/Marketing PlatformWHO, WHAT, WHEN, WHEREProfiles, Segments, Campaigns, Automation, Social
Messaging ServiceHOW (delivery)Templates, Multi-channel delivery, Consent, Providers
SCL ServiceMembership dataMembers, Tiers, Payments → publishes events
TeeTime ServiceGolf dataPlayers, Bookings, Tournaments → publishes events

Consent Management: Messaging service owns consent (GDPR/POPIA compliance). CRM denormalizes opt-in flags for query convenience but does NOT manage consent.


2. Goals & Non-Goals

Goals

#GoalPriorityPhase
G1Unified customer profile across all servicesP01
G2Identity resolution with multi-key matchingP01
G3Activity timeline aggregationP02
G4Smart segmentation (cross-service data)P03
G5Campaign manager (create, schedule, target)P13
G6Customer notes and tagsP12
G7Engagement scoringP17
G8Marketing automation (journeys, triggers)P24
G9Social integration (FB, IG, Twitter)P25
G10Event/tournament promotionP25
G11Churn risk predictionP27
G12A/B testingP34
G13Content calendarP35

Non-Goals

#Non-GoalReason
NG1Replace SCL for membership managementSCL remains source of truth
NG2Replace TeeTime for bookingsTeeTime remains source of truth
NG3Send messages directlyMessaging service handles delivery
NG4Process paymentsSCL Billing handles payments
NG5Manage consentMessaging owns consent (legal compliance)
NG6Real-time sync (under 100ms)Near real-time (seconds) is sufficient
NG7Social inbox/DM managementFuture scope

3. Architecture Overview

High-Level Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│ EXTERNAL CLIENTS │
│ (Admin UI, Mobile App, Staff Portal, Club Dashboard) │
└─────────────────────────────────────┬───────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────────────────┐
│ CRM & MARKETING PLATFORM │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ REST/ │ │ Identity │ │ Campaign │ │ Social │ │
│ │ GraphQL │ │ Resolution │ │ Orchestrator│ │ Publisher │ │
│ │ API │ │ Engine │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Activity │ │ Engagement │ │ Journey │ │ Event │ │
│ │ Timeline │ │ Scoring │ │ Engine │ │ Promoter │ │
│ │ Aggregator │ │ Engine │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │ │
│ └────────────────┴────────────────┴────────────────┘ │
│ │ │
│ ┌───────▼───────┐ │
│ │ CRM Database │ │
│ │ (PostgreSQL) │ │
│ └───────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Messaging │ │ Social APIs │ │ SCL / TeeTime │
│ Service │ │ (FB, IG, X) │ │ (Events) │
│ ───────────── │ │ │ │ │
│ Delivery │ │ Publishing │ │ DomainOutbox │
│ Consent │ │ Engagement │ │ │
└───────────────┘ └───────────────┘ └───────────────┘

Technology Stack

ComponentTechnologyRationale
APINestJS + GraphQLConsistent with existing services
DatabasePostgreSQLConsistent with existing services
ORMPrismaConsistent with existing services
Event TransportRedis + BullMQAlready in use, sufficient for v1
CacheRedisFast profile lookups
SearchPostgreSQL FTS (v1), Elasticsearch (v2)Start simple, scale later
Social APIsOfficial SDKsFacebook, Instagram, Twitter
Job SchedulingBullMQ + cronCampaign scheduling

4. Core Concepts

CustomerProfile

The central entity representing a single customer across all systems.

interface CustomerProfile {
id: string; // CRM's own UUID
tenantId: string; // Multi-tenant isolation

// Identity Keys (at least one required)
authUserId?: string; // IDP user ID (strongest link)
email?: string; // Normalized email
phoneNumber?: string; // E.164 phone

// Cross-Service Links
sclMemberId?: number; // SCL.Member.id
teetimePlayerId?: string; // TeeTime.Player.id
messagingContactId?: string; // Messaging.Contact.id

// External IDs
externalIds: {
mcaV1ZaId?: string; // MCA v1 ZA ID
mcaV1UkId?: string; // MCA v1 UK ID
golfRsaId?: string; // GolfRSA ID
};

// Denormalized Profile
firstName?: string;
lastName?: string;
displayName?: string;

// CRM Data
status: CustomerStatus;
lifecycleStage: LifecycleStage;
tags: string[];

// Computed Scores
engagementScore?: number; // 0-100
churnRiskScore?: number; // 0-100
lifetimeValue?: number; // Cents

// Activity Metrics (denormalized)
lastActivityAt?: Date;
activityCount30d: number;
bookingCount30d: number;

// Golf Data (from TeeTime)
handicap?: number;
homeClubId?: string;

// Membership Data (from SCL)
membershipTier?: string;
membershipStatus?: string;

// Marketing Consent (synced from Messaging - READ ONLY)
emailOptIn: boolean;
smsOptIn: boolean;
pushOptIn: boolean;
whatsappOptIn: boolean;
}

Activity

A single interaction or event in the customer's timeline.

interface Activity {
id: string;
customerId: string;

type: ActivityType; // e.g., TEETIME_BOOKED, MESSAGE_SENT
category: ActivityCategory; // e.g., BOOKING, COMMUNICATION
channel?: string; // e.g., SMS, EMAIL, IN_PERSON

title: string; // Human-readable summary
description?: string;
metadata?: object;

sourceService: string; // scl, teetime, messaging
sourceId?: string; // Original record ID

occurredAt: Date;
}

Campaign

A marketing campaign targeting a segment.

interface Campaign {
id: string;
tenantId: string;
clubId?: string;

name: string;
type: CampaignType; // ONE_TIME, RECURRING, TRIGGERED, JOURNEY
status: CampaignStatus; // DRAFT, SCHEDULED, ACTIVE, PAUSED, COMPLETED

// Targeting
segmentId?: string;

// Channels
channels: Channel[]; // EMAIL, SMS, PUSH, SOCIAL

// Schedule
scheduledAt?: Date;
timezone?: string;

// Stats
sentCount: number;
openRate?: number;
clickRate?: number;
}

5. Identity Resolution

The Challenge

A single person may exist as:

  • Member in SCL (joined via membership signup)
  • Player in TeeTime (booked as a guest)
  • Contact in Messaging (received a campaign)

We need to determine: Are these the same person?

Resolution Strategy

┌─────────────────────────────────────────────────────────────────┐
│ IDENTITY RESOLUTION FLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Incoming Event (e.g., member.created) │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ 1. Extract identifiers │ │
│ │ - authUserId (if present) │ │
│ │ - email (normalized) │ │
│ │ - phoneNumber (E.164) │ │
│ └───────────────────┬───────────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ 2. Match by authUserId (exact) │◄─── Strongest │
│ └───────────────────┬───────────────────┘ │
│ │ No match? │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ 3. Match by email (normalized) │◄─── Strong │
│ └───────────────────┬───────────────────┘ │
│ │ No match? │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ 4. Match by phone (E.164) │◄─── Moderate │
│ └───────────────────┬───────────────────┘ │
│ │ No match? │
│ ▼ │
│ ┌───────────────────────────────────────┐ │
│ │ 5. Create new CustomerProfile │ │
│ └───────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Match Confidence

Match TypeConfidenceAction
authUserId exact100%Auto-link
email exact95%Auto-link
phone exact85%Auto-link
email + phone99%Auto-link
name fuzzy + email domain60%Flag for review

6. Activity Timeline

Event Sources

Source ServiceEventsCategory
SCLmember.created, member.updated, tier.changed, payment.receivedMEMBERSHIP, FINANCIAL
TeeTimeteetime.booked, teetime.completed, handicap.updated, competition.enteredBOOKING, GOLF
Messagingmessage.sent, message.delivered, email.opened, email.clickedCOMMUNICATION, ENGAGEMENT
CRMnote.added, tag.changed, profile.merged, campaign.sentSUPPORT, MARKETING, SYSTEM

Activity Categories

enum ActivityCategory {
MEMBERSHIP // Tier changes, signup, cancellation
BOOKING // Tee times, facility bookings
COMMUNICATION // Messages sent/received
ENGAGEMENT // Opens, clicks, responses
FINANCIAL // Payments, invoices
GOLF // Handicap, competitions, scores
MARKETING // Campaign interactions
SUPPORT // Notes, tickets
SOCIAL // Social media interactions
SYSTEM // Merges, imports, syncs
}

7. Engagement Scoring

Score Components

ComponentWeightData SourceCalculation
Recency30%Last activityDays since last interaction
Frequency25%Activity countActivities per month
Monetary20%SCL paymentsTotal spend / LTV
Breadth15%Channel usageUnique channels engaged
Depth10%EngagementOpen rate, click rate

Churn Risk Factors

Risk FactorWeightIndicator
Activity decline35%50%+ drop in activity
Payment issues25%Failed payments, overdue
Engagement drop20%Stopped opening emails
Tier downgrade10%Recent tier reduction
Complaints10%Support tickets, negative feedback

8. Segmentation

Key Design: CRM Owns Segmentation

CRM defines segments using rich cross-service data. Messaging executes delivery.

CRM                                    Messaging
┌─────────────────────┐ ┌─────────────────────┐
│ CustomerSegment │ │ Segment (simplified)│
│ ─────────────────── │ sync │ ─────────────────── │
│ Rules using: │ ──────────────▶│ Contact membership │
│ - SCL tier │ │ only (for delivery) │
│ - TeeTime bookings │ │ │
│ - CRM engagement │ │ │
│ - Messaging consent │ │ │
└─────────────────────┘ └─────────────────────┘

Segment Types

TypeDescriptionExample
StaticManual membership"VIP List", "Board Members"
DynamicRule-based, auto-computed"Active members with handicap < 10"
SmartML-powered"Likely to churn in 30 days"

Dynamic Segment Rules

Segments can use data from ALL services:

const activeGolferSegment = {
name: "Active Golfers - Low Handicap",
rules: [
// From SCL
{ field: "membershipStatus", operator: "eq", value: "ACTIVE" },
{ field: "membershipTier", operator: "in", value: ["Gold", "Platinum"] },

// From TeeTime (denormalized)
{ field: "handicap", operator: "lt", value: 15 },
{ field: "bookingCount30d", operator: "gte", value: 2 },

// From CRM
{ field: "engagementScore", operator: "gte", value: 50 },

// From Messaging (denormalized consent)
{ field: "emailOptIn", operator: "eq", value: true }
],
combinator: "AND"
};

9. Campaign Management

Campaign Types

TypeDescriptionUse Case
ONE_TIMESingle sendTournament announcement
RECURRINGScheduled repeatsWeekly newsletter
TRIGGEREDEvent-basedBooking confirmation
JOURNEYMulti-step sequenceOnboarding series

Campaign Workflow

┌─────────────────────────────────────────────────────────────────┐
│ CAMPAIGN LIFECYCLE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ DRAFT ──▶ SCHEDULED ──▶ ACTIVE ──▶ COMPLETED │
│ │ │ │ │
│ │ │ ▼ │
│ │ │ PAUSED ─────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ Edit Edit/Cancel Resume/Cancel │
│ │
└─────────────────────────────────────────────────────────────────┘

Campaign Creation Flow

// 1. Create campaign
const campaign = await createCampaign({
name: "Summer Tournament 2024",
type: "ONE_TIME",
segmentId: "active-golfers-segment-id",
channels: ["EMAIL", "SMS", "FACEBOOK"],
scheduledAt: "2024-06-01T09:00:00Z",
timezone: "Africa/Johannesburg"
});

// 2. Configure channel content
await setCampaignContent(campaign.id, {
email: { templateId: "tournament-invite-email" },
sms: { templateId: "tournament-invite-sms" },
social: {
content: "Join us for the Summer Tournament 2024!",
mediaUrls: ["https://..."],
platforms: ["FACEBOOK", "INSTAGRAM"]
}
});

// 3. Schedule sends
await scheduleCampaign(campaign.id);
// → Creates jobs in BullMQ
// → Email/SMS → Messaging Service
// → Social → Social Publisher

10. Marketing Automation

Journey Builder

Multi-step automated sequences triggered by events or schedules.

┌─────────────────────────────────────────────────────────────────┐
│ NEW MEMBER ONBOARDING JOURNEY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [TRIGGER: member.created] │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ SEND Welcome │ │
│ │ Email │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ WAIT 3 days │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ YES ┌─────────────────┐ │
│ │ CONDITION: │───────────▶│ SEND Tips Email │ │
│ │ Opened welcome? │ └─────────────────┘ │
│ └────────┬────────┘ │
│ │ NO │
│ ▼ │
│ ┌─────────────────┐ │
│ │ SEND SMS │ │
│ │ Reminder │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ WAIT 7 days │ │
│ └────────┬────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ END │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Event Triggers

Trigger EventSourcePossible Actions
member.createdSCLWelcome sequence
teetime.bookedTeeTimeBooking confirmation
teetime.completedTeeTimeReview request
handicap.updatedTeeTimeCongratulations message
payment.failedSCLPayment reminder
engagement.droppedCRMWin-back campaign
competition.publishedTeeTimeTournament promotion

Journey Step Types

TypeDescriptionConfiguration
SENDSend messagechannel, templateId
WAITDelay next stepduration (e.g., "3 days")
CONDITIONBranch based on criteriacondition, nextStepYes, nextStepNo
SPLITA/B testvariants[], splitPercentage
ENDTerminate journey-

11. Social Integration

Supported Platforms

PlatformAPIFeatures
FacebookGraph APIPages, Posts, Events
InstagramGraph API (via FB)Business posts, Stories
Twitter/XAPI v2Tweets, Media
LinkedInMarketing APICompany pages (future)

Social Connection Flow

┌─────────────────────────────────────────────────────────────────┐
│ SOCIAL CONNECTION OAUTH FLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Club Admin CRM Platform Facebook │
│ │ │ │ │
│ │ 1. Click "Connect FB" │ │ │
│ │─────────────────────────▶│ │ │
│ │ │ │ │
│ │ │ 2. Redirect to OAuth │ │
│ │◀─────────────────────────│───────────────────────▶│ │
│ │ │ │ │
│ │ 3. Authorize app │ │ │
│ │──────────────────────────────────────────────────▶│ │
│ │ │ │ │
│ │ 4. Callback with token │ │ │
│ │◀─────────────────────────│◀───────────────────────│ │
│ │ │ │ │
│ │ │ 5. Store encrypted │ │
│ │ │ token │ │
│ │ │─────────┐ │ │
│ │ │ │ │ │
│ │ │◀────────┘ │ │
│ │ │ │ │
│ │ 6. Connection saved │ │ │
│ │◀─────────────────────────│ │ │
│ │
└─────────────────────────────────────────────────────────────────┘

Social Post Publishing

interface SocialPost {
id: string;
tenantId: string;

connectionId: string; // Which social account
campaignId?: string; // Optional campaign link

content: string; // Post text
mediaUrls: string[]; // Images/videos
linkUrl?: string; // Link preview

status: SocialPostStatus; // DRAFT, SCHEDULED, PUBLISHED
scheduledAt?: Date;
publishedAt?: Date;

platformPostId?: string; // ID returned by platform

// Engagement metrics (synced)
likes: number;
comments: number;
shares: number;
reach: number;
}

12. Event Promotion

Auto-Promotion for Tournaments

When a competition is published in TeeTime, CRM can automatically:

  1. Create campaign targeting relevant segment
  2. Generate content from competition details
  3. Schedule posts across all channels
  4. Send reminders as event approaches
┌─────────────────────────────────────────────────────────────────┐
│ EVENT PROMOTION WORKFLOW │
├─────────────────────────────────────────────────────────────────┤
│ │
│ TeeTime CRM Platform │
│ │ │ │
│ │ competition.published │ │
│ │──────────────────────────────▶│ │
│ │ │ │
│ │ │ Check auto-promote │
│ │ │ settings for club │
│ │ │─────────┐ │
│ │ │ │ │
│ │ │◀────────┘ │
│ │ │ │
│ │ │ If enabled: │
│ │ │ │
│ │ │ 1. Create campaign │
│ │ │ 2. Build segment │
│ │ │ 3. Generate content │
│ │ │ 4. Schedule: │
│ │ │ - Email blast │
│ │ │ - Social posts │
│ │ │ - SMS reminder │
│ │ │ │
└─────────────────────────────────────────────────────────────────┘

EventPromotion Configuration

interface EventPromotion {
id: string;
tenantId: string;
clubId: string;

// Source
sourceType: 'COMPETITION' | 'CLUB_EVENT';
sourceId: string; // TeeTime competition ID

// Settings
autoPromote: boolean;
channels: Channel[]; // EMAIL, SMS, FACEBOOK, INSTAGRAM

// Timing
announceAt: Date; // Initial announcement
reminderDays: number[]; // Days before: [7, 3, 1]

// Targeting
segmentId?: string; // Custom segment
targetRadius?: number; // km from club for geo

// Content
emailTemplateId?: string;
smsTemplateId?: string;
socialContent?: string;
}

13. Event Integration

Event Transport

Phase 1: Redis + BullMQ (existing infrastructure)

Events Consumed

SourceEventCRM Action
SCLmember.createdCreate/link profile, activity
SCLmember.updatedUpdate profile, activity
SCLtier.changedUpdate tier, activity, rescore
SCLpayment.receivedUpdate LTV, activity
TeeTimeplayer.createdCreate/link profile, activity
TeeTimeteetime.bookedActivity, update frequency
TeeTimeteetime.completedActivity, trigger review
TeeTimecompetition.publishedAuto-promote (if enabled)
TeeTimehandicap.updatedActivity, update handicap
Messagingmessage.sentActivity
Messagingmessage.deliveredActivity
Messagingemail.openedActivity, engagement
Messagingemail.clickedActivity, engagement
MessagingcontactPreference.updatedUpdate opt-in flags

Events Produced

EventTriggerConsumers
crm.profile.createdNew profileAnalytics
crm.profile.mergedDuplicate mergeMessaging (update contact)
crm.segment.membership.changedSegment refreshMessaging (sync)
crm.campaign.scheduledCampaign createdJob scheduler
crm.campaign.sentCampaign executedAnalytics
crm.churn.risk.highRisk score > 80Alerting

14. API Design

REST Endpoints Summary

# Customer Profiles
GET /api/v1/customers
GET /api/v1/customers/:id
GET /api/v1/customers/resolve
POST /api/v1/customers
PATCH /api/v1/customers/:id
POST /api/v1/customers/:id/merge

# Activity Timeline
GET /api/v1/customers/:id/activities
POST /api/v1/customers/:id/activities

# Notes
GET /api/v1/customers/:id/notes
POST /api/v1/customers/:id/notes

# Segments
GET /api/v1/segments
POST /api/v1/segments
GET /api/v1/segments/:id/members
POST /api/v1/segments/:id/refresh
POST /api/v1/segments/:id/sync-to-messaging

# Campaigns
GET /api/v1/campaigns
POST /api/v1/campaigns
GET /api/v1/campaigns/:id
PATCH /api/v1/campaigns/:id
POST /api/v1/campaigns/:id/schedule
POST /api/v1/campaigns/:id/pause
POST /api/v1/campaigns/:id/resume

# Journeys
GET /api/v1/journeys
POST /api/v1/journeys
GET /api/v1/journeys/:id/steps
POST /api/v1/journeys/:id/activate

# Social
GET /api/v1/social/connections
POST /api/v1/social/connections/connect
DELETE /api/v1/social/connections/:id
GET /api/v1/social/posts
POST /api/v1/social/posts
POST /api/v1/social/posts/:id/publish

# Event Promotion
GET /api/v1/promotions
POST /api/v1/promotions
PATCH /api/v1/promotions/:id

# Analytics
GET /api/v1/analytics/engagement
GET /api/v1/analytics/campaigns
GET /api/v1/analytics/social

15. Data Model Summary

See Data Model for complete Prisma schema.

Core Tables

TablePurpose
CustomerProfileUnified customer record
IdentityAliasAdditional emails/phones
ActivityTimeline events
CustomerNoteStaff notes
CustomerSegmentSegment definitions
CustomerSegmentMembershipSegment membership

Campaign Tables

TablePurpose
CampaignCampaign definitions
CampaignInteractionEngagement tracking
JourneyMulti-step automation
JourneyStepIndividual journey steps
JourneyEnrollmentCustomer journey progress

Social Tables

TablePurpose
SocialConnectionOAuth connections
SocialPostScheduled/published posts
EventPromotionAuto-promotion config

Sync & Audit Tables

TablePurpose
SyncLogEvent processing audit
CrmAuditLogCRM changes audit
DuplicateCandidatePotential duplicates

16. Security & Privacy

Multi-Tenancy

  • All queries filtered by tenantId
  • Row-level security enforced
  • No cross-tenant data leakage

Authentication & Authorization

  • API authenticated via existing IDP tokens
  • Role-based access:
    • crm:read - View profiles, timeline
    • crm:write - Add notes, tags
    • crm:campaigns - Manage campaigns
    • crm:social - Manage social connections
    • crm:admin - Merge profiles, manage segments

Social Token Security

  • OAuth tokens encrypted at rest
  • Refresh tokens stored separately
  • Token expiry monitored and auto-refreshed

Data Privacy

  • Consent flags synced from Messaging (read-only)
  • GDPR right-to-erasure supported
  • PII encrypted at rest
  • Audit log for all data access

17. Performance Requirements

MetricTarget
Profile lookupunder 100ms p99
Timeline queryunder 500ms p99
Segment refreshunder 30 seconds for 10k members
Campaign schedulingunder 5 seconds
Social post publishunder 10 seconds
Event processingunder 5 seconds

18. Rollout Plan

Phase 1: Foundation (MVP)

  • Database schema and migrations
  • Identity resolution service
  • Profile CRUD API
  • Basic event consumption

Phase 2: Timeline & Notes

  • Activity model and API
  • SCL/TeeTime/Messaging event integration
  • Customer notes

Phase 3: Marketing Core

  • Segment management (CRM-owned)
  • Segment sync to Messaging
  • Campaign manager
  • Basic scheduling

Phase 4: Automation

  • Journey builder
  • Event triggers
  • A/B testing

Phase 5: Social Integration

  • Social connections (OAuth)
  • Social publisher
  • Event promotion
  • Content calendar

Phase 6: Backfill

  • MCA v1 ZA migration
  • MCA v1 UK migration
  • Data reconciliation

Phase 7: Intelligence

  • Engagement scoring
  • Churn prediction
  • Analytics dashboard

Appendix A: Glossary

TermDefinition
CustomerProfileUnified record representing a single customer
Identity ResolutionProcess of matching records across services
ActivitySingle event in customer timeline
CampaignMarketing communication to a segment
JourneyMulti-step automated sequence
SegmentGroup of customers sharing characteristics