Skip to main content

ComplyAI Data Lineage

Understanding how data flows through ComplyAI systems


Overview

Data lineage maps show how data moves from source to destination, including all transformations along the way. This documentation helps you understand where data comes from, how it's processed, and where it ends up.


High-Level Data Flow

┌─────────────────────────────────────────────────────────────────────────────────┐
│ COMPLYAI DATA FLOW │
└─────────────────────────────────────────────────────────────────────────────────┘

SOURCES PROCESSING DESTINATIONS
─────── ────────── ────────────

┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Meta │──webhooks──▶ │ Maestro │──results──────▶│ PostgreSQL │
│Graph API │ │ (ML/AI) │ │ Database │
└──────────┘ └──────────────┘ └──────────────┘
│ │ │
│ │ │
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ User │──uploads───▶ │ Core API │──sync────────▶│ Frontend │
│ Portal │ │ (Flask) │ │ Dashboard │
└──────────┘ └──────────────┘ └──────────────┘
│ │ │
│ │ │
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Stripe │──webhooks──▶ │ Main API │──events──────▶│ Slack │
│ Billing │ │ (Flask) │ │ Alerts │
└──────────┘ └──────────────┘ └──────────────┘

Detailed Lineage Maps

1. User Registration & Organization Setup

┌─────────────────────────────────────────────────────────────────────────────┐
│ USER ONBOARDING DATA FLOW │
└─────────────────────────────────────────────────────────────────────────────┘

Step 1: User Signs Up
────────────────────
Auth0/OAuth Core API PostgreSQL
────────── ───────── ──────────

┌─────────────┐ auth token ┌─────────────┐ INSERT ┌─────────────┐
│ User clicks │──────────────▶ │ /auth/login │──────────▶ │ users │
│ "Sign Up" │ │ endpoint │ │ table │
└─────────────┘ └─────────────┘ └─────────────┘

│ Create default role

┌─────────────┐
│ roles_users │
│ (client) │
└─────────────┘

Step 2: Create Organization
───────────────────────────
Frontend Form Core API PostgreSQL
───────────── ───────── ──────────

┌─────────────┐ POST ┌─────────────┐ INSERT ┌─────────────┐
│ Org Name │──────────────▶ │ /orgs/ │──────────▶ │organizations│
│ Contact │ │ create │ │ table │
└─────────────┘ └─────────────┘ └─────────────┘

│ Link user to org

┌──────────────────┐
│ user_organizations│
└──────────────────┘

Step 3: Connect Meta Business Manager
─────────────────────────────────────
Meta OAuth Core API PostgreSQL
────────── ───────── ──────────

┌─────────────┐ access ┌─────────────┐ INSERT ┌─────────────────┐
│ User grants │──────token───▶ │ /fb/ │──────────▶ │org_business_ │
│ BM access │ │ connect_bm │ │accounts │
└─────────────┘ └─────────────┘ └─────────────────┘

│ Exchange for system user token

┌──────────────────┐
│Meta Business │
│Manager API │
└──────────────────┘

2. Ad Account Synchronization

┌─────────────────────────────────────────────────────────────────────────────┐
│ AD ACCOUNT SYNC DATA FLOW │
└─────────────────────────────────────────────────────────────────────────────┘

Trigger: Scheduled Celery Task (every 15 minutes)
─────────────────────────────────────────────────

PostgreSQL Meta Graph API PostgreSQL
────────── ────────────── ──────────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│org_business_ │ token │GET /v19.0/ │ ad accounts │ad_accounts │
│accounts │─────────▶│{bm_id}/owned_ │──────────────▶│table │
│(get tokens) │ │ad_accounts │ │ │
└───────────────┘ └───────────────┘ └───────────────┘

│ For each ad account

┌───────────────┐ ┌───────────────┐
│GET /v19.0/ │ ad data │org_ad_accounts│
│act_{id} │──────────────▶│table │
│?fields=... │ │ │
└───────────────┘ └───────────────┘

Data Transformations:
────────────────────
┌──────────────────────────────────────────────────────────────────────────┐
│ Source (Meta API) │ Transformation │ Destination │
├──────────────────────────────────────────────────────────────────────────┤
│ account_id: "123456789" │ Add prefix │ facebook_id: │
│ │ │ "act_123456789" │
├──────────────────────────────────────────────────────────────────────────┤
│ amount_spent: "15000.50" │ Convert to cents │ amount_spent: │
│ (string, dollars) │ (integer) │ 1500050 │
├──────────────────────────────────────────────────────────────────────────┤
│ created_time: │ Parse ISO8601 │ fb_created_time: │
│ "2023-01-15T00:00:00+0000" │ │ timestamp │
└──────────────────────────────────────────────────────────────────────────┘

3. Ad Status Change Webhook Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│ WEBHOOK DATA FLOW (Ad Status Change) │
└─────────────────────────────────────────────────────────────────────────────┘

Meta Platform Maestro Service Core API
──────────── ──────────────── ────────

┌─────────────┐ ┌─────────────────┐ ┌───────────────┐
│ Ad status │ webhook │ /webhook/ │ POST │ /dynamic_ │
│ changes to │─────────────▶│ ad_status │────────▶│ status │
│ DISAPPROVED │ │ │ │ │
└─────────────┘ └─────────────────┘ └───────────────┘
│ │
│ │
┌──────▼──────┐ ┌───────▼───────┐
│ Parse │ │ Update │
│ webhook │ │ facebook_ad_ │
│ payload │ │ status table │
└─────────────┘ └───────────────┘
│ │
│ │
┌──────▼──────┐ ┌───────▼───────┐
│ Validate │ │ Create │
│ signature │ │ notification │
└─────────────┘ └───────────────┘
│ │
│ │
┌──────▼──────┐ ┌───────▼───────┐
│ Queue for │ │ Send activity │
│ processing │ │ event │
└─────────────┘ └───────────────┘

Webhook Payload Structure:
─────────────────────────
{
"entry": [{
"id": "123456789",
"time": 1703500800,
"changes": [{
"field": "ad_status",
"value": {
"ad_id": "23849203842934",
"ad_account_id": "123456789",
"status": "DISAPPROVED",
"old_status": "ACTIVE"
}
}]
}]
}

4. AI Compliance Scoring Pipeline

┌─────────────────────────────────────────────────────────────────────────────┐
│ AI SCORING DATA FLOW │
└─────────────────────────────────────────────────────────────────────────────┘

Trigger: New ad detected via webhook OR manual submission
────────────────────────────────────────────────────────

Step 1: Fetch Ad Creative Data
──────────────────────────────

PostgreSQL Meta Graph API Memory/Cache
────────── ────────────── ────────────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ad_accounts │ token │GET /v19.0/ │ creative │ ad_creative │
│(get token) │─────────▶│{ad_id}/ │──────────────▶│ object │
│ │ │adcreatives │ │ │
└───────────────┘ └───────────────┘ └───────────────┘


Step 2: Process Media & Text
────────────────────────────

Ad Creative Violin Service Maestro
─────────── ────────────── ───────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ image_url │─────────▶│ /analyze/ │──────────────▶│ AI Models │
│ video_url │ │ media │ │ │
│ text_content │ │ │ │ - Vision │
└───────────────┘ │ - Download │ │ - NLP │
│ - OCR │ │ - Classifier │
│ - Transcode │ │ │
└───────────────┘ └───────────────┘


Step 3: Generate Scores
───────────────────────

Maestro Score Engine PostgreSQL
─────── ──────────── ──────────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ ML Features │─────────▶│ Risk │──────────────▶│ org_ads_score │
│ │ │ Calculator │ │ table │
│ - Text emb. │ │ │ │ │
│ - Image emb. │ │ - Policy match│ │ - score │
│ - Policy flags│ │ - Historical │ │ - text_score │
│ │ │ - Ensemble │ │ - media_score │
└───────────────┘ └───────────────┘ └───────────────┘


┌───────────────┐
│ Update │
│ aggregates │
│ │
│ - org avg │
│ - account avg │
│ - BM avg │
└───────────────┘

5. Subscription & Billing Flow

┌─────────────────────────────────────────────────────────────────────────────┐
│ BILLING DATA FLOW │
└─────────────────────────────────────────────────────────────────────────────┘

Step 1: User Subscribes
───────────────────────

Frontend Stripe PostgreSQL
──────── ────── ──────────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Payment Form │─────────▶│ Create │──────────────▶│ organizations │
│ │ │ Subscription │ │ │
│ - Plan │ │ │ │ - stripe_ │
│ - Card info │ │ │ │ customer_id │
│ │ │ │ │ - stripe_ │
└───────────────┘ └───────────────┘ │ subscription│
│ │ _id │
│ webhook │ - stripe_plan │
▼ └───────────────┘
┌───────────────┐
│ invoice.paid │
│ webhook │
└───────────────┘


Step 2: Subscription Renewal
────────────────────────────

Stripe Core API PostgreSQL
────── ──────── ──────────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Automatic │─webhook─▶│ /stripe/ │──────────────▶│ organizations │
│ Renewal │ │ webhook │ │ │
│ │ │ │ │ Update dates: │
│ │ │ - Verify sig │ │ - sub_start │
│ │ │ - Update org │ │ - sub_end │
└───────────────┘ └───────────────┘ └───────────────┘


Step 3: Usage Tracking
──────────────────────

API Requests Activity Logger Analytics
──────────── ─────────────── ─────────

┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Ad Review │─────────▶│ Record │──────────────▶│ Usage │
│ Requests │ │ Activity │ │ Dashboard │
│ │ │ │ │ │
│ │ │ - user_id │ │ - Reviews │
│ │ │ - action │ │ this month │
│ │ │ - timestamp │ │ - Trend │
└───────────────┘ └───────────────┘ └───────────────┘

Data Source Documentation

Primary Data Sources

SourceTypeRefresh RateOwner
Meta Graph APIExternal APIReal-time (webhooks) + 15 min syncMeta
Stripe APIExternal APIReal-time (webhooks)Stripe
User PortalInternalReal-timeComplyAI
Auth0External ServiceReal-timeAuth0

Data Stores

StoreTypePurposeBackup
PostgreSQLPrimary DBAll business dataDaily + WAL
RedisCacheSession, rate limitingHourly
S3Object StorageMedia assetsCross-region

Lineage Metadata

Tracking Information

Every data record includes lineage metadata:

-- Standard timestamp columns
created_time TIMESTAMP NOT NULL DEFAULT NOW()
updated_time TIMESTAMP NOT NULL DEFAULT NOW()

-- Additional tracking (where applicable)
created_by INTEGER REFERENCES users(id)
source_system VARCHAR(50) -- 'meta_api', 'stripe', 'manual'

Change Data Capture

Key tables use activity events for full audit trail:

activity_events
├── user_id (who)
├── action (what)
├── description (details)
├── ip_address (where)
└── created_time (when)

Impact Analysis

If Meta API Changes...

Meta Graph API

├──▶ ad_accounts table (sync broken)
│ │
│ └──▶ org_ad_accounts (missing new accounts)
│ │
│ └──▶ org_ads (no new ad data)
│ │
│ └──▶ Scoring pipeline (stale)

└──▶ Webhooks (no real-time updates)

└──▶ Notifications (delayed alerts)

If PostgreSQL Goes Down...

PostgreSQL

├──▶ Frontend (no data displayed)

├──▶ API endpoints (500 errors)

├──▶ Celery tasks (failed jobs)

└──▶ ML pipeline (no features)

Data Quality Checkpoints

CheckpointLocationValidation
Webhook signatureMaestro ingressHMAC verification
Token validityBefore Meta API callToken refresh if expired
Required fieldsDatabase insertNOT NULL constraints
Foreign keysDatabase insertFK constraints
Data freshnessScheduled jobAlert if >1 hour old

📝 Changelog

DateChange
2024-12Initial lineage documentation