Data Privacy in API Validation: GDPR and CCPA Compliance

Navigate data privacy regulations in API validation with comprehensive GDPR and CCPA compliance strategies.

Data Privacy in API Validation: GDPR and CCPA Compliance
August 16, 2025
42 min read
API Security

Data Privacy in API Validation: GDPR and CCPA Compliance


Data privacy regulations significantly impact API validation and data processing. Understanding GDPR, CCPA, and other privacy laws is essential for compliant API development and operation.


Data Privacy in API Validation Overview

Data Privacy in API Validation Overview


Security Threat Landscape


Data Privacy in API Validation requires careful consideration of multiple factors that impact implementation success and user experience.


Key Considerations


Technical Requirements

  • Scalable architecture design
  • Performance optimization strategies
  • Error handling and recovery
  • Security and compliance measures

Business Impact

  • User experience enhancement
  • Operational efficiency gains
  • Cost optimization opportunities
  • Risk mitigation strategies

Business Impact

  • User experience enhancement
  • Operational efficiency gains
  • Cost optimization opportunities
  • Risk mitigation strategies

Practical Implementation Examples


GDPR Compliance Engine for API Validation


// Production-ready GDPR compliance engine for API data validation
interface GDPRComplianceConfig {
  dataSubjectRights: {
    access: boolean
    rectification: boolean
    erasure: boolean
    restriction: boolean
    portability: boolean
    objection: boolean
  }
  dataProcessing: {
    consentRequired: boolean
    legitimateInterest: boolean
    contract: boolean
    legalObligation: boolean
    vitalInterests: boolean
    publicTask: boolean
  }
  dataRetention: {
    defaultPeriod: number // days
    maxPeriod: number // days
    automaticDeletion: boolean
  }
  consentManagement: {
    explicitConsent: boolean
    withdrawalMechanism: boolean
    consentAudit: boolean
  }
  dataSecurity: {
    encryption: boolean
    pseudonymization: boolean
    accessLogging: boolean
  }
}

interface GDPRDataProcessingRecord {
  id: string
  dataSubjectId: string
  processingPurpose: string
  legalBasis: 'consent' | 'contract' | 'legal_obligation' | 'vital_interests' | 'public_task' | 'legitimate_interest'
  dataCategories: string[]
  retentionPeriod: number
  consentId?: string
  consentTimestamp?: number
  withdrawalTimestamp?: number
  processingStartDate: number
  processingEndDate?: number
  lastAccessDate: number
  accessCount: number
  dataController: string
  dataProcessor?: string
  thirdCountryTransfer: boolean
  safeguards?: string[]
}

interface GDPRComplianceResult {
  isCompliant: boolean
  violations: string[]
  warnings: string[]
  requiredActions: string[]
  legalBases: string[]
  retentionInfo: {
    canProcess: boolean
    retentionPeriod: number
    deletionDate: number
    reason: string
  }
  consentInfo: {
    hasValidConsent: boolean
    consentId?: string
    consentDate?: number
    withdrawalDate?: number
  }
}

class GDPRComplianceEngine {
  private config: GDPRComplianceConfig
  private processingRecords: Map<string, GDPRDataProcessingRecord> = new Map()
  private consentRecords: Map<string, any> = new Map()
  private auditLog: Array<{
    timestamp: number
    action: string
    dataSubjectId: string
    details: any
  }> = new Map()

  constructor(config: GDPRComplianceConfig) {
    this.config = config
    this.initializeComplianceEngine()
  }

  async validateDataProcessing(
    dataSubjectId: string,
    processingPurpose: string,
    dataCategories: string[],
    legalBasis: GDPRDataProcessingRecord['legalBasis']
  ): Promise<GDPRComplianceResult> {
    const violations: string[] = []
    const warnings: string[] = []
    const requiredActions: string[] = []
    const legalBases: string[] = []

    try {
      // Check if legal basis is valid for the processing purpose
      const legalBasisValid = this.validateLegalBasis(processingPurpose, legalBasis)
      if (!legalBasisValid.isValid) {
        violations.push(`Invalid legal basis: ${legalBasisValid.reason}`)
      } else {
        legalBases.push(legalBasis)
      }

      // Check consent requirements
      if (this.requiresConsent(processingPurpose)) {
        const consentCheck = await this.validateConsent(dataSubjectId, processingPurpose)
        if (!consentCheck.isValid) {
          violations.push(`Consent required: ${consentCheck.reason}`)
          requiredActions.push('Obtain valid consent from data subject')
        }
      }

      // Check data retention compliance
      const retentionCheck = this.validateRetentionPolicy(dataSubjectId, processingPurpose)
      if (!retentionCheck.isCompliant) {
        violations.push(`Retention policy violation: ${retentionCheck.reason}`)
      }

      // Check data minimization
      const minimizationCheck = this.validateDataMinimization(dataCategories, processingPurpose)
      if (!minimizationCheck.isCompliant) {
        warnings.push(`Data minimization concern: ${minimizationCheck.reason}`)
      }

      // Check purpose limitation
      const purposeCheck = this.validatePurposeLimitation(dataSubjectId, processingPurpose)
      if (!purposeCheck.isCompliant) {
        violations.push(`Purpose limitation violation: ${purposeCheck.reason}`)
      }

      // Validate data security measures
      const securityCheck = this.validateDataSecurity(dataCategories)
      if (!securityCheck.isCompliant) {
        requiredActions.push(`Implement required security measures: ${securityCheck.missingMeasures.join(', ')}`)
      }

      // Check third country transfers
      if (this.involvesThirdCountryTransfer(dataCategories)) {
        const transferCheck = this.validateInternationalTransfers(dataSubjectId, dataCategories)
        if (!transferCheck.isCompliant) {
          violations.push(`International transfer violation: ${transferCheck.reason}`)
        }
      }

      // Generate compliance record
      const recordId = this.generateRecordId()
      const processingRecord: GDPRDataProcessingRecord = {
        id: recordId,
        dataSubjectId,
        processingPurpose,
        legalBasis,
        dataCategories,
        retentionPeriod: this.calculateRetentionPeriod(processingPurpose),
        consentId: legalBasis === 'consent' ? this.generateConsentId() : undefined,
        consentTimestamp: legalBasis === 'consent' ? Date.now() : undefined,
        processingStartDate: Date.now(),
        lastAccessDate: Date.now(),
        accessCount: 1,
        dataController: this.config.dataController || 'Default Controller',
        thirdCountryTransfer: this.involvesThirdCountryTransfer(dataCategories)
      }

      this.processingRecords.set(recordId, processingRecord)
      this.logAuditEvent('data_processing_validated', dataSubjectId, { recordId, processingPurpose })

      return {
        isCompliant: violations.length === 0,
        violations,
        warnings,
        requiredActions,
        legalBases,
        retentionInfo: retentionCheck,
        consentInfo: await this.getConsentInfo(dataSubjectId, processingPurpose)
      }

    } catch (error) {
      console.error('GDPR compliance validation failed:', error)

      return {
        isCompliant: false,
        violations: ['Validation system error'],
        warnings: [],
        requiredActions: ['Contact system administrator'],
        legalBases: [],
        retentionInfo: {
          canProcess: false,
          retentionPeriod: 0,
          deletionDate: Date.now(),
          reason: 'System error'
        },
        consentInfo: {
          hasValidConsent: false
        }
      }
    }
  }

  private validateLegalBasis(
    purpose: string,
    legalBasis: GDPRDataProcessingRecord['legalBasis']
  ): { isValid: boolean; reason?: string } {
    // Define valid legal bases for different purposes
    const validBases: Record<string, string[]> = {
      'marketing': ['consent', 'legitimate_interest'],
      'analytics': ['consent', 'legitimate_interest'],
      'customer_service': ['contract', 'consent'],
      'fraud_prevention': ['legitimate_interest', 'legal_obligation'],
      'legal_compliance': ['legal_obligation'],
      'vital_interests': ['vital_interests'],
      'public_task': ['public_task']
    }

    const purposeKey = Object.keys(validBases).find(key =>
      purpose.toLowerCase().includes(key.replace('_', ' '))
    ) || 'other'

    if (purposeKey === 'other') {
      return { isValid: false, reason: 'Unrecognized processing purpose' }
    }

    if (!validBases[purposeKey].includes(legalBasis)) {
      return {
        isValid: false,
        reason: `Legal basis '${legalBasis}' not valid for purpose '${purpose}'`
      }
    }

    return { isValid: true }
  }

  private requiresConsent(purpose: string): boolean {
    const consentRequiredPurposes = [
      'marketing',
      'analytics',
      'profiling'
    ]

    return consentRequiredPurposes.some(p => purpose.toLowerCase().includes(p))
  }

  private async validateConsent(dataSubjectId: string, purpose: string): Promise<{ isValid: boolean; reason?: string }> {
    const consentRecord = this.consentRecords.get(`${dataSubjectId}-${purpose}`)

    if (!consentRecord) {
      return { isValid: false, reason: 'No consent record found' }
    }

    if (consentRecord.withdrawn) {
      return { isValid: false, reason: 'Consent has been withdrawn' }
    }

    if (Date.now() - consentRecord.timestamp > 365 * 24 * 60 * 60 * 1000) {
      return { isValid: false, reason: 'Consent has expired' }
    }

    return { isValid: true }
  }

  private validateRetentionPolicy(dataSubjectId: string, purpose: string): {
    isCompliant: boolean
    retentionPeriod: number
    deletionDate: number
    reason: string
  } {
    const record = Array.from(this.processingRecords.values())
      .find(r => r.dataSubjectId === dataSubjectId && r.processingPurpose === purpose)

    if (!record) {
      return {
        isCompliant: false,
        retentionPeriod: 0,
        deletionDate: Date.now(),
        reason: 'No processing record found'
      }
    }

    const deletionDate = record.processingStartDate + (record.retentionPeriod * 24 * 60 * 60 * 1000)

    if (Date.now() > deletionDate) {
      return {
        isCompliant: false,
        retentionPeriod: record.retentionPeriod,
        deletionDate,
        reason: 'Data retention period exceeded'
      }
    }

    return {
      isCompliant: true,
      retentionPeriod: record.retentionPeriod,
      deletionDate,
      reason: 'Within retention period'
    }
  }

  private validateDataMinimization(dataCategories: string[], purpose: string): {
    isCompliant: boolean
    reason?: string
  } {
    // Define minimum required data for different purposes
    const requiredData: Record<string, string[]> = {
      'authentication': ['email', 'password_hash'],
      'payment': ['payment_method', 'billing_address'],
      'shipping': ['shipping_address', 'contact_info']
    }

    const purposeKey = Object.keys(requiredData).find(key =>
      purpose.toLowerCase().includes(key)
    )

    if (purposeKey) {
      const required = requiredData[purposeKey]
      const hasAllRequired = required.every(cat => dataCategories.includes(cat))

      if (!hasAllRequired) {
        return {
          isCompliant: false,
          reason: `Missing required data categories: ${required.filter(cat => !dataCategories.includes(cat)).join(', ')}`
        }
      }
    }

    return { isCompliant: true }
  }

  private validatePurposeLimitation(dataSubjectId: string, purpose: string): {
    isCompliant: boolean
    reason?: string
  } {
    const subjectRecords = Array.from(this.processingRecords.values())
      .filter(r => r.dataSubjectId === dataSubjectId)

    // Check if this purpose is compatible with existing purposes
    const existingPurposes = subjectRecords.map(r => r.processingPurpose)
    const compatiblePurposes = this.getCompatiblePurposes(purpose)

    const hasIncompatiblePurpose = existingPurposes.some(existing =>
      !compatiblePurposes.includes(existing)
    )

    if (hasIncompatiblePurpose) {
      return {
        isCompliant: false,
        reason: 'Purpose not compatible with existing data processing'
      }
    }

    return { isCompliant: true }
  }

  private validateDataSecurity(dataCategories: string[]): {
    isCompliant: boolean
    missingMeasures: string[]
  } {
    const missingMeasures: string[] = []
    const sensitiveCategories = ['personal_data', 'financial_data', 'health_data']

    if (dataCategories.some(cat => sensitiveCategories.includes(cat))) {
      if (!this.config.dataSecurity.encryption) {
        missingMeasures.push('encryption')
      }
      if (!this.config.dataSecurity.pseudonymization) {
        missingMeasures.push('pseudonymization')
      }
    }

    return {
      isCompliant: missingMeasures.length === 0,
      missingMeasures
    }
  }

  private validateInternationalTransfers(dataSubjectId: string, dataCategories: string[]): {
    isCompliant: boolean
    reason?: string
  } {
    // In production, check against adequacy decisions, BCRs, SCCs, etc.
    // For demo, simulate transfer validation

    if (this.config.thirdCountryTransfer) {
      return {
        isCompliant: false,
        reason: 'Third country transfer requires additional safeguards'
      }
    }

    return { isCompliant: true }
  }

  private calculateRetentionPeriod(purpose: string): number {
    // Define retention periods for different purposes (in days)
    const retentionPeriods: Record<string, number> = {
      'marketing': 1095, // 3 years
      'analytics': 2555, // 7 years
      'customer_service': 365, // 1 year
      'fraud_prevention': 2555, // 7 years
      'legal_compliance': 2555, // 7 years
      'default': 365 // 1 year
    }

    const purposeKey = Object.keys(retentionPeriods).find(key =>
      purpose.toLowerCase().includes(key.replace('_', ' '))
    ) || 'default'

    return retentionPeriods[purposeKey]
  }

  private async getConsentInfo(dataSubjectId: string, purpose: string): Promise<{
    hasValidConsent: boolean
    consentId?: string
    consentDate?: number
    withdrawalDate?: number
  }> {
    const consentRecord = this.consentRecords.get(`${dataSubjectId}-${purpose}`)

    if (!consentRecord) {
      return { hasValidConsent: false }
    }

    return {
      hasValidConsent: !consentRecord.withdrawn && (Date.now() - consentRecord.timestamp) <= 365 * 24 * 60 * 60 * 1000,
      consentId: consentRecord.id,
      consentDate: consentRecord.timestamp,
      withdrawalDate: consentRecord.withdrawalDate
    }
  }

  private getCompatiblePurposes(purpose: string): string[] {
    // Define which purposes are compatible with each other
    const compatibilityMap: Record<string, string[]> = {
      'marketing': ['analytics', 'customer_service'],
      'analytics': ['marketing', 'fraud_prevention'],
      'customer_service': ['marketing', 'fraud_prevention'],
      'fraud_prevention': ['analytics', 'customer_service', 'legal_compliance'],
      'legal_compliance': ['fraud_prevention']
    }

    return compatibilityMap[purpose] || []
  }

  private involvesThirdCountryTransfer(dataCategories: string[]): boolean {
    // In production, check if data will be transferred outside EU/EEA
    // For demo, simulate based on data categories

    const sensitiveCategories = ['personal_data', 'financial_data']
    return dataCategories.some(cat => sensitiveCategories.includes(cat))
  }

  private generateRecordId(): string {
    return `gdpr_record_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  private generateConsentId(): string {
    return `consent_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  private logAuditEvent(action: string, dataSubjectId: string, details: any): void {
    this.auditLog.push({
      timestamp: Date.now(),
      action,
      dataSubjectId,
      details
    })

    // Keep only last 10000 audit entries
    if (this.auditLog.length > 10000) {
      this.auditLog.shift()
    }
  }

  private initializeComplianceEngine(): void {
    console.log('GDPR Compliance Engine initialized')
  }

  // Data Subject Rights Implementation
  async handleDataSubjectRequest(
    dataSubjectId: string,
    right: keyof GDPRComplianceConfig['dataSubjectRights'],
    requestDetails?: any
  ): Promise<{
    success: boolean
    message: string
    data?: any
    deletionDate?: number
  }> {
    switch (right) {
      case 'access':
        return this.handleAccessRequest(dataSubjectId)

      case 'rectification':
        return this.handleRectificationRequest(dataSubjectId, requestDetails)

      case 'erasure':
        return this.handleErasureRequest(dataSubjectId)

      case 'restriction':
        return this.handleRestrictionRequest(dataSubjectId)

      case 'portability':
        return this.handlePortabilityRequest(dataSubjectId)

      case 'objection':
        return this.handleObjectionRequest(dataSubjectId, requestDetails)

      default:
        return {
          success: false,
          message: 'Unknown right requested'
        }
    }
  }

  private async handleAccessRequest(dataSubjectId: string): Promise<any> {
    const subjectRecords = Array.from(this.processingRecords.values())
      .filter(r => r.dataSubjectId === dataSubjectId)

    this.logAuditEvent('access_request', dataSubjectId, { recordCount: subjectRecords.length })

    return {
      success: true,
      message: 'Access request processed',
      data: {
        records: subjectRecords.length,
        purposes: subjectRecords.map(r => r.processingPurpose),
        retentionInfo: subjectRecords.map(r => ({
          purpose: r.processingPurpose,
          deletionDate: r.processingStartDate + (r.retentionPeriod * 24 * 60 * 60 * 1000)
        }))
      }
    }
  }

  private async handleRectificationRequest(dataSubjectId: string, corrections: any): Promise<any> {
    // In production, update data in underlying systems
    this.logAuditEvent('rectification_request', dataSubjectId, { corrections })

    return {
      success: true,
      message: 'Data rectification completed'
    }
  }

  private async handleErasureRequest(dataSubjectId: string): Promise<any> {
    const subjectRecords = Array.from(this.processingRecords.values())
      .filter(r => r.dataSubjectId === dataSubjectId)

    // Mark records for deletion
    subjectRecords.forEach(record => {
      record.processingEndDate = Date.now()
    })

    const deletionDate = Date.now() + 30 * 24 * 60 * 60 * 1000 // 30 days

    this.logAuditEvent('erasure_request', dataSubjectId, {
      recordsMarked: subjectRecords.length,
      deletionDate
    })

    return {
      success: true,
      message: 'Erasure request processed',
      deletionDate
    }
  }

  private async handleRestrictionRequest(dataSubjectId: string): Promise<any> {
    // In production, restrict processing of data
    this.logAuditEvent('restriction_request', dataSubjectId, {})

    return {
      success: true,
      message: 'Data processing restricted'
    }
  }

  private async handlePortabilityRequest(dataSubjectId: string): Promise<any> {
    const subjectRecords = Array.from(this.processingRecords.values())
      .filter(r => r.dataSubjectId === dataSubjectId)

    const exportData = {
      personalData: subjectRecords.map(r => ({
        purpose: r.processingPurpose,
        categories: r.dataCategories,
        collectionDate: r.processingStartDate,
        lastAccess: r.lastAccessDate
      })),
      exportDate: Date.now(),
      format: 'JSON'
    }

    this.logAuditEvent('portability_request', dataSubjectId, { dataSize: JSON.stringify(exportData).length })

    return {
      success: true,
      message: 'Data portability package generated',
      data: exportData
    }
  }

  private async handleObjectionRequest(dataSubjectId: string, reason: string): Promise<any> {
    // In production, stop specific processing activities
    this.logAuditEvent('objection_request', dataSubjectId, { reason })

    return {
      success: true,
      message: 'Objection processed'
    }
  }

  // Consent Management
  async recordConsent(
    dataSubjectId: string,
    purpose: string,
    consentGiven: boolean,
    consentText?: string
  ): Promise<string> {
    const consentId = this.generateConsentId()
    const consentRecord = {
      id: consentId,
      dataSubjectId,
      purpose,
      consentGiven,
      consentText,
      timestamp: Date.now(),
      withdrawn: false,
      withdrawalDate: null
    }

    this.consentRecords.set(`${dataSubjectId}-${purpose}`, consentRecord)
    this.logAuditEvent('consent_recorded', dataSubjectId, { consentId, purpose, given: consentGiven })

    return consentId
  }

  async withdrawConsent(dataSubjectId: string, purpose: string): Promise<boolean> {
    const consentRecord = this.consentRecords.get(`${dataSubjectId}-${purpose}`)

    if (!consentRecord) {
      return false
    }

    consentRecord.withdrawn = true
    consentRecord.withdrawalDate = Date.now()

    this.logAuditEvent('consent_withdrawn', dataSubjectId, { purpose })

    return true
  }

  // Data Retention Management
  async processRetentionCleanup(): Promise<{
    recordsDeleted: number
    recordsScheduled: number
    totalRecords: number
  }> {
    const now = Date.now()
    let recordsDeleted = 0
    let recordsScheduled = 0

    for (const [recordId, record] of this.processingRecords.entries()) {
      if (record.processingEndDate) {
        // Record marked for deletion
        const deletionEligibleDate = record.processingEndDate + 30 * 24 * 60 * 60 * 1000 // 30 days grace period

        if (now >= deletionEligibleDate) {
          this.processingRecords.delete(recordId)
          recordsDeleted++
        } else {
          recordsScheduled++
        }
      } else {
        // Check if retention period exceeded
        const deletionDate = record.processingStartDate + (record.retentionPeriod * 24 * 60 * 60 * 1000)

        if (now >= deletionDate) {
          record.processingEndDate = now
          recordsScheduled++
        }
      }
    }

    this.logAuditEvent('retention_cleanup', 'system', {
      recordsDeleted,
      recordsScheduled,
      timestamp: now
    })

    return {
      recordsDeleted,
      recordsScheduled,
      totalRecords: this.processingRecords.size
    }
  }

  // Compliance Reporting
  generateComplianceReport(period: { start: number; end: number }): {
    totalRecords: number
    compliantRecords: number
    violations: number
    consentWithdrawals: number
    dataSubjectRequests: number
    internationalTransfers: number
  } {
    const periodRecords = Array.from(this.processingRecords.values())
      .filter(r => r.processingStartDate >= period.start && r.processingStartDate <= period.end)

    const auditEvents = this.auditLog.filter(
      event => event.timestamp >= period.start && event.timestamp <= period.end
    )

    return {
      totalRecords: periodRecords.length,
      compliantRecords: periodRecords.filter(r => r.processingEndDate === undefined).length,
      violations: auditEvents.filter(e => e.action.includes('violation')).length,
      consentWithdrawals: auditEvents.filter(e => e.action === 'consent_withdrawn').length,
      dataSubjectRequests: auditEvents.filter(e =>
        ['access_request', 'erasure_request', 'portability_request'].includes(e.action)
      ).length,
      internationalTransfers: periodRecords.filter(r => r.thirdCountryTransfer).length
    }
  }
}

// Initialize GDPR compliance engine
const gdprConfig: GDPRComplianceConfig = {
  dataSubjectRights: {
    access: true,
    rectification: true,
    erasure: true,
    restriction: true,
    portability: true,
    objection: true
  },
  dataProcessing: {
    consentRequired: true,
    legitimateInterest: true,
    contract: true,
    legalObligation: true,
    vitalInterests: true,
    publicTask: true
  },
  dataRetention: {
    defaultPeriod: 365,
    maxPeriod: 2555,
    automaticDeletion: true
  },
  consentManagement: {
    explicitConsent: true,
    withdrawalMechanism: true,
    consentAudit: true
  },
  dataSecurity: {
    encryption: true,
    pseudonymization: true,
    accessLogging: true
  }
}

const gdprComplianceEngine = new GDPRComplianceEngine(gdprConfig)

// GDPR compliance validation endpoint
app.post('/api/gdpr/validate-processing', async (req, res) => {
  try {
    const { dataSubjectId, processingPurpose, dataCategories, legalBasis } = req.body

    if (!dataSubjectId || !processingPurpose || !dataCategories || !legalBasis) {
      return res.status(400).json({ error: 'dataSubjectId, processingPurpose, dataCategories, and legalBasis required' })
    }

    const result = await gdprComplianceEngine.validateDataProcessing(
      dataSubjectId,
      processingPurpose,
      dataCategories,
      legalBasis
    )

    res.json({
      compliance: result,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('GDPR compliance validation error:', error)
    res.status(500).json({ error: 'GDPR validation failed' })
  }
})

// Data subject rights endpoint
app.post('/api/gdpr/data-subject-request', async (req, res) => {
  try {
    const { dataSubjectId, right, requestDetails } = req.body

    if (!dataSubjectId || !right) {
      return res.status(400).json({ error: 'dataSubjectId and right required' })
    }

    const result = await gdprComplianceEngine.handleDataSubjectRequest(dataSubjectId, right, requestDetails)

    res.json({
      request: result,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Data subject request handling error:', error)
    res.status(500).json({ error: 'Request handling failed' })
  }
})

// Consent management endpoint
app.post('/api/gdpr/consent', async (req, res) => {
  try {
    const { dataSubjectId, purpose, consentGiven, consentText } = req.body

    if (!dataSubjectId || !purpose) {
      return res.status(400).json({ error: 'dataSubjectId and purpose required' })
    }

    const consentId = await gdprComplianceEngine.recordConsent(dataSubjectId, purpose, consentGiven, consentText)

    res.json({
      consentId,
      message: consentGiven ? 'Consent recorded' : 'Consent denied',
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Consent management error:', error)
    res.status(500).json({ error: 'Consent management failed' })
  }
})

// Withdraw consent endpoint
app.delete('/api/gdpr/consent', async (req, res) => {
  try {
    const { dataSubjectId, purpose } = req.body

    if (!dataSubjectId || !purpose) {
      return res.status(400).json({ error: 'dataSubjectId and purpose required' })
    }

    const success = await gdprComplianceEngine.withdrawConsent(dataSubjectId, purpose)

    if (success) {
      res.json({
        message: 'Consent withdrawn successfully',
        timestamp: new Date().toISOString()
      })
    } else {
      res.status(404).json({ error: 'Consent record not found' })
    }

  } catch (error) {
    console.error('Consent withdrawal error:', error)
    res.status(500).json({ error: 'Consent withdrawal failed' })
  }
})

// GDPR compliance report endpoint
app.get('/api/gdpr/compliance-report', (req, res) => {
  try {
    const { startDate, endDate } = req.query

    const start = startDate ? new Date(startDate as string).getTime() : Date.now() - 30 * 24 * 60 * 60 * 1000
    const end = endDate ? new Date(endDate as string).getTime() : Date.now()

    const report = gdprComplianceEngine.generateComplianceReport({ start, end })

    res.json({
      report,
      period: { start, end },
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Compliance report generation error:', error)
    res.status(500).json({ error: 'Report generation failed' })
  }
})

console.log('GDPR Compliance Engine initialized')

CCPA Compliance Framework


// CCPA compliance framework for California Consumer Privacy Act
interface CCPAComplianceConfig {
  businessType: 'for_profit' | 'nonprofit' | 'government'
  annualRevenue: number
  dataCollection: {
    personalInformation: boolean
    sensitivePersonalInformation: boolean
    biometricInformation: boolean
    geolocationData: boolean
  }
  dataSharing: {
    thirdPartySharing: boolean
    saleOfPersonalInformation: boolean
    crossContextBehavioralAdvertising: boolean
  }
  consumerRights: {
    rightToKnow: boolean
    rightToDelete: boolean
    rightToOptOut: boolean
    rightToCorrect: boolean
    rightToDataPortability: boolean
    rightToLimitUse: boolean
  }
  dataRetention: {
    defaultPeriod: number
    deletionGracePeriod: number
  }
}

interface CCPAConsumerRequest {
  id: string
  consumerId: string
  requestType: 'know' | 'delete' | 'opt_out' | 'correct' | 'portability' | 'limit_use'
  requestDate: number
  status: 'pending' | 'in_progress' | 'completed' | 'denied'
  personalInformationCategories: string[]
  responseData?: any
  completionDate?: number
  denialReason?: string
}

interface CCPAComplianceResult {
  isCompliant: boolean
  violations: string[]
  warnings: string[]
  requiredActions: string[]
  consumerRights: string[]
  retentionInfo: {
    canRetain: boolean
    retentionPeriod: number
    deletionRequired: boolean
  }
}

class CCPAComplianceFramework {
  private config: CCPAComplianceConfig
  private consumerRequests: Map<string, CCPAConsumerRequest> = new Map()
  private dataInventory: Map<string, any> = new Map()
  private optOutList: Set<string> = new Set()

  constructor(config: CCPAComplianceConfig) {
    this.config = config
    this.initializeCCPAFramework()
  }

  async validateDataCollection(
    consumerId: string,
    dataCategories: string[],
    collectionPurpose: string
  ): Promise<CCPAComplianceResult> {
    const violations: string[] = []
    const warnings: string[] = []
    const requiredActions: string[] = []
    const consumerRights: string[] = []

    try {
      // Check if business is subject to CCPA
      if (!this.isBusinessSubjectToCCPA()) {
        return {
          isCompliant: true,
          violations: [],
          warnings: [],
          requiredActions: [],
          consumerRights: [],
          retentionInfo: {
            canRetain: true,
            retentionPeriod: 0,
            deletionRequired: false
          }
        }
      }

      // Validate data collection practices
      const collectionCheck = this.validateCollectionPractices(dataCategories, collectionPurpose)
      if (!collectionCheck.isValid) {
        violations.push(`Invalid collection practice: ${collectionCheck.reason}`)
      }

      // Check data sharing compliance
      const sharingCheck = this.validateDataSharing(dataCategories)
      if (!sharingCheck.isCompliant) {
        violations.push(`Data sharing violation: ${sharingCheck.reason}`)
      }

      // Validate consumer notice requirements
      const noticeCheck = this.validateConsumerNotice(consumerId)
      if (!noticeCheck.isCompliant) {
        requiredActions.push('Provide required privacy notice to consumer')
      }

      // Check opt-out status
      if (this.optOutList.has(consumerId)) {
        violations.push('Consumer has opted out of data sales')
        requiredActions.push('Honor consumer opt-out request')
      }

      // Determine applicable consumer rights
      consumerRights.push(...this.determineConsumerRights(dataCategories))

      // Validate data retention
      const retentionCheck = this.validateRetentionPolicy(dataCategories)

      // Create request record for tracking
      const requestId = this.generateRequestId()
      const consumerRequest: CCPAConsumerRequest = {
        id: requestId,
        consumerId,
        requestType: 'know',
        requestDate: Date.now(),
        status: 'completed',
        personalInformationCategories: dataCategories,
        responseData: {
          collectionPurpose,
          legalBasis: 'Business purpose',
          retentionPeriod: retentionCheck.retentionPeriod
        },
        completionDate: Date.now()
      }

      this.consumerRequests.set(requestId, consumerRequest)

      return {
        isCompliant: violations.length === 0,
        violations,
        warnings,
        requiredActions,
        consumerRights,
        retentionInfo: retentionCheck
      }

    } catch (error) {
      console.error('CCPA compliance validation failed:', error)

      return {
        isCompliant: false,
        violations: ['Validation system error'],
        warnings: [],
        requiredActions: ['Contact system administrator'],
        consumerRights: [],
        retentionInfo: {
          canRetain: false,
          retentionPeriod: 0,
          deletionRequired: true
        }
      }
    }
  }

  private isBusinessSubjectToCCPA(): boolean {
    // CCPA applies to for-profit businesses that:
    // 1. Have annual gross revenue > $25M, OR
    // 2. Buy/sell/share personal information of 100,000+ consumers/households, OR
    // 3. Derive 50%+ of revenue from selling personal information

    if (this.config.businessType !== 'for_profit') {
      return false
    }

    return (
      this.config.annualRevenue > 25000000 ||
      this.config.dataSharing.saleOfPersonalInformation ||
      this.config.dataCollection.personalInformation
    )
  }

  private validateCollectionPractices(
    dataCategories: string[],
    purpose: string
  ): { isValid: boolean; reason?: string } {
    // CCPA requires businesses to collect only necessary personal information
    const sensitiveCategories = [
      'social_security_number',
      'drivers_license',
      'financial_account',
      'medical_information',
      'biometric_data'
    ]

    const hasSensitiveData = dataCategories.some(cat => sensitiveCategories.includes(cat))

    if (hasSensitiveData && !this.isSensitiveDataNecessary(purpose)) {
      return {
        isValid: false,
        reason: 'Sensitive data collection not justified by business purpose'
      }
    }

    return { isValid: true }
  }

  private validateDataSharing(dataCategories: string[]): {
    isCompliant: boolean
    reason?: string
  } {
    // CCPA requires notice and opt-out for data sales
    if (this.config.dataSharing.saleOfPersonalInformation) {
      return {
        isCompliant: false,
        reason: 'Data sales require consumer notice and opt-out mechanism'
      }
    }

    return { isCompliant: true }
  }

  private validateConsumerNotice(consumerId: string): {
    isCompliant: boolean
    missingNotices?: string[]
  } {
    // CCPA requires privacy notice at or before collection
    const missingNotices: string[] = []

    if (!this.hasProvidedPrivacyNotice(consumerId)) {
      missingNotices.push('privacy_policy')
    }

    if (this.config.dataSharing.saleOfPersonalInformation && !this.hasProvidedOptOutNotice(consumerId)) {
      missingNotices.push('opt_out_notice')
    }

    return {
      isCompliant: missingNotices.length === 0,
      missingNotices
    }
  }

  private isSensitiveDataNecessary(purpose: string): boolean {
    // Define when sensitive data collection is justified
    const justifiedPurposes: Record<string, string[]> = {
      'identity_verification': ['social_security_number', 'drivers_license'],
      'financial_services': ['financial_account'],
      'healthcare_services': ['medical_information'],
      'security_authentication': ['biometric_data']
    }

    for (const [purposeKey, categories] of Object.entries(justifiedPurposes)) {
      if (purpose.toLowerCase().includes(purposeKey.replace('_', ' '))) {
        return true
      }
    }

    return false
  }

  private hasProvidedPrivacyNotice(consumerId: string): boolean {
    // In production, check if privacy notice was provided
    // For demo, simulate based on consumer ID
    return consumerId.startsWith('notice_provided_')
  }

  private hasProvidedOptOutNotice(consumerId: string): boolean {
    // In production, check if opt-out notice was provided
    // For demo, simulate based on consumer ID
    return consumerId.startsWith('optout_notice_')
  }

  private determineConsumerRights(dataCategories: string[]): string[] {
    const rights: string[] = []

    if (this.config.consumerRights.rightToKnow) {
      rights.push('Right to know what personal information is collected')
    }

    if (this.config.consumerRights.rightToDelete) {
      rights.push('Right to delete personal information')
    }

    if (this.config.consumerRights.rightToOptOut && this.config.dataSharing.saleOfPersonalInformation) {
      rights.push('Right to opt-out of the sale of personal information')
    }

    if (this.config.consumerRights.rightToCorrect) {
      rights.push('Right to correct inaccurate personal information')
    }

    if (this.config.consumerRights.rightToDataPortability) {
      rights.push('Right to data portability')
    }

    if (this.config.consumerRights.rightToLimitUse && this.hasSensitiveData(dataCategories)) {
      rights.push('Right to limit the use of sensitive personal information')
    }

    return rights
  }

  private hasSensitiveData(dataCategories: string[]): boolean {
    const sensitiveCategories = [
      'social_security_number',
      'drivers_license',
      'financial_account',
      'medical_information',
      'biometric_data',
      'geolocation_data'
    ]

    return dataCategories.some(cat => sensitiveCategories.includes(cat))
  }

  private validateRetentionPolicy(dataCategories: string[]): {
    canRetain: boolean
    retentionPeriod: number
    deletionRequired: boolean
  } {
    // CCPA requires deletion of personal information when no longer necessary
    const hasPersonalData = dataCategories.includes('personal_information') ||
                           dataCategories.includes('contact_information')

    if (!hasPersonalData) {
      return {
        canRetain: true,
        retentionPeriod: 0,
        deletionRequired: false
      }
    }

    return {
      canRetain: true,
      retentionPeriod: this.config.dataRetention.defaultPeriod,
      deletionRequired: false
    }
  }

  private generateRequestId(): string {
    return `ccpa_request_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
  }

  private initializeCCPAFramework(): void {
    console.log('CCPA Compliance Framework initialized')
  }

  // Consumer Rights Implementation
  async handleConsumerRequest(
    consumerId: string,
    requestType: CCPAConsumerRequest['requestType'],
    requestDetails?: any
  ): Promise<{
    success: boolean
    requestId: string
    message: string
    estimatedCompletion?: number
  }> {
    const requestId = this.generateRequestId()
    const estimatedCompletion = Date.now() + 45 * 24 * 60 * 60 * 1000 // 45 days

    const consumerRequest: CCPAConsumerRequest = {
      id: requestId,
      consumerId,
      requestType,
      requestDate: Date.now(),
      status: 'pending',
      personalInformationCategories: requestDetails?.categories || []
    }

    this.consumerRequests.set(requestId, consumerRequest)

    // Process request based on type
    switch (requestType) {
      case 'know':
        return this.processKnowRequest(consumerRequest)

      case 'delete':
        return this.processDeleteRequest(consumerRequest)

      case 'opt_out':
        return this.processOptOutRequest(consumerRequest)

      case 'correct':
        return this.processCorrectRequest(consumerRequest, requestDetails)

      case 'portability':
        return this.processPortabilityRequest(consumerRequest)

      case 'limit_use':
        return this.processLimitUseRequest(consumerRequest)

      default:
        return {
          success: false,
          requestId: '',
          message: 'Unknown request type'
        }
    }
  }

  private async processKnowRequest(request: CCPAConsumerRequest): Promise<any> {
    // CCPA Right to Know: Businesses must disclose personal information collected
    request.status = 'in_progress'

    // In production, gather personal information from all systems
    const personalInfo = {
      categories: request.personalInformationCategories,
      collectionSources: ['Website', 'Mobile App', 'Customer Service'],
      businessPurposes: ['Customer service', 'Marketing', 'Analytics'],
      thirdPartyRecipients: this.config.dataSharing.thirdPartySharing ?
        ['Marketing partners', 'Analytics providers'] : [],
      collectionDate: Date.now() - 30 * 24 * 60 * 60 * 1000
    }

    request.responseData = personalInfo
    request.status = 'completed'
    request.completionDate = Date.now()

    return {
      success: true,
      requestId: request.id,
      message: 'Right to Know request processed',
      estimatedCompletion: request.completionDate
    }
  }

  private async processDeleteRequest(request: CCPAConsumerRequest): Promise<any> {
    // CCPA Right to Delete: Businesses must delete consumer's personal information
    request.status = 'in_progress'

    // In production, delete personal information from all systems
    const deletionInfo = {
      categoriesDeleted: request.personalInformationCategories,
      deletionDate: Date.now(),
      retentionExceptions: ['Legal compliance', 'Transaction completion']
    }

    request.responseData = deletionInfo
    request.status = 'completed'
    request.completionDate = Date.now()

    return {
      success: true,
      requestId: request.id,
      message: 'Right to Delete request processed',
      estimatedCompletion: request.completionDate
    }
  }

  private async processOptOutRequest(request: CCPAConsumerRequest): Promise<any> {
    // CCPA Right to Opt-Out: Consumers can opt-out of data sales
    this.optOutList.add(request.consumerId)

    request.status = 'completed'
    request.completionDate = Date.now()

    return {
      success: true,
      requestId: request.id,
      message: 'Opt-out request processed',
      estimatedCompletion: request.completionDate
    }
  }

  private async processCorrectRequest(request: CCPAConsumerRequest, corrections: any): Promise<any> {
    // CCPA Right to Correct: Businesses must correct inaccurate personal information
    request.status = 'in_progress'

    // In production, update personal information in all systems
    const correctionInfo = {
      correctionsApplied: corrections,
      correctionDate: Date.now()
    }

    request.responseData = correctionInfo
    request.status = 'completed'
    request.completionDate = Date.now()

    return {
      success: true,
      requestId: request.id,
      message: 'Right to Correct request processed',
      estimatedCompletion: request.completionDate
    }
  }

  private async processPortabilityRequest(request: CCPAConsumerRequest): Promise<any> {
    // CCPA Right to Data Portability: Provide personal information in portable format
    request.status = 'in_progress'

    // In production, export personal information in machine-readable format
    const exportData = {
      personalInformation: {
        contact: 'consumer@example.com',
        preferences: ['marketing_opt_in'],
        activity: ['website_visits', 'purchases']
      },
      exportFormat: 'JSON',
      exportDate: Date.now()
    }

    request.responseData = exportData
    request.status = 'completed'
    request.completionDate = Date.now()

    return {
      success: true,
      requestId: request.id,
      message: 'Right to Data Portability request processed',
      estimatedCompletion: request.completionDate
    }
  }

  private async processLimitUseRequest(request: CCPAConsumerRequest): Promise<any> {
    // CCPA Right to Limit Use: Limit use of sensitive personal information
    request.status = 'in_progress'

    // In production, restrict processing of sensitive data
    const limitationInfo = {
      sensitiveDataCategories: request.personalInformationCategories.filter(cat =>
        ['biometric', 'geolocation', 'health'].includes(cat)
      ),
      limitationApplied: true,
      limitationDate: Date.now()
    }

    request.responseData = limitationInfo
    request.status = 'completed'
    request.completionDate = Date.now()

    return {
      success: true,
      requestId: request.id,
      message: 'Right to Limit Use request processed',
      estimatedCompletion: request.completionDate
    }
  }

  // Opt-out management
  isConsumerOptedOut(consumerId: string): boolean {
    return this.optOutList.has(consumerId)
  }

  addConsumerOptOut(consumerId: string): void {
    this.optOutList.add(consumerId)
  }

  removeConsumerOptOut(consumerId: string): void {
    this.optOutList.delete(consumerId)
  }

  // Compliance reporting
  generateCCPAReport(): {
    totalRequests: number
    completedRequests: number
    pendingRequests: number
    deniedRequests: number
    optOutCount: number
    dataCategories: string[]
    businessPurposes: string[]
  } {
    const requests = Array.from(this.consumerRequests.values())

    return {
      totalRequests: requests.length,
      completedRequests: requests.filter(r => r.status === 'completed').length,
      pendingRequests: requests.filter(r => r.status === 'pending').length,
      deniedRequests: requests.filter(r => r.status === 'denied').length,
      optOutCount: this.optOutList.size,
      dataCategories: [...new Set(requests.flatMap(r => r.personalInformationCategories))],
      businessPurposes: this.config.dataCollection.personalInformation ?
        ['Customer service', 'Marketing', 'Analytics', 'Fraud prevention'] : []
    }
  }
}

// Initialize CCPA compliance framework
const ccpaConfig: CCPAComplianceConfig = {
  businessType: 'for_profit',
  annualRevenue: 50000000,
  dataCollection: {
    personalInformation: true,
    sensitivePersonalInformation: false,
    biometricInformation: false,
    geolocationData: true
  },
  dataSharing: {
    thirdPartySharing: true,
    saleOfPersonalInformation: false,
    crossContextBehavioralAdvertising: true
  },
  consumerRights: {
    rightToKnow: true,
    rightToDelete: true,
    rightToOptOut: true,
    rightToCorrect: true,
    rightToDataPortability: true,
    rightToLimitUse: true
  },
  dataRetention: {
    defaultPeriod: 365,
    deletionGracePeriod: 30
  }
}

const ccpaComplianceFramework = new CCPAComplianceFramework(ccpaConfig)

// CCPA compliance validation endpoint
app.post('/api/ccpa/validate-collection', async (req, res) => {
  try {
    const { consumerId, dataCategories, collectionPurpose } = req.body

    if (!consumerId || !dataCategories || !collectionPurpose) {
      return res.status(400).json({ error: 'consumerId, dataCategories, and collectionPurpose required' })
    }

    const result = await ccpaComplianceFramework.validateDataCollection(
      consumerId,
      dataCategories,
      collectionPurpose
    )

    res.json({
      compliance: result,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('CCPA compliance validation error:', error)
    res.status(500).json({ error: 'CCPA validation failed' })
  }
})

// Consumer rights request endpoint
app.post('/api/ccpa/consumer-request', async (req, res) => {
  try {
    const { consumerId, requestType, requestDetails } = req.body

    if (!consumerId || !requestType) {
      return res.status(400).json({ error: 'consumerId and requestType required' })
    }

    const result = await ccpaComplianceFramework.handleConsumerRequest(consumerId, requestType, requestDetails)

    res.json({
      request: result,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Consumer request handling error:', error)
    res.status(500).json({ error: 'Request handling failed' })
  }
})

// Opt-out management endpoints
app.post('/api/ccpa/opt-out', async (req, res) => {
  try {
    const { consumerId } = req.body

    if (!consumerId) {
      return res.status(400).json({ error: 'consumerId required' })
    }

    ccpaComplianceFramework.addConsumerOptOut(consumerId)

    res.json({
      message: 'Consumer opted out successfully',
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Opt-out processing error:', error)
    res.status(500).json({ error: 'Opt-out processing failed' })
  }
})

app.delete('/api/ccpa/opt-out', async (req, res) => {
  try {
    const { consumerId } = req.body

    if (!consumerId) {
      return res.status(400).json({ error: 'consumerId required' })
    }

    ccpaComplianceFramework.removeConsumerOptOut(consumerId)

    res.json({
      message: 'Consumer opt-in processed successfully',
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('Opt-in processing error:', error)
    res.status(500).json({ error: 'Opt-in processing failed' })
  }
})

// CCPA compliance report endpoint
app.get('/api/ccpa/compliance-report', (req, res) => {
  try {
    const report = ccpaComplianceFramework.generateCCPAReport()

    res.json({
      report,
      timestamp: new Date().toISOString()
    })

  } catch (error) {
    console.error('CCPA report generation error:', error)
    res.status(500).json({ error: 'Report generation failed' })
  }
})

console.log('CCPA Compliance Framework initialized')

Protection Mechanisms


Successful implementation requires understanding the technical landscape and choosing appropriate strategies.


Implementation Approaches


Modern Solutions

  • Cloud-native architectures
  • Microservices integration
  • Real-time processing capabilities
  • Automated scaling mechanisms

Data Privacy in API Validation Architecture

Data Privacy in API Validation Architecture


Implementation Strategies {#implementation-strategies}


Deploy privacy-compliant validation systems.


class PrivacyCompliantValidation {
  private gdprEngine: GDPRComplianceEngine
  private ccpaEngine: CCPAComplianceEngine
  
  constructor() {
    this.gdprEngine = new GDPRComplianceEngine()
    this.ccpaEngine = new CCPAComplianceEngine()
  }
  
  async validate(data: any, userRegion: string): Promise<{
    valid: boolean
    privacyCompliant: boolean
    warnings: string[]
  }> {
    const engine = userRegion === 'EU' ? this.gdprEngine : this.ccpaEngine
    const compliance = await engine.validateProcessing(data)
    
    return {
      valid: true,
      privacyCompliant: compliance.isCompliant,
      warnings: compliance.warnings
    }
  }
}

Monitoring and Detection {#monitoring-and-detection}


Track privacy compliance and data handling.


Key Metrics:

  • Data retention compliance rate
  • Consent tracking accuracy
  • Data subject request response time
  • Privacy incident count
  • Audit log completeness

Incident Response Planning {#incident-response-planning}


Respond to privacy incidents.


const PRIVACY_INCIDENT_PLAYBOOKS = {
  'unauthorized_access': {
    severity: 'critical',
    actions: ['Revoke access', 'Notify DPO', 'Notify affected users'],
    reportingDeadline: 72 // hours (GDPR requirement)
  },
  'data_breach': {
    severity: 'critical',
    actions: ['Contain breach', 'Assess impact', 'Notify authorities', 'Notify users'],
    reportingDeadline: 72
  },
  'retention_violation': {
    severity: 'medium',
    actions: ['Delete expired data', 'Review retention policy', 'Update processes'],
    reportingDeadline: null
  }
}

Compliance and Best Practices {#compliance-and-best-practices}


Maintain ongoing privacy compliance.


Best Practices:

  • Regular privacy impact assessments
  • Data minimization in validation
  • Transparent data processing notices
  • Documented consent mechanisms
  • Privacy-by-design architecture
  • Regular compliance audits

Conclusion {#conclusion}


Data privacy in API validation requires implementing GDPR/CCPA frameworks, data minimization, consent management, retention policies, and data subject rights. Success depends on privacy-by-design architecture, comprehensive audit trails, automated compliance checks, and proactive privacy incident management.


Key success factors include understanding applicable regulations, implementing privacy controls at API level, maintaining detailed processing records, providing data subject rights mechanisms, and conducting regular privacy audits.


Validate data privacy-compliantly with our APIs, designed to meet GDPR, CCPA, and global privacy requirements while maintaining performance and user experience.

Tags:data-privacygdpr-complianceccpa-complianceprivacy-regulations