privacy-reviewer

Installation
SKILL.md

Privacy Compliance Review

Review PII identification, encryption, data deletion, and regulatory compliance.

PII Identification Checklist

Category Examples Treatment
Direct identifiers Name, email, phone, SSN Encrypt at rest
Indirect identifiers IP address, device ID Hash or encrypt
Location data GPS, address, zip code Encrypt, retention limits
Financial Card numbers, bank accounts PCI compliance required
Health Medical records, conditions HIPAA compliance required
Behavioral Browsing history, preferences Consent required

Encryption for Sensitive Fields

# Rails 7+ built-in encryption
class User < ApplicationRecord
  encrypts :ssn
  encrypts :date_of_birth
  encrypts :medical_notes, deterministic: false  # Non-searchable
end

# Configuration in credentials
# active_record_encryption:
#   primary_key: <32-byte key>
#   deterministic_key: <32-byte key>
#   key_derivation_salt: <salt>

Right to Deletion (GDPR Article 17)

# PROBLEM: Hard delete loses audit trail
user.destroy

# SOLUTION: Anonymization with audit preservation
def anonymize!
  transaction do
    update!(
      email: "deleted_#{id}@anonymized.local",
      name: "Deleted User",
      phone: nil,
      address: nil,
      deleted_at: Time.current
    )
    # Keep orders for accounting, anonymize PII
    orders.update_all(
      customer_name: "Anonymized",
      shipping_address: nil
    )
  end
end

Data Retention

# Automated cleanup job
class PiiRetentionJob < ApplicationJob
  def perform
    # Delete inactive users after retention period
    User.where("last_activity_at < ?", 3.years.ago)
        .find_each(&:anonymize!)

    # Purge old logs
    AuditLog.where("created_at < ?", 7.years.ago).delete_all
  end
end

Audit Trails

# Track PII access
class PiiAccessLog < ApplicationRecord
  belongs_to :user           # Whose data was accessed
  belongs_to :accessed_by, class_name: 'User'

  # Log: what, when, why, who
  # user_id, accessed_by_id, field_accessed, purpose, created_at
end

# In model
def ssn
  PiiAccessLog.create!(user: self, accessed_by: Current.user, field_accessed: 'ssn')
  super
end

Consent Management

class UserConsent < ApplicationRecord
  belongs_to :user

  # Track: what consented, when, version, withdrawal
  # consent_type, granted_at, policy_version, withdrawn_at
end

# Check before processing
def can_send_marketing?(user)
  user.consents.active.exists?(consent_type: 'marketing')
end

Data Export (GDPR Article 20)

def export_personal_data
  {
    profile: attributes.slice('name', 'email', 'phone'),
    orders: orders.map(&:export_data),
    activity: activity_logs.map(&:export_data),
    exported_at: Time.current.iso8601
  }.to_json
end

Review Checklist

  • All PII fields identified and documented?
  • Sensitive fields encrypted at rest?
  • Anonymization method exists for deletion requests?
  • Data retention policies implemented?
  • PII access logged for audit?
  • Consent tracked before data processing?
  • Data export available for portability requests?

Output Format

## Privacy Review: [PASS/WARN/FAIL]

### Unencrypted PII
- [model.field]: [PII type, should be encrypted]

### Deletion Compliance
- [issue]: [hard deletes without anonymization option]

### Missing Audit Trails
- [model]: [PII accessed without logging]

### Consent Gaps
- [feature]: [processes data without consent check]

### Recommendations
1. [Prioritized fixes]
Weekly Installs
9
GitHub Stars
37
First Seen
Mar 24, 2026