Cross-Border Data Compliance: Handling IP Geolocation Legally

Navigate international data protection laws and compliance requirements for IP geolocation services.

Cross-Border Data Compliance: Handling IP Geolocation Legally
13 серпня 2025 р.
48 min read
IP Geolocation

International data protection laws create complex compliance requirements for IP geolocation services. Understanding regional regulations and implementing appropriate safeguards is essential for global operations.

Cross-Border Data Compliance Overview
Cross-Border Data Compliance Overview

Overview

  • Data types: IP address, coarse geolocation, device/network metadata can be personal data when reasonably linkable to a person.
  • Processing goals: fraud/risk, content localization, tax/geo-pricing, legal blocking, analytics, SRE.
  • Key levers: minimization, purpose limitation, retention, security controls, transfer mechanism, accountability evidence.

Regulatory Frameworks and Data Localization

  • GDPR/UK GDPR: lawful basis, DPIA for high risk, DPO/representative if applicable, RoPA, Schrems II-compliant transfers.
  • CCPA/CPRA (US-CA): notice at collection, sensitive data handling, opt-out signals (GPC), non-discrimination.
  • LGPD (BR), PIPEDA (CA), PDPA (SG/TH), POPIA (ZA): map equivalence to minimize policy divergence.
  • Localization laws: CN PIPL, RU 242-FZ, IN DPDP — prefer regional processing + keyed tokenization to avoid exporting raw identifiers.

Policy pattern:

  • Store raw IP transiently (≤ 24h) for security; persist derived geo at city/region level when sufficient.
  • Separate keys: one dataset for risk, one for personalization; link with rotating pseudonymous IDs.
  • Maintain per-region processing nodes; export only aggregates or pseudonymized artifacts when feasible.

International Transfer Mechanisms

  • Adequacy: EU/UK lists; monitor validity and scope. Cache with expiry and regulator references.
  • SCCs 2021 (EU): choose module(s) 1-4; include Annex II controls and TIA outcome.
  • BCRs: for intra-group transfers; ensure approval currency and scope; track coverage.
  • EU–US DPF/UK Extension/Swiss-US: valid for certified entities; track org ID and re-cert dates.
  • Derogations: exceptional; avoid for systematic or sensitive transfers.

SCC module selector (example):

function selectSCCModule(isControllerExporter: boolean, isControllerImporter: boolean) {
  if (isControllerExporter && isControllerImporter) return 'Module 1 (C2C)'
  if (isControllerExporter && !isControllerImporter) return 'Module 2 (C2P)'
  if (!isControllerExporter && !isControllerImporter) return 'Module 3 (P2P)'
  return 'Module 4 (P2C)'
}

Schrems II and Transfer Impact Assessments (TIA)

Minimal TIA fields and evaluator:

type TIA = {
  destination: string
  purpose: string
  lawsAssessed: string[]
  govAccessRisk: 'low' | 'medium' | 'high'
  measures: string[]
  residualRisk: 'low' | 'medium' | 'high'
  decision: 'approve' | 'approve_with_measures' | 'reject'
  reviewer: string
  reviewedAt: number
}

export function evaluateTIA(tia: TIA): { ok: boolean; notes: string[] } {
  const notes: string[] = []
  if (tia.govAccessRisk === 'high' && !tia.measures.some(m => m.includes('E2EE'))) {
    notes.push('High access risk without end-to-end encryption')
  }
  if (tia.residualRisk === 'high') notes.push('Residual risk too high')
  return { ok: tia.decision !== 'reject', notes }
}

Supplementary Measures

  • Encryption: at-rest AES-256-GCM; in-transit TLS 1.3; client-side or split-key for sensitive fields.
  • Pseudonymization: rotate mapping tables; segregate identifiers; salt/pepper under HSM/KMS; deterministic tokens for joins.
  • Split processing: compute sensitive risk models within region; export only non-identifying features.
  • Access controls: JIT access, ABAC, session recording; dual control for decrypt actions.
  • Data minimization: drop precise lat/long; store only country/region when sufficient.

Example envelope encryption for IP artifacts:

async function encryptGeoRecord(record: Record<string, unknown>, kms: { wrap: (k: Uint8Array)=>Promise<Uint8Array> }) {
  const dek = crypto.getRandomValues(new Uint8Array(32))
  const iv = crypto.getRandomValues(new Uint8Array(12))
  const alg = { name: 'AES-GCM', iv }
  const cryptoKey = await crypto.subtle.importKey('raw', dek, alg, false, ['encrypt'])
  const ciphertext = await crypto.subtle.encrypt(alg, cryptoKey, new TextEncoder().encode(JSON.stringify(record)))
  const wrappedDek = await kms.wrap(dek)
  return { ciphertext: Buffer.from(ciphertext).toString('base64'), iv: Buffer.from(iv).toString('base64'), wrappedDek: Buffer.from(wrappedDek).toString('base64') }
}

DPAs, RoPA and Governance

  • DPA clauses: subject matter/duration, data types (IP, coarse geo), subprocessor list and flow-down, SCC/BCR refs, audit rights.
  • RoPA entries: purpose, categories, recipients, retention by purpose, transfers, technical/org measures.
  • DPIA triggers: large-scale monitoring, novel tech, systematic profiling; maintain register and outcomes.
  • Incident playbook: cross-border notification timelines (72h EU), regulator selection, evidence bundle.

Practical Implementation Examples

GDPR Compliance Engine for Cross-Border Data Transfers

// Production-ready GDPR compliance engine for cross-border data processing
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
    maxPeriod: number
    automaticDeletion: boolean
  }
  consentManagement: {
    explicitConsent: boolean
    withdrawalMechanism: boolean
    consentAudit: boolean
  }
  dataSecurity: {
    encryption: boolean
    pseudonymization: boolean
    accessLogging: boolean
  }
  crossBorderTransfers: {
    adequacyDecisions: boolean
    bindingCorporateRules: boolean
    standardContractualClauses: boolean
    certifications: boolean
  }
}

interface CrossBorderTransferRequest {
  dataSubjectId: string
  sourceCountry: string
  destinationCountry: string
  dataCategories: string[]
  transferPurpose: string
  legalBasis: 'consent' | 'contract' | 'legal_obligation' | 'vital_interests' | 'public_task' | 'legitimate_interest'
  transferMechanism: 'adequacy' | 'bcr' | 'scc' | 'certification' | 'derogation'
  safeguards?: string[]
  retentionPeriod: number
}

interface GDPRComplianceResult {
  isCompliant: boolean
  violations: string[]
  warnings: string[]
  requiredActions: string[]
  transferMechanism: string
  adequacyDecision?: string
  bindingRules?: string[]
  contractualClauses?: string[]
  transferRiskAssessment: {
    riskLevel: 'low' | 'medium' | 'high'
    riskFactors: string[]
    mitigationMeasures: string[]
  }
}

class CrossBorderGDPRComplianceEngine {
  private config: GDPRComplianceConfig
  private transferRecords: Map<string, any> = new Map()
  private adequacyDecisions: Map<string, any> = new Map()
  private bindingRules: Map<string, any> = new Map()

  constructor(config: GDPRComplianceConfig) {
    this.config = config
    this.initializeAdequacyDecisions()
    this.initializeBindingCorporateRules()
  }

  async validateCrossBorderTransfer(request: CrossBorderTransferRequest): Promise<GDPRComplianceResult> {
    const violations: string[] = []
    const warnings: string[] = []
    const requiredActions: string[] = []

    try {
      // Validate transfer mechanism
      const mechanismCheck = this.validateTransferMechanism(request)
      if (!mechanismCheck.isValid) {
        violations.push(`Invalid transfer mechanism: ${mechanismCheck.reason}`)
      }

      // Check if destination country has adequacy decision
      const adequacyCheck = this.validateAdequacyDecision(request.destinationCountry)
      if (!adequacyCheck.hasAdequacy) {
        if (!this.hasAlternativeSafeguards(request)) {
          violations.push('No adequate safeguards for international transfer')
          requiredActions.push('Implement standard contractual clauses or binding corporate rules')
        } else {
          warnings.push('Transfer relies on alternative safeguards')
        }
      }

      // Validate data minimization for cross-border transfer
      const minimizationCheck = this.validateDataMinimization(request.dataCategories, request.transferPurpose)
      if (!minimizationCheck.isCompliant) {
        warnings.push(`Data minimization concern: ${minimizationCheck.reason}`)
      }

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

      // Validate retention policy for cross-border data
      const retentionCheck = this.validateCrossBorderRetention(request)
      if (!retentionCheck.isCompliant) {
        violations.push(`Retention policy violation: ${retentionCheck.reason}`)
      }

      // Assess transfer risks
      const riskAssessment = this.assessTransferRisks(request)

      // Create transfer record
      const transferId = this.generateTransferId()
      const transferRecord = {
        id: transferId,
        ...request,
        complianceCheck: Date.now(),
        riskAssessment,
        approved: violations.length === 0
      }

      this.transferRecords.set(transferId, transferRecord)

      return {
        isCompliant: violations.length === 0,
        violations,
        warnings,
        requiredActions,
        transferMechanism: request.transferMechanism,
        adequacyDecision: adequacyCheck.decision,
        bindingRules: this.getApplicableBindingRules(request.destinationCountry),
        contractualClauses: this.getApplicableSCCs(request.destinationCountry),
        transferRiskAssessment: riskAssessment
      }

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

      return {
        isCompliant: false,
        violations: ['Validation system error'],
        warnings: [],
        requiredActions: ['Contact compliance officer'],
        transferMechanism: 'unknown',
        transferRiskAssessment: {
          riskLevel: 'high',
          riskFactors: ['System error'],
          mitigationMeasures: ['Manual review required']
        }
      }
    }
  }

  private validateTransferMechanism(request: CrossBorderTransferRequest): {
    isValid: boolean
    reason?: string
  } {
    const validMechanisms = ['adequacy', 'bcr', 'scc', 'certification', 'derogation']

    if (!validMechanisms.includes(request.transferMechanism)) {
      return {
        isValid: false,
        reason: 'Invalid transfer mechanism specified'
      }
    }

    // Validate mechanism appropriateness based on data sensitivity
    const sensitiveCategories = ['personal_data', 'financial_data', 'health_data', 'biometric_data']

    if (request.dataCategories.some(cat => sensitiveCategories.includes(cat))) {
      if (request.transferMechanism === 'derogation') {
        return {
          isValid: false,
          reason: 'Derogations not appropriate for sensitive data'
        }
      }
    }

    return { isValid: true }
  }

  private validateAdequacyDecision(country: string): {
    hasAdequacy: boolean
    decision?: string
    expiryDate?: number
  } {
    const decision = this.adequacyDecisions.get(country)

    if (!decision) {
      return { hasAdequacy: false }
    }

    if (Date.now() > decision.expiryDate) {
      return { hasAdequacy: false, decision: 'Expired' }
    }

    return {
      hasAdequacy: true,
      decision: decision.reference,
      expiryDate: decision.expiryDate
    }
  }

  private hasAlternativeSafeguards(request: CrossBorderTransferRequest): boolean {
    // Check for binding corporate rules
    if (request.transferMechanism === 'bcr') {
      return this.hasValidBCR(request.destinationCountry)
    }

    // Check for standard contractual clauses
    if (request.transferMechanism === 'scc') {
      return this.hasValidSCCs(request.destinationCountry)
    }

    // Check for certification
    if (request.transferMechanism === 'certification') {
      return this.hasValidCertification(request.destinationCountry)
    }

    return false
  }

  private validateDataMinimization(dataCategories: string[], purpose: string): {
    isCompliant: boolean
    reason?: string
  } {
    // Define minimum required data for different purposes
    const requiredData: Record<string, string[]> = {
      'authentication': ['email', 'device_id'],
      'payment': ['payment_method', 'billing_address'],
      'shipping': ['shipping_address', 'contact_info'],
      'analytics': ['usage_data', 'device_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(request: CrossBorderTransferRequest): {
    isCompliant: boolean
    reason?: string
  } {
    // Check if transfer purpose is compatible with original collection purpose
    const compatiblePurposes: Record<string, string[]> = {
      'customer_service': ['support', 'billing', 'account_management'],
      'marketing': ['advertising', 'personalization', 'analytics'],
      'fraud_prevention': ['security', 'risk_assessment', 'compliance']
    }

    const purposeKey = Object.keys(compatiblePurposes).find(key =>
      request.transferPurpose.toLowerCase().includes(key)
    ) || 'other'

    const compatible = compatiblePurposes[purposeKey] || []

    if (compatible.length === 0) {
      return {
        isCompliant: false,
        reason: 'Transfer purpose not compatible with data processing purposes'
      }
    }

    return { isCompliant: true }
  }

  private validateCrossBorderRetention(request: CrossBorderTransferRequest): {
    isCompliant: boolean
    reason?: string
  } {
    // Validate retention periods for cross-border transfers
    const maxRetentionByCountry: Record<string, number> = {
      'US': 2555, // 7 years
      'EU': 2555, // 7 years
      'UK': 2190, // 6 years
      'CA': 2555, // 7 years
      'AU': 2555 // 7 years
    }

    const maxRetention = maxRetentionByCountry[request.destinationCountry] || 3650 // 10 years default

    if (request.retentionPeriod > maxRetention) {
      return {
        isCompliant: false,
        reason: `Retention period exceeds ${request.destinationCountry} maximum of ${maxRetention} days`
      }
    }

    return { isCompliant: true }
  }

  private assessTransferRisks(request: CrossBorderTransferRequest): {
    riskLevel: 'low' | 'medium' | 'high'
    riskFactors: string[]
    mitigationMeasures: string[]
  } {
    const riskFactors: string[] = []
    const mitigationMeasures: string[] = []

    // Assess data sensitivity
    const sensitiveCategories = ['personal_data', 'financial_data', 'health_data']
    if (request.dataCategories.some(cat => sensitiveCategories.includes(cat))) {
      riskFactors.push('Sensitive data categories')
      mitigationMeasures.push('Apply enhanced encryption and pseudonymization')
    }

    // Assess destination country risks
    const highRiskCountries = ['CN', 'RU', 'IR', 'KP']
    if (highRiskCountries.includes(request.destinationCountry)) {
      riskFactors.push('High-risk destination country')
      mitigationMeasures.push('Implement additional safeguards and monitoring')
    }

    // Assess transfer mechanism risks
    if (request.transferMechanism === 'derogation') {
      riskFactors.push('Reliance on derogations')
      mitigationMeasures.push('Document compelling legitimate interests')
    }

    // Determine overall risk level
    const riskScore = riskFactors.length
    const riskLevel = riskScore > 2 ? 'high' : riskScore > 1 ? 'medium' : 'low'

    return { riskLevel, riskFactors, mitigationMeasures }
  }

  private hasValidBCR(country: string): boolean {
    const bcr = this.bindingRules.get(country)
    return bcr && bcr.isActive && Date.now() < bcr.expiryDate
  }

  private hasValidSCCs(country: string): boolean {
    // In production, check if SCCs are valid for the country
    const sccCountries = ['US', 'CA', 'AU', 'JP', 'KR', 'SG']
    return sccCountries.includes(country)
  }

  private hasValidCertification(country: string): boolean {
    // In production, check certification validity
    const certifiedCountries = ['US', 'CA', 'CH', 'AR', 'UY']
    return certifiedCountries.includes(country)
  }

  private initializeAdequacyDecisions(): void {
    // In production, load from official EU adequacy decisions
    // For demo, populate with sample data

    const decisions = [
      {
        country: 'US',
        reference: 'EU-US Privacy Shield (Invalid)',
        decisionDate: new Date('2020-07-16').getTime(),
        expiryDate: new Date('2020-07-16').getTime(),
        isActive: false
      },
      {
        country: 'CA',
        reference: 'EU-Canada PNR Agreement',
        decisionDate: new Date('2014-12-01').getTime(),
        expiryDate: new Date('2024-12-01').getTime(),
        isActive: true
      }
    ]

    decisions.forEach(decision => {
      this.adequacyDecisions.set(decision.country, decision)
    })
  }

  private initializeBindingCorporateRules(): void {
    // In production, load from company BCR database
    // For demo, populate with sample data

    const rules = [
      {
        company: 'TechCorp',
        countries: ['US', 'CA', 'AU'],
        approvalDate: new Date('2023-01-01').getTime(),
        expiryDate: new Date('2026-01-01').getTime(),
        isActive: true
      }
    ]

    rules.forEach(rule => {
      rule.countries.forEach(country => {
        this.bindingRules.set(country, rule)
      })
    })
  }

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

  private getApplicableBindingRules(country: string): string[] {
    const rule = this.bindingRules.get(country)
    return rule ? [rule.company] : []
  }

  private getApplicableSCCs(country: string): string[] {
    if (this.hasValidSCCs(country)) {
      return ['EU Standard Contractual Clauses 2021']
    }
    return []
  }

  // Data Subject Rights for Cross-Border Data
  async handleCrossBorderDataSubjectRequest(
    dataSubjectId: string,
    right: string,
    sourceCountry: string,
    destinationCountry: string
  ): Promise<{
    success: boolean
    message: string
    affectedTransfers: number
    requiresInternationalCoordination: boolean
  }> {
    // Find all cross-border transfers for this data subject
    const subjectTransfers = Array.from(this.transferRecords.values())
      .filter(record => record.dataSubjectId === dataSubjectId)

    const crossBorderTransfers = subjectTransfers.filter(transfer =>
      transfer.sourceCountry !== transfer.destinationCountry
    )

    if (crossBorderTransfers.length === 0) {
      return {
        success: true,
        message: 'No cross-border transfers found for data subject',
        affectedTransfers: 0,
        requiresInternationalCoordination: false
      }
    }

    // Check if international coordination is required
    const uniqueCountries = new Set([
      ...crossBorderTransfers.map(t => t.sourceCountry),
      ...crossBorderTransfers.map(t => t.destinationCountry)
    ])

    const requiresInternationalCoordination = uniqueCountries.size > 1

    // Process the right across all relevant transfers
    for (const transfer of crossBorderTransfers) {
      await this.processDataSubjectRight(transfer, right, sourceCountry, destinationCountry)
    }

    return {
      success: true,
      message: `${right} processed for ${crossBorderTransfers.length} cross-border transfers`,
      affectedTransfers: crossBorderTransfers.length,
      requiresInternationalCoordination
    }
  }

  private async processDataSubjectRight(
    transfer: any,
    right: string,
    sourceCountry: string,
    destinationCountry: string
  ): Promise<void> {
    // In production, coordinate with data processors in destination country
    // For demo, log the action

    console.log(`Processing ${right} for transfer ${transfer.id} from ${sourceCountry} to ${destinationCountry}`)

    // Update transfer record
    transfer.dataSubjectRights.push({
      right,
      processedDate: Date.now(),
      sourceCountry,
      destinationCountry
    })
  }

  // Compliance Reporting
  generateCrossBorderComplianceReport(period: { start: number; end: number }): {
    totalTransfers: number
    compliantTransfers: number
    violations: number
    riskAssessments: {
      low: number
      medium: number
      high: number
    }
    topDestinationCountries: Array<{ country: string; count: number }>
    transferMechanisms: Record<string, number>
  } {
    const periodTransfers = Array.from(this.transferRecords.values())
      .filter(record => record.complianceCheck >= period.start && record.complianceCheck <= period.end)

    const compliantTransfers = periodTransfers.filter(t => t.approved).length

    // Analyze risk levels
    const riskAssessments = periodTransfers.reduce(
      (acc, transfer) => {
        acc[transfer.riskAssessment.riskLevel]++
        return acc
      },
      { low: 0, medium: 0, high: 0 }
    )

    // Count destination countries
    const countryCounts = new Map<string, number>()
    periodTransfers.forEach(transfer => {
      const count = countryCounts.get(transfer.destinationCountry) || 0
      countryCounts.set(transfer.destinationCountry, count + 1)
    })

    const topDestinationCountries = Array.from(countryCounts.entries())
      .sort(([, a], [, b]) => b - a)
      .slice(0, 10)
      .map(([country, count]) => ({ country, count }))

    // Count transfer mechanisms
    const transferMechanisms = periodTransfers.reduce(
      (acc, transfer) => {
        acc[transfer.transferMechanism] = (acc[transfer.transferMechanism] || 0) + 1
        return acc
      },
      {} as Record<string, number>
    )

    return {
      totalTransfers: periodTransfers.length,
      compliantTransfers,
      violations: periodTransfers.length - compliantTransfers,
      riskAssessments,
      topDestinationCountries,
      transferMechanisms
    }
  }
}

// Initialize GDPR cross-border 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
  },
  crossBorderTransfers: {
    adequacyDecisions: true,
    bindingCorporateRules: true,
    standardContractualClauses: true,
    certifications: true
  }
}

const crossBorderGDPRCompliance = new CrossBorderGDPRComplianceEngine(gdprConfig)

// Cross-border GDPR compliance validation endpoint
app.post('/api/gdpr/validate-cross-border-transfer', async (req, res) => {
  try {
    const {
      dataSubjectId,
      sourceCountry,
      destinationCountry,
      dataCategories,
      transferPurpose,
      legalBasis,
      transferMechanism,
      safeguards,
      retentionPeriod
    } = req.body

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

    const request: CrossBorderTransferRequest = {
      dataSubjectId,
      sourceCountry,
      destinationCountry,
      dataCategories,
      transferPurpose,
      legalBasis: legalBasis || 'legitimate_interest',
      transferMechanism: transferMechanism || 'adequacy',
      safeguards,
      retentionPeriod: retentionPeriod || 365
    }

    const result = await crossBorderGDPRCompliance.validateCrossBorderTransfer(request)

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

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

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

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

    const result = await crossBorderGDPRCompliance.handleCrossBorderDataSubjectRequest(
      dataSubjectId,
      right,
      sourceCountry,
      destinationCountry
    )

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

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

// Cross-border compliance report endpoint
app.get('/api/gdpr/cross-border-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 = crossBorderGDPRCompliance.generateCrossBorderComplianceReport({ start, end })

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

  } catch (error) {
    console.error('Cross-border compliance report generation error:', error)
    res.status(500).json({ error: 'Report generation failed' })
  }
})

console.log('Cross-Border GDPR Compliance Engine initialized')

International Data Transfer Compliance System

// Comprehensive international data transfer compliance system
interface InternationalComplianceConfig {
  gdpr: {
    enabled: boolean
    adequacyDecisions: boolean
    standardContractualClauses: boolean
    bindingCorporateRules: boolean
  }
  ccpa: {
    enabled: boolean
    nonDiscrimination: boolean
    optOutMechanism: boolean
  }
  lgpd: {
    enabled: boolean
    dataSubjectRights: boolean
    dataProtectionOfficer: boolean
  }
  pdpa: {
    enabled: boolean
    consentManagement: boolean
    crossBorderRequirements: boolean
  }
  pipeda: {
    enabled: boolean
    consentRequirements: boolean
    accountability: boolean
  }
  transferMechanisms: {
    adequacyDecisions: string[]
    sccs: string[]
    bcrs: string[]
    certifications: string[]
    derogations: string[]
  }
}

interface DataTransferAssessment {
  transferId: string
  source: {
    country: string
    region: string
    dataProtectionLevel: 'adequate' | 'partial' | 'inadequate'
  }
  destination: {
    country: string
    region: string
    dataProtectionLevel: 'adequate' | 'partial' | 'inadequate'
    applicableLaws: string[]
  }
  data: {
    categories: string[]
    sensitivity: 'low' | 'medium' | 'high' | 'critical'
    volume: number
    retentionPeriod: number
  }
  purpose: {
    primaryPurpose: string
    secondaryPurposes: string[]
    legitimateInterest?: string
  }
  legalBases: string[]
  transferMechanism: string
  safeguards: string[]
  riskAssessment: {
    overallRisk: 'low' | 'medium' | 'high'
    dataBreachRisk: number
    unauthorizedAccessRisk: number
    retentionRisk: number
    thirdCountryRisk: number
  }
  complianceStatus: 'compliant' | 'conditional' | 'non_compliant'
  recommendations: string[]
}

class InternationalDataTransferComplianceSystem {
  private config: InternationalComplianceConfig
  private transferAssessments: Map<string, DataTransferAssessment> = new Map()
  private countryProfiles: Map<string, any> = new Map()

  constructor(config: InternationalComplianceConfig) {
    this.config = config
    this.initializeCountryProfiles()
  }

  async assessDataTransfer(
    sourceCountry: string,
    destinationCountry: string,
    dataCategories: string[],
    purpose: string,
    legalBasis: string[]
  ): Promise<DataTransferAssessment> {
    const transferId = this.generateTransferId()

    try {
      // Get country profiles
      const sourceProfile = this.getCountryProfile(sourceCountry)
      const destinationProfile = this.getCountryProfile(destinationCountry)

      // Assess data sensitivity
      const sensitivity = this.assessDataSensitivity(dataCategories)

      // Determine applicable legal frameworks
      const applicableLaws = this.determineApplicableLaws(destinationCountry)

      // Evaluate transfer mechanism
      const transferMechanism = this.determineTransferMechanism(sourceProfile, destinationProfile)

      // Assess risks
      const riskAssessment = this.performRiskAssessment(
        sourceProfile,
        destinationProfile,
        dataCategories,
        sensitivity
      )

      // Generate compliance recommendations
      const recommendations = this.generateComplianceRecommendations(
        transferMechanism,
        riskAssessment,
        applicableLaws
      )

      // Determine compliance status
      const complianceStatus = this.determineComplianceStatus(
        transferMechanism,
        riskAssessment,
        recommendations
      )

      const assessment: DataTransferAssessment = {
        transferId,
        source: sourceProfile,
        destination: destinationProfile,
        data: {
          categories: dataCategories,
          sensitivity,
          volume: 1000, // In production, calculate actual volume
          retentionPeriod: 365 // In production, use actual retention period
        },
        purpose: {
          primaryPurpose: purpose,
          secondaryPurposes: ['analytics', 'improvement']
        },
        legalBases: legalBasis,
        transferMechanism,
        safeguards: this.getApplicableSafeguards(transferMechanism, destinationCountry),
        riskAssessment,
        complianceStatus,
        recommendations
      }

      this.transferAssessments.set(transferId, assessment)

      return assessment

    } catch (error) {
      console.error('International data transfer assessment failed:', error)

      return {
        transferId,
        source: this.getCountryProfile(sourceCountry),
        destination: this.getCountryProfile(destinationCountry),
        data: {
          categories: dataCategories,
          sensitivity: 'high',
          volume: 0,
          retentionPeriod: 0
        },
        purpose: {
          primaryPurpose: purpose,
          secondaryPurposes: []
        },
        legalBases: [],
        transferMechanism: 'unknown',
        safeguards: [],
        riskAssessment: {
          overallRisk: 'high',
          dataBreachRisk: 100,
          unauthorizedAccessRisk: 100,
          retentionRisk: 100,
          thirdCountryRisk: 100
        },
        complianceStatus: 'non_compliant',
        recommendations: ['Assessment failed - manual review required']
      }
    }
  }

  private assessDataSensitivity(dataCategories: string[]): 'low' | 'medium' | 'high' | 'critical' {
    const criticalCategories = ['health_data', 'biometric_data', 'genetic_data', 'criminal_records']
    const highCategories = ['personal_data', 'financial_data', 'location_data']
    const mediumCategories = ['contact_data', 'behavioral_data', 'preferences']

    if (dataCategories.some(cat => criticalCategories.includes(cat))) {
      return 'critical'
    }

    if (dataCategories.some(cat => highCategories.includes(cat))) {
      return 'high'
    }

    if (dataCategories.some(cat => mediumCategories.includes(cat))) {
      return 'medium'
    }

    return 'low'
  }

  private determineApplicableLaws(country: string): string[] {
    const laws: string[] = []

    // GDPR (EU countries + countries with GDPR-like laws)
    if (this.isGDPREquivalent(country)) {
      laws.push('GDPR')
    }

    // CCPA (California, US)
    if (country === 'US' && this.hasCCPAEquivalent(country)) {
      laws.push('CCPA')
    }

    // LGPD (Brazil)
    if (country === 'BR') {
      laws.push('LGPD')
    }

    // PDPA (Thailand, Singapore, etc.)
    if (this.isPDPACompliant(country)) {
      laws.push('PDPA')
    }

    // PIPEDA (Canada)
    if (country === 'CA') {
      laws.push('PIPEDA')
    }

    return laws
  }

  private isGDPREquivalent(country: string): boolean {
    const gdprCountries = [
      'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU',
      'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE'
    ]
    return gdprCountries.includes(country) || country === 'GB' || country === 'CH' || country === 'NO'
  }

  private hasCCPAEquivalent(country: string): boolean {
    return country === 'US' // In production, check for state-level privacy laws
  }

  private isPDPACompliant(country: string): boolean {
    const pdpaCountries = ['TH', 'SG', 'MY', 'PH', 'ID', 'VN']
    return pdpaCountries.includes(country)
  }

  private determineTransferMechanism(
    sourceProfile: any,
    destinationProfile: any
  ): string {
    // Determine appropriate transfer mechanism based on country profiles
    if (destinationProfile.dataProtectionLevel === 'adequate') {
      return 'adequacy_decision'
    }

    if (sourceProfile.dataProtectionLevel === 'adequate' &&
        destinationProfile.dataProtectionLevel === 'partial') {
      return 'standard_contractual_clauses'
    }

    if (this.hasBindingCorporateRules(sourceProfile.country)) {
      return 'binding_corporate_rules'
    }

    return 'standard_contractual_clauses'
  }

  private performRiskAssessment(
    sourceProfile: any,
    destinationProfile: any,
    dataCategories: string[],
    sensitivity: string
  ): DataTransferAssessment['riskAssessment'] {
    let dataBreachRisk = 20 // Base risk
    let unauthorizedAccessRisk = 15
    let retentionRisk = 10
    let thirdCountryRisk = 25

    // Adjust based on data sensitivity
    switch (sensitivity) {
      case 'critical':
        dataBreachRisk += 50
        unauthorizedAccessRisk += 40
        break
      case 'high':
        dataBreachRisk += 30
        unauthorizedAccessRisk += 25
        break
      case 'medium':
        dataBreachRisk += 15
        unauthorizedAccessRisk += 10
        break
    }

    // Adjust based on destination country
    if (destinationProfile.dataProtectionLevel === 'inadequate') {
      thirdCountryRisk += 40
    } else if (destinationProfile.dataProtectionLevel === 'partial') {
      thirdCountryRisk += 20
    }

    // Calculate overall risk
    const overallRiskScore = (dataBreachRisk + unauthorizedAccessRisk + retentionRisk + thirdCountryRisk) / 4
    const overallRisk = overallRiskScore > 60 ? 'high' : overallRiskScore > 30 ? 'medium' : 'low'

    return {
      overallRisk,
      dataBreachRisk: Math.min(dataBreachRisk, 100),
      unauthorizedAccessRisk: Math.min(unauthorizedAccessRisk, 100),
      retentionRisk: Math.min(retentionRisk, 100),
      thirdCountryRisk: Math.min(thirdCountryRisk, 100)
    }
  }

  private generateComplianceRecommendations(
    transferMechanism: string,
    riskAssessment: any,
    applicableLaws: string[]
  ): string[] {
    const recommendations: string[] = []

    // Mechanism-specific recommendations
    switch (transferMechanism) {
      case 'adequacy_decision':
        recommendations.push('Monitor adequacy decision validity')
        break
      case 'standard_contractual_clauses':
        recommendations.push('Implement and maintain SCCs')
        recommendations.push('Conduct regular compliance audits')
        break
      case 'binding_corporate_rules':
        recommendations.push('Ensure BCR approval is current')
        recommendations.push('Train staff on BCR requirements')
        break
    }

    // Risk-based recommendations
    if (riskAssessment.overallRisk === 'high') {
      recommendations.push('Implement enhanced security measures')
      recommendations.push('Conduct privacy impact assessment')
      recommendations.push('Obtain explicit consent where required')
    }

    // Law-specific recommendations
    if (applicableLaws.includes('GDPR')) {
      recommendations.push('Appoint EU representative if required')
      recommendations.push('Maintain records of processing activities')
    }

    if (applicableLaws.includes('CCPA')) {
      recommendations.push('Implement do-not-sell mechanism')
      recommendations.push('Provide privacy notice at collection')
    }

    return recommendations
  }

  private determineComplianceStatus(
    transferMechanism: string,
    riskAssessment: any,
    recommendations: string[]
  ): 'compliant' | 'conditional' | 'non_compliant' {
    if (riskAssessment.overallRisk === 'high' && !recommendations.some(r => r.includes('enhanced'))) {
      return 'non_compliant'
    }

    if (riskAssessment.overallRisk === 'medium' || recommendations.length > 5) {
      return 'conditional'
    }

    return 'compliant'
  }

  private getApplicableSafeguards(transferMechanism: string, country: string): string[] {
    const safeguards: string[] = []

    switch (transferMechanism) {
      case 'adequacy_decision':
        safeguards.push('EU Adequacy Decision')
        break
      case 'standard_contractual_clauses':
        safeguards.push('EU SCCs 2021')
        safeguards.push('Supplementary measures')
        break
      case 'binding_corporate_rules':
        safeguards.push('Approved BCR')
        break
      case 'certification':
        safeguards.push('Approved certification scheme')
        break
    }

    return safeguards
  }

  private hasBindingCorporateRules(country: string): boolean {
    // In production, check company BCR database
    return ['US', 'CA', 'AU'].includes(country)
  }

  private initializeCountryProfiles(): void {
    // In production, load comprehensive country data protection profiles
    // For demo, populate with sample data

    const profiles = [
      {
        country: 'US',
        region: 'North America',
        dataProtectionLevel: 'partial',
        applicableLaws: ['CCPA', 'State Laws'],
        enforcement: 'FTC, State AGs',
        penalties: 'Civil penalties, class actions',
        lastUpdated: Date.now()
      },
      {
        country: 'DE',
        region: 'Europe',
        dataProtectionLevel: 'adequate',
        applicableLaws: ['GDPR', 'BDSG'],
        enforcement: 'Data Protection Authorities',
        penalties: 'Administrative fines up to 4% global turnover',
        lastUpdated: Date.now()
      }
    ]

    profiles.forEach(profile => {
      this.countryProfiles.set(profile.country, profile)
    })
  }

  private getCountryProfile(country: string): any {
    return this.countryProfiles.get(country) || {
      country,
      region: 'Unknown',
      dataProtectionLevel: 'inadequate',
      applicableLaws: ['Unknown'],
      enforcement: 'Unknown',
      penalties: 'Unknown'
    }
  }

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

  // Generate compliance report
  generateComplianceReport(period: { start: number; end: number }): {
    totalAssessments: number
    compliantTransfers: number
    conditionalTransfers: number
    nonCompliantTransfers: number
    riskDistribution: Record<string, number>
    topDestinationCountries: Array<{ country: string; count: number }>
    mechanismUsage: Record<string, number>
  } {
    const periodAssessments = Array.from(this.transferAssessments.values())
      .filter(assessment => assessment.transferId.includes(period.start.toString().substring(0, 10)))

    const compliantTransfers = periodAssessments.filter(a => a.complianceStatus === 'compliant').length
    const conditionalTransfers = periodAssessments.filter(a => a.complianceStatus === 'conditional').length
    const nonCompliantTransfers = periodAssessments.filter(a => a.complianceStatus === 'non_compliant').length

    // Risk distribution
    const riskDistribution = periodAssessments.reduce(
      (acc, assessment) => {
        acc[assessment.riskAssessment.overallRisk] = (acc[assessment.riskAssessment.overallRisk] || 0) + 1
        return acc
      },
      {} as Record<string, number>
    )

    // Top destination countries
    const countryCounts = new Map<string, number>()
    periodAssessments.forEach(assessment => {
      const count = countryCounts.get(assessment.destination.country) || 0
      countryCounts.set(assessment.destination.country, count + 1)
    })

    const topDestinationCountries = Array.from(countryCounts.entries())
      .sort(([, a], [, b]) => b - a)
      .slice(0, 10)
      .map(([country, count]) => ({ country, count }))

    // Transfer mechanism usage
    const mechanismUsage = periodAssessments.reduce(
      (acc, assessment) => {
        acc[assessment.transferMechanism] = (acc[assessment.transferMechanism] || 0) + 1
        return acc
      },
      {} as Record<string, number>
    )

    return {
      totalAssessments: periodAssessments.length,
      compliantTransfers,
      conditionalTransfers,
      nonCompliantTransfers,
      riskDistribution,
      topDestinationCountries,
      mechanismUsage
    }
  }
}

// Initialize international data transfer compliance system
const internationalComplianceConfig: InternationalComplianceConfig = {
  gdpr: {
    enabled: true,
    adequacyDecisions: true,
    standardContractualClauses: true,
    bindingCorporateRules: true
  },
  ccpa: {
    enabled: true,
    nonDiscrimination: true,
    optOutMechanism: true
  },
  lgpd: {
    enabled: true,
    dataSubjectRights: true,
    dataProtectionOfficer: true
  },
  pdpa: {
    enabled: true,
    consentManagement: true,
    crossBorderRequirements: true
  },
  pipeda: {
    enabled: true,
    consentRequirements: true,
    accountability: true
  },
  transferMechanisms: {
    adequacyDecisions: ['EU', 'UK', 'CH'],
    sccs: ['US', 'CA', 'AU', 'JP', 'KR'],
    bcrs: ['US', 'CA', 'AU'],
    certifications: ['US', 'CA', 'CH'],
    derogations: ['compelling_legitimate_interests', 'vital_interests', 'public_interest']
  }
}

const internationalComplianceSystem = new InternationalDataTransferComplianceSystem(internationalComplianceConfig)

// International data transfer assessment endpoint
app.post('/api/compliance/assess-transfer', async (req, res) => {
  try {
    const { sourceCountry, destinationCountry, dataCategories, purpose, legalBasis } = req.body

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

    const assessment = await internationalComplianceSystem.assessDataTransfer(
      sourceCountry,
      destinationCountry,
      dataCategories,
      purpose,
      legalBasis || ['legitimate_interest']
    )

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

  } catch (error) {
    console.error('International compliance assessment error:', error)
    res.status(500).json({ error: 'Assessment failed' })
  }
})

// Compliance report endpoint
app.get('/api/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 = internationalComplianceSystem.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('International Data Transfer Compliance System initialized')

Practical Implementation Examples

  1. Cross-border policy engine (decide transfer path, mask level, and mechanism):
type TransferCtx = { src: string; dst: string; purpose: 'fraud'|'personalization'|'legal'; sensitivity: 'low'|'high' }

function decideTransfer(ctx: TransferCtx) {
  const adequate = ['EEA','GB','CH','NZ','JP','KR']
  const isAdequate = adequate.includes(ctx.dst)
  const mechanism = isAdequate ? 'adequacy' : 'SCC-Module-2'
  const maskLevel = ctx.purpose === 'personalization' ? 'city-only' : 'region-only'
  const retentionDays = ctx.purpose === 'fraud' ? 365 : 90
  return { mechanism, maskLevel, retentionDays }
}
  1. Regionalization pattern (keep raw in-region, export derived):
  • Raw IP and full resolution geo retained in-region storage; export only hashed IP and country/region for analytics.
  • Use message bus with field-level encryption; consumers outside region decrypt only allowed fields.
  1. Consent and opt-out signals:
  • Respect GPC and store opt-out scope per region; degrade to non-personalized localization when opted-out.

Operational Controls and Playbooks

  • Data lifecycle: configurable TTL by purpose; enforce deletion jobs; verify with deletion proofs.
  • Subprocessor management: DPAs, audits, SCC flow-down, breach clauses; maintain live registry.
  • Key management: KMS/HSM backed keys, rotation ≤ 90 days for sensitive contexts, access logging with immutable store.
  • Access: break-glass with approvals, session recording, periodic access recertifications.
  • Testing: privacy unit tests (masking, purpose gates), TIA unit snapshots, SCC module choice tests.

Monitoring, Auditing, and Evidence

  • Evidence artifacts: signed DPA versions, SCC annexes, TIA records, adequacy cache, key-rotation logs, deletion job logs.
  • Dashboards: transfers by mechanism and destination, TIA outcomes, opt-out rates, retention backlog, access anomalies.
  • Alerts: adequacy change, SCC update, overdue DPIA, key not rotated, failed deletion, unusual cross-region queries.

Conclusion

For IP geolocation workloads, sustainable cross-border compliance combines minimization, regionalization, strong cryptography, and explicit transfer mechanisms (SCC/BCR/DPF) evidenced by living records (RoPA, TIAs, DPAs). Build controls into the pipeline rather than bolting them on.

We can help design and audit these controls end-to-end, from SCC selection to evidence automation.

Tags:data-complianceprivacy-lawsinternational-regulationslegal-requirements