Home/Blog/GDPR Technical Implementation Guide: Data Protection Compliance for Engineering Teams

GDPR Technical Implementation Guide: Data Protection Compliance for Engineering Teams

Comprehensive technical guide to GDPR compliance implementation. Learn data mapping, consent management, DSAR automation, pseudonymization, privacy by design patterns, and breach notification systems.

By Inventive Software Engineering
GDPR Technical Implementation Guide: Data Protection Compliance for Engineering Teams

GDPR Technical Implementation Guide

The General Data Protection Regulation (GDPR) requires organizations to implement comprehensive data protection measures. This guide covers the technical implementation aspects, from data mapping to automated compliance systems.

GDPR Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────┐
│                    GDPR COMPLIANCE ARCHITECTURE                             │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  DATA SUBJECT RIGHTS (Articles 15-22)                                       │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │                                                                        │ │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐        │ │
│  │  │ Access  │ │Rectify  │ │ Erasure │ │Restrict │ │Portabil │        │ │
│  │  │Art. 15  │ │Art. 16  │ │Art. 17  │ │Art. 18  │ │Art. 20  │        │ │
│  │  └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘        │ │
│  │       │           │           │           │           │              │ │
│  │       └───────────┴───────────┼───────────┴───────────┘              │ │
│  │                               │                                       │ │
│  │                               ▼                                       │ │
│  │                    ┌─────────────────────┐                           │ │
│  │                    │   DSAR MANAGEMENT   │                           │ │
│  │                    │      SYSTEM         │                           │ │
│  │                    └──────────┬──────────┘                           │ │
│  │                               │                                       │ │
│  └───────────────────────────────┼───────────────────────────────────────┘ │
│                                  │                                         │
│  ┌───────────────────────────────┼───────────────────────────────────────┐ │
│  │                               │                                        │ │
│  │  DATA PROCESSING ACTIVITIES   │                                        │ │
│  │  ┌────────────────────────────┴────────────────────────────┐          │ │
│  │  │                                                          │          │ │
│  │  │   ┌──────────────┐    ┌──────────────┐    ┌──────────┐ │          │ │
│  │  │   │   CONSENT    │    │    DATA      │    │  LAWFUL  │ │          │ │
│  │  │   │  MANAGEMENT  │    │   MAPPING    │    │   BASIS  │ │          │ │
│  │  │   │   (Art. 7)   │    │   (Art. 30)  │    │  (Art. 6)│ │          │ │
│  │  │   └──────────────┘    └──────────────┘    └──────────┘ │          │ │
│  │  │                                                          │          │ │
│  │  └──────────────────────────────────────────────────────────┘          │ │
│  │                                                                        │ │
│  │  ┌────────────────────────────────────────────────────────────────┐   │ │
│  │  │                    DATA PROTECTION MEASURES                     │   │ │
│  │  │                                                                  │   │ │
│  │  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐  │   │ │
│  │  │  │Encryption│ │Pseudonym │ │ Access   │ │ Security by      │  │   │ │
│  │  │  │(Art. 32) │ │(Art. 4)  │ │ Control  │ │ Design (Art. 25) │  │   │ │
│  │  │  └──────────┘ └──────────┘ └──────────┘ └──────────────────┘  │   │ │
│  │  │                                                                  │   │ │
│  │  └────────────────────────────────────────────────────────────────┘   │ │
│  │                                                                        │ │
│  └────────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  ┌────────────────────────────────────────────────────────────────────────┐│
│  │                     COMPLIANCE DOCUMENTATION                           ││
│  │  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ ││
│  │  │Processing│ │   DPIA   │ │  Breach  │ │  DPA     │ │   Privacy    │ ││
│  │  │ Records  │ │(Art. 35) │ │  Log     │ │Contracts │ │   Notice     │ ││
│  │  │(Art. 30) │ │          │ │(Art. 33) │ │(Art. 28) │ │ (Art. 13/14) │ ││
│  │  └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ ││
│  └────────────────────────────────────────────────────────────────────────┘│
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Data Mapping Implementation

Data Inventory Structure

// Data mapping schema
interface DataInventoryRecord {
  id: string;
  dataCategory: string;
  personalDataTypes: PersonalDataType[];
  specialCategoryData: boolean;

  // Processing details
  processingPurposes: string[];
  lawfulBasis: LawfulBasis;
  consentRequired: boolean;

  // Data subjects
  dataSubjectCategories: string[];
  estimatedVolume: number;

  // Data sources and destinations
  sources: DataSource[];
  recipients: DataRecipient[];
  thirdCountryTransfers: ThirdCountryTransfer[];

  // Retention
  retentionPeriod: string;
  retentionJustification: string;

  // Security
  securityMeasures: string[];
  encryptionAtRest: boolean;
  encryptionInTransit: boolean;
  pseudonymized: boolean;

  // Systems
  systems: string[];
  databases: string[];

  // Metadata
  dataOwner: string;
  lastReview: Date;
  nextReview: Date;
}

type LawfulBasis =
  | 'consent'           // Article 6(1)(a)
  | 'contract'          // Article 6(1)(b)
  | 'legal_obligation'  // Article 6(1)(c)
  | 'vital_interests'   // Article 6(1)(d)
  | 'public_task'       // Article 6(1)(e)
  | 'legitimate_interests'; // Article 6(1)(f)

interface ThirdCountryTransfer {
  country: string;
  recipient: string;
  mechanism: 'adequacy_decision' | 'standard_clauses' | 'bcr' | 'derogation';
  documentation: string;
}

Data Discovery Automation

#!/usr/bin/env python3
"""
Automated PII discovery for GDPR data mapping
Scans databases for personal data patterns
"""

import re
from dataclasses import dataclass
from typing import List, Dict
import sqlalchemy

@dataclass
class PIIPattern:
    name: str
    pattern: str
    category: str
    special_category: bool = False

# PII detection patterns
PII_PATTERNS = [
    PIIPattern("email", r'^[\w\.-]+@[\w\.-]+\.\w+$', "contact"),
    PIIPattern("phone", r'^\+?[\d\s\-\(\)]{10,}$', "contact"),
    PIIPattern("ssn", r'^\d{3}-\d{2}-\d{4}$', "government_id"),
    PIIPattern("credit_card", r'^\d{4}[\s\-]?\d{4}[\s\-]?\d{4}[\s\-]?\d{4}$', "financial"),
    PIIPattern("ip_address", r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$', "technical"),
    PIIPattern("date_of_birth", r'^\d{4}-\d{2}-\d{2}$', "personal"),
    # Special category data
    PIIPattern("health_condition", r'(?i)(diagnosis|medical|health|disease)', "health", True),
    PIIPattern("religious", r'(?i)(religion|faith|worship|church|mosque)', "belief", True),
    PIIPattern("political", r'(?i)(party|political|vote|election)', "political", True),
]

def scan_database(connection_string: str) -> Dict:
    """Scan database for PII columns"""
    engine = sqlalchemy.create_engine(connection_string)
    inspector = sqlalchemy.inspect(engine)

    findings = []

    for table_name in inspector.get_table_names():
        columns = inspector.get_columns(table_name)

        for column in columns:
            col_name = column['name'].lower()

            # Check column names for PII indicators
            pii_indicators = ['email', 'phone', 'name', 'address', 'ssn',
                            'dob', 'birth', 'card', 'account']

            for indicator in pii_indicators:
                if indicator in col_name:
                    findings.append({
                        'table': table_name,
                        'column': column['name'],
                        'type': column['type'],
                        'pii_indicator': indicator,
                        'requires_review': True
                    })

    # Sample data for pattern matching
    with engine.connect() as conn:
        for finding in findings:
            query = f"SELECT DISTINCT {finding['column']} FROM {finding['table']} LIMIT 100"
            try:
                result = conn.execute(sqlalchemy.text(query))
                samples = [str(row[0]) for row in result if row[0]]

                # Match against PII patterns
                for sample in samples[:10]:
                    for pattern in PII_PATTERNS:
                        if re.match(pattern.pattern, sample):
                            finding['confirmed_pii'] = pattern.name
                            finding['category'] = pattern.category
                            finding['special_category'] = pattern.special_category
                            break
            except Exception as e:
                finding['error'] = str(e)

    return {
        'scan_date': datetime.now().isoformat(),
        'database': connection_string.split('@')[-1],
        'findings': findings,
        'summary': {
            'tables_scanned': len(inspector.get_table_names()),
            'pii_columns_found': len([f for f in findings if f.get('confirmed_pii')]),
            'special_category_found': len([f for f in findings if f.get('special_category')])
        }
    }

if __name__ == '__main__':
    import sys
    results = scan_database(sys.argv[1])
    print(json.dumps(results, indent=2))
// Consent management types
interface ConsentRecord {
  id: string;
  dataSubjectId: string;

  // Consent details
  purpose: string;
  processingActivities: string[];

  // Consent properties (GDPR Article 7 requirements)
  givenAt: Date;
  collectionMethod: 'explicit_checkbox' | 'double_opt_in' | 'written';
  ipAddress?: string;
  userAgent?: string;

  // Consent text shown
  consentTextVersion: string;
  consentTextHash: string;

  // Status
  status: 'active' | 'withdrawn';
  withdrawnAt?: Date;

  // Evidence
  evidence: ConsentEvidence;
}

interface ConsentEvidence {
  screenshot?: string;
  formSubmission: Record<string, any>;
  timestamp: Date;
  source: string;
}

// Consent management service
class ConsentService {
  async recordConsent(
    dataSubjectId: string,
    consents: ConsentRequest[]
  ): Promise<ConsentRecord[]> {

    const records: ConsentRecord[] = [];

    for (const consent of consents) {
      // Validate consent is freely given (no pre-checked boxes)
      if (consent.preChecked) {
        throw new Error('Pre-checked consent is not valid under GDPR');
      }

      // Validate consent is specific (one purpose per consent)
      if (consent.purposes.length > 1) {
        throw new Error('Consent must be specific to each purpose');
      }

      const record: ConsentRecord = {
        id: generateUUID(),
        dataSubjectId,
        purpose: consent.purpose,
        processingActivities: consent.processingActivities,
        givenAt: new Date(),
        collectionMethod: consent.method,
        consentTextVersion: consent.textVersion,
        consentTextHash: hashConsentText(consent.text),
        status: 'active',
        evidence: {
          formSubmission: consent.formData,
          timestamp: new Date(),
          source: consent.source
        }
      };

      await this.store.save(record);
      records.push(record);
    }

    return records;
  }

  async withdrawConsent(
    dataSubjectId: string,
    consentId: string
  ): Promise<void> {
    const consent = await this.store.findById(consentId);

    if (consent.dataSubjectId !== dataSubjectId) {
      throw new Error('Unauthorized');
    }

    consent.status = 'withdrawn';
    consent.withdrawnAt = new Date();

    await this.store.save(consent);

    // Trigger downstream processing cessation
    await this.processingService.stopProcessing(
      dataSubjectId,
      consent.processingActivities
    );
  }

  async getConsentStatus(
    dataSubjectId: string,
    purpose: string
  ): Promise<boolean> {
    const consent = await this.store.findActiveConsent(
      dataSubjectId,
      purpose
    );

    return consent?.status === 'active';
  }
}
// GDPR-compliant cookie consent implementation
interface CookieCategory {
  id: string;
  name: string;
  description: string;
  required: boolean;  // Strictly necessary = required, no consent needed
  cookies: CookieDefinition[];
}

interface CookieConsentConfig {
  categories: CookieCategory[];
  privacyPolicyUrl: string;
  cookiePolicyUrl: string;
  dpoContact: string;
}

const cookieConfig: CookieConsentConfig = {
  categories: [
    {
      id: 'necessary',
      name: 'Strictly Necessary',
      description: 'Essential for the website to function. Cannot be disabled.',
      required: true,
      cookies: [
        { name: 'session_id', purpose: 'User session', duration: 'Session' },
        { name: 'csrf_token', purpose: 'Security', duration: 'Session' }
      ]
    },
    {
      id: 'analytics',
      name: 'Analytics',
      description: 'Help us understand how visitors use our website.',
      required: false,
      cookies: [
        { name: '_ga', purpose: 'Google Analytics', duration: '2 years' },
        { name: '_gid', purpose: 'Google Analytics', duration: '24 hours' }
      ]
    },
    {
      id: 'marketing',
      name: 'Marketing',
      description: 'Used to deliver relevant advertisements.',
      required: false,
      cookies: [
        { name: '_fbp', purpose: 'Facebook Pixel', duration: '90 days' }
      ]
    }
  ],
  privacyPolicyUrl: '/privacy',
  cookiePolicyUrl: '/cookies',
  dpoContact: '[email protected]'
};

// React component for cookie banner
function CookieConsentBanner() {
  const [preferences, setPreferences] = useState<Record<string, boolean>>({});
  const [showDetails, setShowDetails] = useState(false);

  const handleAcceptAll = () => {
    const allAccepted = Object.fromEntries(
      cookieConfig.categories.map(c => [c.id, true])
    );
    savePreferences(allAccepted);
  };

  const handleRejectOptional = () => {
    const onlyNecessary = Object.fromEntries(
      cookieConfig.categories.map(c => [c.id, c.required])
    );
    savePreferences(onlyNecessary);
  };

  const handleSavePreferences = () => {
    savePreferences(preferences);
  };

  return (
    <div className="cookie-banner">
      <h3>We use cookies</h3>
      <p>
        We use cookies to improve your experience. See our{' '}
        <a href={cookieConfig.cookiePolicyUrl}>Cookie Policy</a>.
      </p>

      {showDetails && (
        <div className="cookie-categories">
          {cookieConfig.categories.map(category => (
            <div key={category.id} className="category">
              <label>
                <input
                  type="checkbox"
                  checked={category.required || preferences[category.id]}
                  disabled={category.required}
                  onChange={(e) => setPreferences({
                    ...preferences,
                    [category.id]: e.target.checked
                  })}
                />
                <strong>{category.name}</strong>
                {category.required && <span>(Required)</span>}
              </label>
              <p>{category.description}</p>
            </div>
          ))}
        </div>
      )}

      <div className="actions">
        <button onClick={handleRejectOptional}>
          Reject Optional
        </button>
        <button onClick={() => setShowDetails(!showDetails)}>
          Manage Preferences
        </button>
        <button onClick={handleAcceptAll} className="primary">
          Accept All
        </button>
        {showDetails && (
          <button onClick={handleSavePreferences}>
            Save Preferences
          </button>
        )}
      </div>
    </div>
  );
}

DSAR (Data Subject Access Request) System

DSAR Workflow

┌─────────────────────────────────────────────────────────────────────────────┐
│                       DSAR PROCESSING WORKFLOW                              │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐                  │
│  │  1. REQUEST │────▶│ 2. VERIFY   │────▶│ 3. SEARCH   │                  │
│  │   RECEIVED  │     │  IDENTITY   │     │    DATA     │                  │
│  └─────────────┘     └─────────────┘     └─────────────┘                  │
│        │                   │                   │                           │
│        │                   │                   │                           │
│  Day 0: Clock      Day 1-3: ID         Day 3-20: Gather                   │
│  starts            verification        data from all                       │
│                                        systems                             │
│                                                                             │
│        │                   │                   │                           │
│        ▼                   ▼                   ▼                           │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐                  │
│  │ 4. REVIEW   │────▶│ 5. PREPARE  │────▶│ 6. DELIVER  │                  │
│  │  & REDACT   │     │  RESPONSE   │     │  RESPONSE   │                  │
│  └─────────────┘     └─────────────┘     └─────────────┘                  │
│        │                   │                   │                           │
│        │                   │                   │                           │
│  Day 20-25:         Day 25-28:          Day 28-30:                        │
│  Review for         Format data,        Secure delivery                   │
│  third-party        generate report     to data subject                   │
│  data, exemptions                                                          │
│                                                                             │
│  ─────────────────────────────────────────────────────────────────────────│
│  TIMELINE: 30 calendar days (extendable by 60 days for complex requests) │
│  ─────────────────────────────────────────────────────────────────────────│
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

DSAR Automation Implementation

// DSAR request types
interface DSARRequest {
  id: string;
  dataSubjectId: string;
  requestType: DSARType;
  receivedAt: Date;
  deadline: Date;
  status: DSARStatus;

  // Identity verification
  identityVerified: boolean;
  verificationMethod?: string;
  verifiedAt?: Date;

  // Processing
  assignedTo?: string;
  notes: string[];

  // Response
  responseData?: DSARResponse;
  deliveredAt?: Date;
}

type DSARType =
  | 'access'        // Article 15 - Right of access
  | 'rectification' // Article 16 - Right to rectification
  | 'erasure'       // Article 17 - Right to erasure
  | 'restriction'   // Article 18 - Right to restriction
  | 'portability'   // Article 20 - Right to data portability
  | 'objection';    // Article 21 - Right to object

type DSARStatus =
  | 'received'
  | 'identity_verification'
  | 'in_progress'
  | 'review'
  | 'response_ready'
  | 'completed'
  | 'rejected';

// DSAR processing service
class DSARService {

  async submitRequest(
    email: string,
    requestType: DSARType,
    details: string
  ): Promise<DSARRequest> {

    // Find or create data subject
    const dataSubject = await this.findOrCreateDataSubject(email);

    const deadline = this.calculateDeadline(new Date());

    const request: DSARRequest = {
      id: generateUUID(),
      dataSubjectId: dataSubject.id,
      requestType,
      receivedAt: new Date(),
      deadline,
      status: 'received',
      identityVerified: false,
      notes: [details]
    };

    await this.store.save(request);

    // Send verification email
    await this.sendVerificationEmail(dataSubject.email, request.id);

    // Notify DPO/privacy team
    await this.notifyPrivacyTeam(request);

    return request;
  }

  async processAccessRequest(requestId: string): Promise<DSARResponse> {
    const request = await this.store.findById(requestId);

    if (!request.identityVerified) {
      throw new Error('Identity not verified');
    }

    // Collect data from all sources
    const dataCollections: DataCollection[] = [];

    // 1. Main database
    dataCollections.push(
      await this.collectFromDatabase(request.dataSubjectId)
    );

    // 2. Analytics systems
    dataCollections.push(
      await this.collectFromAnalytics(request.dataSubjectId)
    );

    // 3. Support tickets
    dataCollections.push(
      await this.collectFromSupport(request.dataSubjectId)
    );

    // 4. Third-party processors
    for (const processor of this.processors) {
      dataCollections.push(
        await processor.collectData(request.dataSubjectId)
      );
    }

    // Compile response
    const response: DSARResponse = {
      requestId,
      generatedAt: new Date(),
      dataSubjectInfo: await this.getDataSubjectInfo(request.dataSubjectId),

      // Article 15(1) requirements
      processingPurposes: this.getProcessingPurposes(),
      dataCategories: this.extractCategories(dataCollections),
      recipients: this.getRecipients(),
      retentionPeriods: this.getRetentionInfo(),
      dataSubjectRights: this.getRightsInfo(),
      sourceOfData: this.getDataSources(dataCollections),
      automatedDecisionMaking: this.getAutomatedDecisions(),

      // Actual data
      data: dataCollections,

      // Third country transfers
      thirdCountryTransfers: this.getTransferInfo()
    };

    return response;
  }

  async processErasureRequest(requestId: string): Promise<void> {
    const request = await this.store.findById(requestId);

    // Check for exemptions
    const exemptions = await this.checkErasureExemptions(
      request.dataSubjectId
    );

    if (exemptions.length > 0) {
      // Partial erasure - document what can't be deleted and why
      request.notes.push(
        `Exemptions found: ${exemptions.join(', ')}`
      );
    }

    // Delete from all systems
    const deletionLog: DeletionRecord[] = [];

    // 1. Main database
    deletionLog.push(
      await this.deleteFromDatabase(request.dataSubjectId, exemptions)
    );

    // 2. Backups (schedule for deletion per retention policy)
    await this.scheduleBackupDeletion(request.dataSubjectId);

    // 3. Third-party processors
    for (const processor of this.processors) {
      deletionLog.push(
        await processor.deleteData(request.dataSubjectId)
      );
    }

    // 4. Analytics (anonymize rather than delete if needed for statistics)
    await this.anonymizeAnalytics(request.dataSubjectId);

    // Document deletion
    request.notes.push(`Deletion completed: ${JSON.stringify(deletionLog)}`);
    request.status = 'completed';

    await this.store.save(request);
  }

  private calculateDeadline(receivedDate: Date): Date {
    // 30 calendar days from receipt
    const deadline = new Date(receivedDate);
    deadline.setDate(deadline.getDate() + 30);
    return deadline;
  }

  private async checkErasureExemptions(
    dataSubjectId: string
  ): Promise<string[]> {
    const exemptions: string[] = [];

    // Article 17(3) exemptions
    // (a) Freedom of expression and information
    // (b) Legal obligation
    if (await this.hasLegalRetentionRequirement(dataSubjectId)) {
      exemptions.push('legal_obligation');
    }

    // (c) Public health
    // (d) Archiving in public interest
    // (e) Legal claims
    if (await this.hasOngoingLegalMatter(dataSubjectId)) {
      exemptions.push('legal_claims');
    }

    return exemptions;
  }
}

Privacy by Design Implementation

Data Minimization Patterns

// Privacy by Design: Data minimization in API responses

interface User {
  id: string;
  email: string;
  passwordHash: string;
  name: string;
  dateOfBirth: Date;
  address: Address;
  phoneNumber: string;
  createdAt: Date;
  lastLogin: Date;
  internalNotes: string;
}

// Different views based on purpose and audience
interface UserPublicProfile {
  id: string;
  name: string;
  // Only what's necessary for public display
}

interface UserSelfView {
  id: string;
  email: string;
  name: string;
  dateOfBirth: Date;
  address: Address;
  phoneNumber: string;
  createdAt: Date;
  lastLogin: Date;
  // User can see their own data (minus internal fields)
}

interface UserAdminView extends User {
  // Admins see everything for legitimate purposes
}

// View transformer with purpose validation
class UserViewTransformer {

  toPublicProfile(user: User): UserPublicProfile {
    return {
      id: user.id,
      name: user.name
    };
  }

  toSelfView(user: User, requestingUserId: string): UserSelfView {
    // Verify the user is requesting their own data
    if (user.id !== requestingUserId) {
      throw new Error('Unauthorized');
    }

    const { passwordHash, internalNotes, ...selfView } = user;
    return selfView;
  }

  toAdminView(user: User, admin: Admin, purpose: string): UserAdminView {
    // Log access for audit trail
    this.auditLog.record({
      accessedBy: admin.id,
      accessedData: user.id,
      purpose,
      timestamp: new Date()
    });

    return user;
  }
}

Pseudonymization Implementation

// Pseudonymization service for GDPR compliance

interface PseudonymizationConfig {
  algorithm: 'sha256' | 'hmac-sha256';
  secret: string; // For reversible pseudonymization
  salt?: string;
}

class PseudonymizationService {
  constructor(private config: PseudonymizationConfig) {}

  // One-way pseudonymization (irreversible)
  pseudonymize(identifier: string): string {
    const hash = crypto.createHash('sha256');
    hash.update(identifier + (this.config.salt || ''));
    return hash.digest('hex');
  }

  // Reversible pseudonymization (when re-identification needed)
  pseudonymizeReversible(identifier: string): string {
    const hmac = crypto.createHmac('sha256', this.config.secret);
    hmac.update(identifier);
    return hmac.digest('hex');
  }

  // Generate consistent pseudonym for same input
  generatePseudonym(identifier: string, context: string): string {
    // Context-specific pseudonyms prevent correlation
    const hash = crypto.createHash('sha256');
    hash.update(`${context}:${identifier}:${this.config.salt}`);
    return `PSEUDO_${hash.digest('hex').substring(0, 16)}`;
  }

  // Pseudonymize dataset for analytics
  pseudonymizeDataset(
    records: Record<string, any>[],
    fieldsToMask: string[]
  ): Record<string, any>[] {
    return records.map(record => {
      const masked = { ...record };

      for (const field of fieldsToMask) {
        if (masked[field]) {
          masked[field] = this.pseudonymize(String(masked[field]));
        }
      }

      return masked;
    });
  }
}

// Usage example: Analytics with pseudonymized data
async function generateAnalyticsReport(): Promise<Report> {
  const pseudoService = new PseudonymizationService(config);

  // Fetch user activity data
  const rawData = await database.query(`
    SELECT user_id, action, timestamp, ip_address
    FROM user_activity
    WHERE timestamp > NOW() - INTERVAL '30 days'
  `);

  // Pseudonymize before analysis
  const pseudonymizedData = pseudoService.pseudonymizeDataset(
    rawData,
    ['user_id', 'ip_address']  // Fields containing personal data
  );

  // Now safe to analyze without identifying individuals
  return analyzeActivityPatterns(pseudonymizedData);
}

Data Protection Impact Assessment (DPIA)

┌─────────────────────────────────────────────────────────────────────────────┐
│                      DPIA PROCESS WORKFLOW                                  │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  STEP 1: SCREENING - Is DPIA Required?                                     │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │ DPIA required if processing is likely to result in HIGH RISK:        │ │
│  │                                                                        │ │
│  │ ☐ Systematic profiling with significant effects                      │ │
│  │ ☐ Large-scale processing of special categories                       │ │
│  │ ☐ Systematic monitoring of public areas                              │ │
│  │ ☐ Automated decision-making with legal effects                       │ │
│  │ ☐ New technologies                                                    │ │
│  │ ☐ Denies data subjects a right/service/contract                     │ │
│  │ ☐ Large-scale profiling                                              │ │
│  │ ☐ Processing biometric/genetic data                                  │ │
│  │ ☐ Cross-border processing                                            │ │
│  │                                                                        │ │
│  │ 2 or more criteria checked = DPIA required                           │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  STEP 2: DESCRIBE THE PROCESSING                                           │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │ • Nature of processing (what operations?)                            │ │
│  │ • Scope (how much data, how many subjects, geographic area?)         │ │
│  │ • Context (relationship with data subjects, expectations)            │ │
│  │ • Purpose (why processing this data?)                                │ │
│  │ • Data flows (collection → storage → use → sharing → deletion)      │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  STEP 3: ASSESS NECESSITY AND PROPORTIONALITY                              │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │ • Is processing necessary for the purpose?                           │ │
│  │ • Could the purpose be achieved with less data?                      │ │
│  │ • What is the lawful basis?                                          │ │
│  │ • How is data quality ensured?                                       │ │
│  │ • What are retention periods?                                        │ │
│  │ • How are data subject rights facilitated?                          │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  STEP 4: IDENTIFY AND ASSESS RISKS                                         │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │                                                                        │ │
│  │  Risk Type          │ Likelihood │ Severity │ Overall Risk           │ │
│  │  ───────────────────┼────────────┼──────────┼─────────────────────── │ │
│  │  Unauthorized access│   Medium   │   High   │   High                 │ │
│  │  Data breach        │    Low     │   High   │   Medium               │ │
│  │  Function creep     │   Medium   │  Medium  │   Medium               │ │
│  │  Re-identification  │    Low     │   High   │   Medium               │ │
│  │  Discrimination     │    Low     │  V.High  │   High                 │ │
│  │                                                                        │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  STEP 5: IDENTIFY MEASURES TO MITIGATE RISKS                               │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │                                                                        │ │
│  │  Risk               │ Mitigation Measure                │ Residual   │ │
│  │  ───────────────────┼───────────────────────────────────┼─────────── │ │
│  │  Unauthorized access│ MFA, encryption, access controls  │   Low      │ │
│  │  Data breach        │ Encryption, monitoring, IR plan   │   Low      │ │
│  │  Function creep     │ Purpose limitation, audits        │   Low      │ │
│  │  Re-identification  │ Pseudonymization, aggregation     │   Low      │ │
│  │  Discrimination     │ Bias testing, human oversight     │   Medium   │ │
│  │                                                                        │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
│  STEP 6: SIGN OFF AND RECORD                                               │
│  ┌───────────────────────────────────────────────────────────────────────┐ │
│  │ • DPO review and advice                                               │ │
│  │ • Management sign-off                                                 │ │
│  │ • Document decision and rationale                                     │ │
│  │ • Publish DPIA (if appropriate)                                       │ │
│  │ • Schedule review (annually or when processing changes)               │ │
│  │ • Consult supervisory authority if high risk remains                 │ │
│  └───────────────────────────────────────────────────────────────────────┘ │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

Breach Notification System

// Data breach management system

interface DataBreach {
  id: string;
  detectedAt: Date;
  reportingDeadline: Date; // 72 hours from detection

  // Breach details
  description: string;
  affectedDataTypes: string[];
  affectedDataSubjectCount: number;
  affectedDataSubjectCategories: string[];

  // Risk assessment
  riskLevel: 'low' | 'medium' | 'high';
  likelyConsequences: string[];

  // Measures taken
  containmentMeasures: string[];
  mitigationMeasures: string[];

  // Notifications
  supervisoryAuthorityNotified: boolean;
  supervisoryAuthorityNotifiedAt?: Date;
  dataSubjectsNotified: boolean;
  dataSubjectsNotifiedAt?: Date;

  // Documentation
  internalReportUrl: string;
  status: 'detected' | 'contained' | 'reported' | 'closed';
}

class BreachNotificationService {

  async reportBreach(breachDetails: Partial<DataBreach>): Promise<DataBreach> {
    const breach: DataBreach = {
      id: generateUUID(),
      detectedAt: new Date(),
      reportingDeadline: this.calculate72HourDeadline(),
      status: 'detected',
      supervisoryAuthorityNotified: false,
      dataSubjectsNotified: false,
      ...breachDetails
    } as DataBreach;

    // Immediately notify incident response team
    await this.notifyIncidentTeam(breach);

    // Assess if supervisory authority notification required
    if (this.requiresAuthorityNotification(breach)) {
      await this.scheduleAuthorityNotification(breach);
    }

    // Assess if data subject notification required
    if (this.requiresDataSubjectNotification(breach)) {
      await this.scheduleDataSubjectNotification(breach);
    }

    await this.store.save(breach);
    return breach;
  }

  private requiresAuthorityNotification(breach: DataBreach): boolean {
    // Article 33: Notify unless "unlikely to result in a risk"
    // Most breaches require notification to be safe
    return breach.riskLevel !== 'low';
  }

  private requiresDataSubjectNotification(breach: DataBreach): boolean {
    // Article 34: Notify if "likely to result in a high risk"
    return breach.riskLevel === 'high';
  }

  async generateAuthorityNotification(breach: DataBreach): Promise<string> {
    // Article 33(3) required content
    return `
      DATA BREACH NOTIFICATION TO SUPERVISORY AUTHORITY

      1. Nature of the breach:
      ${breach.description}

      2. Categories and approximate number of data subjects:
      Categories: ${breach.affectedDataSubjectCategories.join(', ')}
      Approximate number: ${breach.affectedDataSubjectCount}

      3. Categories and approximate number of data records:
      ${breach.affectedDataTypes.join(', ')}

      4. Contact details of DPO:
      ${this.dpoContact}

      5. Likely consequences:
      ${breach.likelyConsequences.join('\n')}

      6. Measures taken/proposed:
      Containment: ${breach.containmentMeasures.join('\n')}
      Mitigation: ${breach.mitigationMeasures.join('\n')}

      Reported within 72 hours: ${
        breach.detectedAt <= breach.reportingDeadline ? 'Yes' : 'No'
      }
    `;
  }

  private calculate72HourDeadline(): Date {
    const deadline = new Date();
    deadline.setHours(deadline.getHours() + 72);
    return deadline;
  }
}

Tools

Need Expert IT & Security Guidance?

Our team is ready to help protect and optimize your business technology infrastructure.