Principal Compliance Officer. GDPR (data mapping, DPIA, consent, erasure, portability, breach 72hr), HIPAA (PHI, BAA, encryption, audit trails), SOC 2 Type II, PCI-DSS, ISO 27001, privacy by design.
Regulatory compliance is not optional. A 30-year veteran understands that non-compliance costs 4-20% of annual global revenue (GDPR), permanent incarceration (HIPAA), or billion-dollar settlements (meta-breaches). This skill is a legal defense mechanism built into your system architecture.
Applies to any organization processing data of EU residents, regardless of where your company is located.
Create a Data Inventory:
| Data Type | Collection Method | Processing Purpose | Retention Period | Data Subject Rights | Processor/Controller |
|---|---|---|---|---|---|
| Registration form |
| Account authentication |
| Indefinite (until account deletion) |
| Access, Erasure, Portability |
| Self (Controller) |
| IP Address | HTTP logs | Security & fraud detection | 90 days | Access, Erasure | Self (Controller) |
| Billing Address | Checkout form | Invoicing, tax compliance | 7 years (tax law) | Access, Portability | Self (Controller), Stripe (Processor) |
| Location (GPS) | Mobile app | Route optimization | 30 days | Access, Erasure | Self (Controller) |
| Biometric (Fingerprint) | WebAuthn | Authentication | Indefinite | Access, Erasure | Self (Controller) |
| Payment Details | Credit card input | Transaction processing | 0 days (tokenized) | N/A | Stripe (PCI-DSS compliant) |
Key Definitions:
You must choose ONE legal basis before processing ANY data:
Consent (Article 6(1)(a)): User explicitly agrees. Must be informed, specific, unambiguous.
Contractual (Article 6(1)(b)): Processing is necessary to deliver a service the user contracted for.
Legal Obligation (Article 6(1)(c)): Law requires the processing.
Vital Interests (Article 6(1)(d)): Processing is necessary to protect someone's life.
Public Task (Article 6(1)(e)): Processing is necessary for a public authority's official function.
Legitimate Interests (Article 6(1)(f)): Your interests outweigh the individual's privacy rights (requires Balancing Test).
Mandatory for high-risk processing (biometric data, large-scale profiling, automated decision-making affecting rights).
# DPIA: Real-time location tracking in delivery app
## 1. Processing Description
- Data: GPS coordinates, speed, geofence entry/exit
- Frequency: Every 10 seconds during delivery
- Duration: 8 hours/day for delivery drivers
- Storage: 90 days, then anonymized
## 2. Necessity & Proportionality
- **Necessity**: Route optimization, customer ETA, theft prevention
- **Alternative**: Collect location only at delivery start/end (less invasive)
- **Proportionality**: Driver consents (contractual necessity), benefits outweigh privacy intrusion
## 3. Risk Assessment
| Risk | Likelihood | Impact | Mitigation |
|------|---|---|---|
| Location data leaked | Medium | High (stalking, theft) | Encryption, access controls, employee training |
| Driver profiled for productivity | High | Medium (surveillance) | De-identification after 90 days |
| Tracking after shift ends | Medium | High (privacy violation) | Automatic location stop at shift end |
## 4. Mitigation Measures
1. Minimize data: Collect location every 30 seconds (not 10).
2. Pseudonymization: Replace driver name with ID in logs.
3. Encryption: AES-256 in transit and at rest.
4. Access control: Only route optimization team can access, not management.
5. Retention: Delete after 90 days automatically.
6. Transparency: Driver sees what's being collected and why.
## 5. Residual Risk Assessment
- **Acceptable?** Yes, with above measures.
# Consent must be explicit, informed, specific, freely given
class ConsentRecord:
def __init__(self, user_id, purpose, version):
self.user_id = user_id
self.purpose = purpose # 'marketing', 'analytics', 'third_party_ads'
self.version = version # Version of consent form (for audit)
self.given_at = datetime.utcnow()
self.ip_address = request.remote_addr # Proof of consent
self.user_agent = request.headers['User-Agent']
self.withdrawn_at = None
def withdraw_consent(user_id, purpose):
consent = db.query('consents', user_id=user_id, purpose=purpose)
consent.withdrawn_at = datetime.utcnow()
# Upon withdrawal, stop processing immediately
if purpose == 'marketing':
email_service.unsubscribe(user_id)
elif purpose == 'analytics':
analytics.delete_user(user_id)
Critical: Pre-checked consent boxes violate GDPR. User must actively click/toggle consent.
User can request all data you hold about them. You must respond within 30 days with:
@app.route('/api/gdpr/download', methods=['GET'])
def download_user_data():
user_id = request.user_id
data = {
'profile': db.get_user(user_id),
'orders': db.get_orders(user_id),
'interactions': db.get_interactions(user_id),
'consent_records': db.get_consents(user_id),
'processing_purposes': ['account management', 'fraud detection']
}
return json_response(data), 200
User can correct inaccurate data. You must update within 30 days.
User can demand deletion under these conditions:
Exceptions (you can refuse):
@app.route('/api/gdpr/erase', methods=['DELETE'])
def erase_user():
user_id = request.user_id
# Check if erasure is permitted
if has_pending_refund(user_id) or is_under_legal_hold(user_id):
return {'error': 'Erasure blocked: pending refund'}, 409
# Full erasure
db.delete_user(user_id) # Soft delete: mark as deleted, don't remove
# Rationale: hard delete breaks referential integrity in orders, transactions
storage.delete_user_files(user_id)
analytics.delete_user_profile(user_id)
# Notify 3rd party processors
stripe.delete_customer(user_id)
email_service.unsubscribe(user_id)
log_audit_event('erasure', user_id, datetime.utcnow())
return {'status': 'erased'}, 200
Soft Delete Approach (Recommended):
-- Keep record but mark as deleted
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP;
-- Never query deleted users
SELECT * FROM users WHERE deleted_at IS NULL;
-- After 7-year retention, hard delete
DELETE FROM users WHERE deleted_at < NOW() - INTERVAL '7 years';
User can request you freeze their data (don't use it, but keep it).
def restrict_user_processing(user_id):
user.processing_restricted = True
# Stop all automated decision-making, analytics, etc.
# But maintain data for potential future processing.
User can request their data in a portable format (JSON, CSV) to move to a competitor.
@app.route('/api/gdpr/export', methods=['GET'])
def export_user_data():
user_id = request.user_id
data = db.get_all_user_data(user_id)
return send_csv(data, filename=f'user_{user_id}_export.csv')
User can object to processing based on legitimate interests.
Users have the right not to be subjected to automated decisions affecting their rights (denying a loan, firing, etc.) unless:
If automated decision-making is used, provide:
Article 33: If a breach of personal data occurs, you must notify the Data Protection Authority (DPA) within 72 hours.
def handle_data_breach(data_type, affected_users_count, breach_date):
"""
Notify within 72 hours of discovering breach (not when it occurred).
"""
notification = {
'description': f'{affected_users_count} users\' {data_type} exposed',
'date_of_breach': breach_date,
'date_of_discovery': datetime.utcnow(),
'likely_consequences': 'High risk of identity theft',
'measures_taken': 'Accounts locked, password reset forced, notification email sent',
'controller_contact': '[email protected]'
}
# Notify DPA immediately
dpa = get_dpa_for_jurisdiction(user_jurisdiction) # E.g., CNIL for France
submit_breach_notification(dpa, notification)
# Notify affected users (if high risk)
for user_id in affected_users:
send_email(user_id, 'Your data was exposed in a breach. Reset your password.')
Exception: Notify DPA UNLESS the breach is unlikely to cause harm (e.g., only internal employee emails, data already encrypted).
Article 28: Every processor you use (AWS, Stripe, email service) must sign a DPA.
# Data Processing Agreement (Stripe)
## 1. Scope
Stripe processes payment card data and transaction details on behalf of [Your Company].
## 2. Processing Details
- Data: Card tokens (masked), transaction amounts, IP addresses
- Purpose: Payment processing and fraud detection
- Duration: For the lifetime of the customer relationship
- Processor Location: USA, EU (data centers depend on region)
## 3. Security Measures
- Encryption: AES-256 at rest, TLS 1.2+ in transit
- Access Control: Limited staff, 2FA required
- Audits: SOC 2 Type II, PCI-DSS Level 1
- Sub-processors: [List of third parties Stripe uses]
## 4. Data Subject Rights
- Stripe must assist in fulfilling subject access requests
- Stripe must delete data upon instruction (within agreed timeframe)
## 5. Liability
- Stripe is liable for damages if it violates GDPR.
## 6. Term & Termination
- On termination, Stripe deletes all personal data unless law requires retention.
Applies to Covered Entities (healthcare providers, health plans, healthcare clearinghouses) and Business Associates (anyone processing Protected Health Information (PHI)).
Any health information (explicit or implicit) that can identify an individual:
If you process PHI, sign a BAA with the Covered Entity.
# Business Associate Agreement (EHR Vendor)
## 1. Permitted Uses
- Vendor processes patient medical records on behalf of [Hospital].
- Vendor may use PHI only for: Data storage, backup, maintenance.
- Vendor must NOT use PHI for marketing, secondary analysis, or sharing with third parties.
## 2. Security Requirements
- Minimum 256-bit encryption at rest.
- TLS 1.2+ for transmission.
- Multi-factor authentication for staff access.
- Annual security risk analysis.
- Incident response plan (notify within 24 hours).
## 3. Breach Notification
- Vendor notifies Hospital within 24 hours of discovering a breach.
- Hospital notifies affected patients within 60 days.
## 4. Subcontractors
- Vendor must require all subcontractors to sign BAA or DPA.
- Vendor remains liable for subcontractor violations.
## 5. Audit Rights
- Hospital reserves the right to audit vendor's security controls.
## 6. Termination
- Upon contract end, all PHI is securely destroyed or returned to Hospital.
| Data Type | Encryption Standard | Key Length | Protocol |
|---|---|---|---|
| PHI at Rest | AES | 256-bit | CBC or CTR mode |
| PHI in Transit | TLS | 256-bit | TLS 1.2+ only |
| Encryption Keys | FIPS 140-2 Level 2 | 256-bit | Hardware Security Module (HSM) |
| Backups | AES | 256-bit | Separate key from production |
# HIPAA requires role-based access with minimum necessary principle
ROLES = {
'doctor': ['read:own_patients', 'write:own_patients', 'order:tests'],
'nurse': ['read:assigned_patients', 'write:vitals_only'],
'billing': ['read:billing_only'], # No access to diagnoses
'admin': ['read:all', 'write:all'] # Rarely needed, logged heavily
}
def can_access(user_id, action, patient_id):
user = db.get_user(user_id)
# Minimum necessary check: Is the user actually treating this patient?
if action.startswith('read:') and not is_treating(user_id, patient_id):
log_access_denial(user_id, action, patient_id)
return False
# HIPAA Audit Log
log_hipaa_access(
user_id=user_id,
action=action,
patient_id=patient_id,
ip_address=request.remote_addr,
timestamp=datetime.utcnow()
)
return action in ROLES.get(user['role'], [])
HIPAA requires comprehensive audit logging of all PHI access.
# Schema for HIPAA audit logs
class AuditLog:
id: int
user_id: str
action: str # 'read', 'write', 'delete'
resource_type: str # 'patient_record', 'lab_result'
resource_id: str # patient ID, lab ID
timestamp: datetime
ip_address: str
success: bool
failure_reason: str (optional)
change_details: dict (optional) # If write/delete, what changed
# Audit logs must be:
# 1. Immutable: Write-once, read-many (WORM) storage
# 2. Retained: Minimum 6 years
# 3. Tamper-evident: Cryptographic hashing to detect changes
# 4. Reviewed: Quarterly for unauthorized access patterns
Notify affected individuals within 60 days (faster than GDPR's 72 hours to authority).
def notify_breach(affected_count, data_type, breach_date):
# 1. Notify individuals
for patient_id in affected_list:
send_breach_notification_letter(patient_id)
# 2. Notify media (if 500+ individuals in same jurisdiction)
if affected_count >= 500:
notify_media()
# 3. Notify HHS (Department of Health & Human Services)
notify_hhs_breach_portal()
# 4. Document in breach log
log_breach_for_audit(affected_count, data_type, breach_date)
Not a regulation, but a Trust Service certification. Demonstrates to customers that you have controls for:
Audit: Annual assessment by independent auditor covering 6-12 month period.
# SOC 2 Type II Control Example: Encryption of Data at Rest
## Control Objective
All data at rest must be encrypted with AES-256 to prevent unauthorized disclosure.
## Control Activity
1. Database encryption enabled (AWS RDS encryption, Postgres pgcrypto).
2. Backup encryption enabled.
3. Key management: Keys rotated quarterly via AWS KMS.
4. Access restricted: Only application service account can decrypt.
## Testing Performed
- Auditor verified encryption settings in AWS console.
- Auditor verified encryption keys are not publicly exposed.
- Auditor tested that unencrypted data is not accessible.
- Auditor reviewed key rotation logs (3 rotations in audit period).
## Result
✓ **Operating Effectively**: Control operating as designed throughout audit period.
Applies if you handle, transmit, or store credit card data.
Instead of storing card numbers, store tokens:
# User enters card details on Stripe's hosted form
# Stripe returns a token: tok_visa_4242
# Your database stores: token, not card number
order.payment_token = 'tok_visa_4242'
db.save(order)
# Charge later
charge = stripe.Charge.create(
amount=1000,
currency='usd',
source='tok_visa_4242' # Use token, not card number
)
# Your servers never see card number = SAQ-A compliance
Principle: Build privacy into your system from day 1, not as an afterthought.
Data Minimization: Collect only what's necessary.
Pseudonymization: Replace identifiable data with IDs.
Purpose Limitation: Data collected for one purpose cannot be used for another (without new consent).
Storage Limitation: Delete data when no longer needed.
Integrity & Confidentiality: Encrypt sensitive data, restrict access, maintain audit trails.
Accountability: Document all processing, maintain audit logs, demonstrate GDPR compliance.
# Privacy by Design Example: User Registration
# 1. Minimal collection (data minimization)
class UserSignup:
email: str # Necessary for authentication
password: str # Necessary for authentication
# No: phone, address, gender, etc. unless required
# 2. Encryption at rest (confidentiality)
password_hash = argon2.hash(password)
email_encrypted = AES.encrypt(email, key=encryption_key)
# 3. Retention policy (storage limitation)
deletion_scheduled = now() + timedelta(days=365 * 7) # 7-year legal hold
# 4. Audit trail (accountability)
log_account_creation(
user_id=new_user.id,
timestamp=now(),
ip_address=request.remote_addr,
consent_version='v2.0'
)
# 5. Purpose limitation
# Consent choices:
# - "Essential" (account management) - mandatory
# - "Marketing" (emails, newsletters) - optional
# - "Analytics" (usage patterns) - optional
# 🔒 Regulatory Compliance & Privacy Architecture Review
## I. GDPR Compliance Assessment
- [ ] Data inventory created (all personal data types catalogued)
- [ ] Legal basis identified for each processing type
- [ ] DPIA completed for high-risk processing
- [ ] Consent mechanism implemented (explicit opt-in)
- [ ] Data Subject Rights workflows implemented (access, erasure, portability)
- [ ] Data Processing Agreements signed with all processors
- [ ] Breach notification process documented (72-hour DPA notification)
### Critical Gaps
1. [Gap 1]: Consent is pre-checked (violates GDPR Article 7)
- **Fix**: Implement unchecked-by-default consent boxes
2. [Gap 2]: Marketing emails sent without opt-in consent
- **Fix**: Implement double-opt-in (confirmation email required)
## II. HIPAA Compliance (if applicable)
- [ ] BAA signed with Covered Entity
- [ ] PHI encryption: AES-256 at rest, TLS 1.2+ in transit
- [ ] Access controls enforced (role-based, minimum necessary)
- [ ] Audit trails captured for all PHI access
- [ ] Breach notification plan (60-day patient notification)
## III. PCI-DSS Compliance
- **SAQ Type**: [A / A-EP / D]
- [ ] Tokenization implemented (card data never stored)
- [ ] Firewall enforced
- [ ] Encryption for data in transit and at rest
- [ ] Access logging (1-year retention)
## IV. Privacy by Design Assessment
- Data minimization: ✓ Only essential data collected
- Pseudonymization: ✓ User IDs used in analytics
- Purpose limitation: ✓ Consent per use case
- Retention policies: ✓ Auto-deletion after [X years]
## V. Recommendations
1. [Implement GDPR Right to Erasure workflow]
2. [Upgrade encryption to AES-256]
3. [Schedule annual SOC 2 Type II audit]
## VI. Skill Chaining
- Chain to `security-audit` for comprehensive threat assessment.
- Chain to `authentication-system` for PII handling in auth tokens.