fraiseql-confiture 0.3.7__cp311-cp311-macosx_11_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- confiture/__init__.py +48 -0
- confiture/_core.cpython-311-darwin.so +0 -0
- confiture/cli/__init__.py +0 -0
- confiture/cli/dry_run.py +116 -0
- confiture/cli/lint_formatter.py +193 -0
- confiture/cli/main.py +1893 -0
- confiture/config/__init__.py +0 -0
- confiture/config/environment.py +263 -0
- confiture/core/__init__.py +51 -0
- confiture/core/anonymization/__init__.py +0 -0
- confiture/core/anonymization/audit.py +485 -0
- confiture/core/anonymization/benchmarking.py +372 -0
- confiture/core/anonymization/breach_notification.py +652 -0
- confiture/core/anonymization/compliance.py +617 -0
- confiture/core/anonymization/composer.py +298 -0
- confiture/core/anonymization/data_subject_rights.py +669 -0
- confiture/core/anonymization/factory.py +319 -0
- confiture/core/anonymization/governance.py +737 -0
- confiture/core/anonymization/performance.py +1092 -0
- confiture/core/anonymization/profile.py +284 -0
- confiture/core/anonymization/registry.py +195 -0
- confiture/core/anonymization/security/kms_manager.py +547 -0
- confiture/core/anonymization/security/lineage.py +888 -0
- confiture/core/anonymization/security/token_store.py +686 -0
- confiture/core/anonymization/strategies/__init__.py +41 -0
- confiture/core/anonymization/strategies/address.py +359 -0
- confiture/core/anonymization/strategies/credit_card.py +374 -0
- confiture/core/anonymization/strategies/custom.py +161 -0
- confiture/core/anonymization/strategies/date.py +218 -0
- confiture/core/anonymization/strategies/differential_privacy.py +398 -0
- confiture/core/anonymization/strategies/email.py +141 -0
- confiture/core/anonymization/strategies/format_preserving_encryption.py +310 -0
- confiture/core/anonymization/strategies/hash.py +150 -0
- confiture/core/anonymization/strategies/ip_address.py +235 -0
- confiture/core/anonymization/strategies/masking_retention.py +252 -0
- confiture/core/anonymization/strategies/name.py +298 -0
- confiture/core/anonymization/strategies/phone.py +119 -0
- confiture/core/anonymization/strategies/preserve.py +85 -0
- confiture/core/anonymization/strategies/redact.py +101 -0
- confiture/core/anonymization/strategies/salted_hashing.py +322 -0
- confiture/core/anonymization/strategies/text_redaction.py +183 -0
- confiture/core/anonymization/strategies/tokenization.py +334 -0
- confiture/core/anonymization/strategy.py +241 -0
- confiture/core/anonymization/syncer_audit.py +357 -0
- confiture/core/blue_green.py +683 -0
- confiture/core/builder.py +500 -0
- confiture/core/checksum.py +358 -0
- confiture/core/connection.py +184 -0
- confiture/core/differ.py +522 -0
- confiture/core/drift.py +564 -0
- confiture/core/dry_run.py +182 -0
- confiture/core/health.py +313 -0
- confiture/core/hooks/__init__.py +87 -0
- confiture/core/hooks/base.py +232 -0
- confiture/core/hooks/context.py +146 -0
- confiture/core/hooks/execution_strategies.py +57 -0
- confiture/core/hooks/observability.py +220 -0
- confiture/core/hooks/phases.py +53 -0
- confiture/core/hooks/registry.py +295 -0
- confiture/core/large_tables.py +775 -0
- confiture/core/linting/__init__.py +70 -0
- confiture/core/linting/composer.py +192 -0
- confiture/core/linting/libraries/__init__.py +17 -0
- confiture/core/linting/libraries/gdpr.py +168 -0
- confiture/core/linting/libraries/general.py +184 -0
- confiture/core/linting/libraries/hipaa.py +144 -0
- confiture/core/linting/libraries/pci_dss.py +104 -0
- confiture/core/linting/libraries/sox.py +120 -0
- confiture/core/linting/schema_linter.py +491 -0
- confiture/core/linting/versioning.py +151 -0
- confiture/core/locking.py +389 -0
- confiture/core/migration_generator.py +298 -0
- confiture/core/migrator.py +882 -0
- confiture/core/observability/__init__.py +44 -0
- confiture/core/observability/audit.py +323 -0
- confiture/core/observability/logging.py +187 -0
- confiture/core/observability/metrics.py +174 -0
- confiture/core/observability/tracing.py +192 -0
- confiture/core/pg_version.py +418 -0
- confiture/core/pool.py +406 -0
- confiture/core/risk/__init__.py +39 -0
- confiture/core/risk/predictor.py +188 -0
- confiture/core/risk/scoring.py +248 -0
- confiture/core/rollback_generator.py +388 -0
- confiture/core/schema_analyzer.py +769 -0
- confiture/core/schema_to_schema.py +590 -0
- confiture/core/security/__init__.py +32 -0
- confiture/core/security/logging.py +201 -0
- confiture/core/security/validation.py +416 -0
- confiture/core/signals.py +371 -0
- confiture/core/syncer.py +540 -0
- confiture/exceptions.py +192 -0
- confiture/integrations/__init__.py +0 -0
- confiture/models/__init__.py +24 -0
- confiture/models/lint.py +193 -0
- confiture/models/migration.py +265 -0
- confiture/models/schema.py +203 -0
- confiture/models/sql_file_migration.py +225 -0
- confiture/scenarios/__init__.py +36 -0
- confiture/scenarios/compliance.py +586 -0
- confiture/scenarios/ecommerce.py +199 -0
- confiture/scenarios/financial.py +253 -0
- confiture/scenarios/healthcare.py +315 -0
- confiture/scenarios/multi_tenant.py +340 -0
- confiture/scenarios/saas.py +295 -0
- confiture/testing/FRAMEWORK_API.md +722 -0
- confiture/testing/__init__.py +100 -0
- confiture/testing/fixtures/__init__.py +11 -0
- confiture/testing/fixtures/data_validator.py +229 -0
- confiture/testing/fixtures/migration_runner.py +167 -0
- confiture/testing/fixtures/schema_snapshotter.py +352 -0
- confiture/testing/frameworks/__init__.py +10 -0
- confiture/testing/frameworks/mutation.py +587 -0
- confiture/testing/frameworks/performance.py +479 -0
- confiture/testing/loader.py +225 -0
- confiture/testing/pytest/__init__.py +38 -0
- confiture/testing/pytest_plugin.py +190 -0
- confiture/testing/sandbox.py +304 -0
- confiture/testing/utils/__init__.py +0 -0
- fraiseql_confiture-0.3.7.dist-info/METADATA +438 -0
- fraiseql_confiture-0.3.7.dist-info/RECORD +124 -0
- fraiseql_confiture-0.3.7.dist-info/WHEEL +4 -0
- fraiseql_confiture-0.3.7.dist-info/entry_points.txt +4 -0
- fraiseql_confiture-0.3.7.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
"""Data protection and privacy compliance standards.
|
|
2
|
+
|
|
3
|
+
Implements anonymization profiles and verification rules for major global
|
|
4
|
+
data protection regulations:
|
|
5
|
+
|
|
6
|
+
- GDPR (EU/EEA): General Data Protection Regulation
|
|
7
|
+
- CCPA (USA/California): California Consumer Privacy Act
|
|
8
|
+
- PIPEDA (Canada): Personal Information Protection and Electronic Documents Act
|
|
9
|
+
- LGPD (Brazil): Lei Geral de Proteção de Dados
|
|
10
|
+
- PIPL (China): Personal Information Protection Law
|
|
11
|
+
- Privacy Act (Australia): Privacy Act 1988
|
|
12
|
+
- POPIA (South Africa): Protection of Personal Information Act
|
|
13
|
+
|
|
14
|
+
Each regulation defines:
|
|
15
|
+
- Personal data categories requiring protection
|
|
16
|
+
- Anonymization thresholds
|
|
17
|
+
- Verification requirements
|
|
18
|
+
- Consent and opt-out mechanisms
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from enum import Enum
|
|
23
|
+
from typing import Any
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class RegulationType(Enum):
|
|
27
|
+
"""Enumeration of major data protection regulations."""
|
|
28
|
+
|
|
29
|
+
GDPR = "gdpr" # EU/EEA
|
|
30
|
+
CCPA = "ccpa" # California, USA
|
|
31
|
+
PIPEDA = "pipeda" # Canada
|
|
32
|
+
LGPD = "lgpd" # Brazil
|
|
33
|
+
PIPL = "pipl" # China
|
|
34
|
+
PRIVACY_ACT = "privacy_act" # Australia
|
|
35
|
+
POPIA = "popia" # South Africa
|
|
36
|
+
GENERIC = "generic" # Generic PII protection
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class PersonalDataCategory:
|
|
41
|
+
"""Definition of a personal data category under regulations."""
|
|
42
|
+
|
|
43
|
+
name: str
|
|
44
|
+
description: str
|
|
45
|
+
regulations: list[RegulationType]
|
|
46
|
+
requires_anonymization: bool
|
|
47
|
+
requires_consent: bool
|
|
48
|
+
retention_period_days: int | None = None
|
|
49
|
+
examples: list[str] | None = None
|
|
50
|
+
|
|
51
|
+
def applies_to(self, regulation: RegulationType) -> bool:
|
|
52
|
+
"""Check if this category applies to a regulation."""
|
|
53
|
+
return regulation in self.regulations
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class PersonalDataCategories:
|
|
57
|
+
"""Standard personal data categories across regulations."""
|
|
58
|
+
|
|
59
|
+
# Identifiers
|
|
60
|
+
DIRECT_IDENTIFIERS = PersonalDataCategory(
|
|
61
|
+
name="Direct Identifiers",
|
|
62
|
+
description="Information directly identifying a person",
|
|
63
|
+
regulations=[
|
|
64
|
+
RegulationType.GDPR,
|
|
65
|
+
RegulationType.CCPA,
|
|
66
|
+
RegulationType.PIPEDA,
|
|
67
|
+
RegulationType.LGPD,
|
|
68
|
+
RegulationType.PIPL,
|
|
69
|
+
RegulationType.PRIVACY_ACT,
|
|
70
|
+
RegulationType.POPIA,
|
|
71
|
+
],
|
|
72
|
+
requires_anonymization=True,
|
|
73
|
+
requires_consent=True,
|
|
74
|
+
examples=["name", "email", "phone", "passport_number"],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
QUASI_IDENTIFIERS = PersonalDataCategory(
|
|
78
|
+
name="Quasi-Identifiers",
|
|
79
|
+
description="Information that could identify person when combined",
|
|
80
|
+
regulations=[
|
|
81
|
+
RegulationType.GDPR,
|
|
82
|
+
RegulationType.CCPA,
|
|
83
|
+
RegulationType.PIPEDA,
|
|
84
|
+
RegulationType.LGPD,
|
|
85
|
+
RegulationType.PIPL,
|
|
86
|
+
RegulationType.PRIVACY_ACT,
|
|
87
|
+
RegulationType.POPIA,
|
|
88
|
+
],
|
|
89
|
+
requires_anonymization=True,
|
|
90
|
+
requires_consent=False,
|
|
91
|
+
examples=["age", "zip_code", "employment_date", "salary_range"],
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# Health data
|
|
95
|
+
HEALTH_DATA = PersonalDataCategory(
|
|
96
|
+
name="Health Data",
|
|
97
|
+
description="Information about physical or mental health",
|
|
98
|
+
regulations=[
|
|
99
|
+
RegulationType.GDPR,
|
|
100
|
+
RegulationType.CCPA,
|
|
101
|
+
RegulationType.PIPEDA,
|
|
102
|
+
RegulationType.LGPD,
|
|
103
|
+
RegulationType.PIPL,
|
|
104
|
+
RegulationType.PRIVACY_ACT,
|
|
105
|
+
RegulationType.POPIA,
|
|
106
|
+
],
|
|
107
|
+
requires_anonymization=True,
|
|
108
|
+
requires_consent=True,
|
|
109
|
+
retention_period_days=2555, # 7 years typical
|
|
110
|
+
examples=["diagnosis", "medication", "medical_history", "genetic_data"],
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Genetic data (special category under GDPR)
|
|
114
|
+
GENETIC_DATA = PersonalDataCategory(
|
|
115
|
+
name="Genetic Data",
|
|
116
|
+
description="Data revealing genetic characteristics",
|
|
117
|
+
regulations=[
|
|
118
|
+
RegulationType.GDPR,
|
|
119
|
+
RegulationType.CCPA,
|
|
120
|
+
RegulationType.PIPEDA,
|
|
121
|
+
RegulationType.LGPD,
|
|
122
|
+
RegulationType.PIPL,
|
|
123
|
+
RegulationType.POPIA,
|
|
124
|
+
],
|
|
125
|
+
requires_anonymization=True,
|
|
126
|
+
requires_consent=True,
|
|
127
|
+
examples=["dna_profile", "ancestry_data", "genetic_test_results"],
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Biometric data
|
|
131
|
+
BIOMETRIC_DATA = PersonalDataCategory(
|
|
132
|
+
name="Biometric Data",
|
|
133
|
+
description="Unique biological/behavioral characteristics",
|
|
134
|
+
regulations=[
|
|
135
|
+
RegulationType.GDPR,
|
|
136
|
+
RegulationType.CCPA,
|
|
137
|
+
RegulationType.PIPEDA,
|
|
138
|
+
RegulationType.LGPD,
|
|
139
|
+
RegulationType.PIPL,
|
|
140
|
+
RegulationType.PRIVACY_ACT,
|
|
141
|
+
RegulationType.POPIA,
|
|
142
|
+
],
|
|
143
|
+
requires_anonymization=True,
|
|
144
|
+
requires_consent=True,
|
|
145
|
+
examples=["fingerprint", "facial_recognition", "iris_scan", "voice_print"],
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Financial data
|
|
149
|
+
FINANCIAL_DATA = PersonalDataCategory(
|
|
150
|
+
name="Financial Data",
|
|
151
|
+
description="Information about financial status and accounts",
|
|
152
|
+
regulations=[
|
|
153
|
+
RegulationType.GDPR,
|
|
154
|
+
RegulationType.CCPA,
|
|
155
|
+
RegulationType.PIPEDA,
|
|
156
|
+
RegulationType.LGPD,
|
|
157
|
+
RegulationType.PIPL,
|
|
158
|
+
RegulationType.PRIVACY_ACT,
|
|
159
|
+
RegulationType.POPIA,
|
|
160
|
+
],
|
|
161
|
+
requires_anonymization=True,
|
|
162
|
+
requires_consent=True,
|
|
163
|
+
retention_period_days=2555, # 7 years for compliance
|
|
164
|
+
examples=["bank_account", "credit_card", "salary", "transaction_history"],
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# Location data
|
|
168
|
+
LOCATION_DATA = PersonalDataCategory(
|
|
169
|
+
name="Location Data",
|
|
170
|
+
description="Information about physical location or movements",
|
|
171
|
+
regulations=[
|
|
172
|
+
RegulationType.GDPR,
|
|
173
|
+
RegulationType.CCPA,
|
|
174
|
+
RegulationType.PIPEDA,
|
|
175
|
+
RegulationType.LGPD,
|
|
176
|
+
RegulationType.PIPL,
|
|
177
|
+
RegulationType.PRIVACY_ACT,
|
|
178
|
+
RegulationType.POPIA,
|
|
179
|
+
],
|
|
180
|
+
requires_anonymization=True,
|
|
181
|
+
requires_consent=True,
|
|
182
|
+
examples=["ip_address", "gps_coordinates", "device_location", "travel_history"],
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
# Communication data
|
|
186
|
+
COMMUNICATION_DATA = PersonalDataCategory(
|
|
187
|
+
name="Communication Data",
|
|
188
|
+
description="Records of communications and interactions",
|
|
189
|
+
regulations=[
|
|
190
|
+
RegulationType.GDPR,
|
|
191
|
+
RegulationType.CCPA,
|
|
192
|
+
RegulationType.PIPEDA,
|
|
193
|
+
RegulationType.LGPD,
|
|
194
|
+
RegulationType.PIPL,
|
|
195
|
+
RegulationType.PRIVACY_ACT,
|
|
196
|
+
RegulationType.POPIA,
|
|
197
|
+
],
|
|
198
|
+
requires_anonymization=True,
|
|
199
|
+
requires_consent=False,
|
|
200
|
+
retention_period_days=365,
|
|
201
|
+
examples=["email_content", "call_logs", "message_history", "browsing_history"],
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Employment data
|
|
205
|
+
EMPLOYMENT_DATA = PersonalDataCategory(
|
|
206
|
+
name="Employment Data",
|
|
207
|
+
description="Information about employment and professional activities",
|
|
208
|
+
regulations=[
|
|
209
|
+
RegulationType.GDPR,
|
|
210
|
+
RegulationType.CCPA,
|
|
211
|
+
RegulationType.PIPEDA,
|
|
212
|
+
RegulationType.LGPD,
|
|
213
|
+
RegulationType.PIPL,
|
|
214
|
+
RegulationType.PRIVACY_ACT,
|
|
215
|
+
RegulationType.POPIA,
|
|
216
|
+
],
|
|
217
|
+
requires_anonymization=True,
|
|
218
|
+
requires_consent=False,
|
|
219
|
+
examples=["employer_name", "job_title", "employment_dates", "salary"],
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# Education data
|
|
223
|
+
EDUCATION_DATA = PersonalDataCategory(
|
|
224
|
+
name="Education Data",
|
|
225
|
+
description="Information about education and training",
|
|
226
|
+
regulations=[
|
|
227
|
+
RegulationType.GDPR,
|
|
228
|
+
RegulationType.CCPA,
|
|
229
|
+
RegulationType.PIPEDA,
|
|
230
|
+
RegulationType.LGPD,
|
|
231
|
+
RegulationType.PIPL,
|
|
232
|
+
RegulationType.PRIVACY_ACT,
|
|
233
|
+
RegulationType.POPIA,
|
|
234
|
+
],
|
|
235
|
+
requires_anonymization=True,
|
|
236
|
+
requires_consent=False,
|
|
237
|
+
retention_period_days=3650, # 10 years typical
|
|
238
|
+
examples=["school_name", "grades", "certificates", "degree"],
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
# Racial/ethnic data (special under GDPR, regulated elsewhere)
|
|
242
|
+
RACIAL_ETHNIC_DATA = PersonalDataCategory(
|
|
243
|
+
name="Racial or Ethnic Origin",
|
|
244
|
+
description="Data about racial or ethnic origin",
|
|
245
|
+
regulations=[
|
|
246
|
+
RegulationType.GDPR,
|
|
247
|
+
RegulationType.PIPEDA,
|
|
248
|
+
RegulationType.LGPD,
|
|
249
|
+
RegulationType.POPIA,
|
|
250
|
+
],
|
|
251
|
+
requires_anonymization=True,
|
|
252
|
+
requires_consent=True,
|
|
253
|
+
examples=["ethnicity", "race", "ancestry"],
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
# Political affiliation (special under GDPR)
|
|
257
|
+
POLITICAL_DATA = PersonalDataCategory(
|
|
258
|
+
name="Political Affiliation",
|
|
259
|
+
description="Data about political opinions or affiliations",
|
|
260
|
+
regulations=[
|
|
261
|
+
RegulationType.GDPR,
|
|
262
|
+
RegulationType.LGPD,
|
|
263
|
+
RegulationType.POPIA,
|
|
264
|
+
],
|
|
265
|
+
requires_anonymization=True,
|
|
266
|
+
requires_consent=True,
|
|
267
|
+
examples=["party_affiliation", "voting_record", "political_donation"],
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Religious/philosophical data (special under GDPR)
|
|
271
|
+
RELIGIOUS_DATA = PersonalDataCategory(
|
|
272
|
+
name="Religious or Philosophical Beliefs",
|
|
273
|
+
description="Data about religious or philosophical beliefs",
|
|
274
|
+
regulations=[
|
|
275
|
+
RegulationType.GDPR,
|
|
276
|
+
RegulationType.LGPD,
|
|
277
|
+
RegulationType.POPIA,
|
|
278
|
+
],
|
|
279
|
+
requires_anonymization=True,
|
|
280
|
+
requires_consent=True,
|
|
281
|
+
examples=["religion", "belief_system", "church_affiliation"],
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
# Trade union membership (special under GDPR)
|
|
285
|
+
UNION_DATA = PersonalDataCategory(
|
|
286
|
+
name="Trade Union Membership",
|
|
287
|
+
description="Data about trade union or professional association membership",
|
|
288
|
+
regulations=[
|
|
289
|
+
RegulationType.GDPR,
|
|
290
|
+
RegulationType.LGPD,
|
|
291
|
+
],
|
|
292
|
+
requires_anonymization=True,
|
|
293
|
+
requires_consent=True,
|
|
294
|
+
examples=["union_membership", "professional_association"],
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Children's data (special handling)
|
|
298
|
+
CHILDREN_DATA = PersonalDataCategory(
|
|
299
|
+
name="Children's Data",
|
|
300
|
+
description="Data about children (under 13-16 depending on regulation)",
|
|
301
|
+
regulations=[
|
|
302
|
+
RegulationType.GDPR,
|
|
303
|
+
RegulationType.CCPA,
|
|
304
|
+
RegulationType.PIPEDA,
|
|
305
|
+
RegulationType.LGPD,
|
|
306
|
+
RegulationType.PIPL,
|
|
307
|
+
RegulationType.PRIVACY_ACT,
|
|
308
|
+
RegulationType.POPIA,
|
|
309
|
+
],
|
|
310
|
+
requires_anonymization=True,
|
|
311
|
+
requires_consent=True,
|
|
312
|
+
examples=["student_id", "school_name", "parental_consent"],
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
@classmethod
|
|
316
|
+
def get_for_regulation(cls, regulation: RegulationType) -> list[PersonalDataCategory]:
|
|
317
|
+
"""Get all data categories applicable to a regulation."""
|
|
318
|
+
categories = [
|
|
319
|
+
cls.DIRECT_IDENTIFIERS,
|
|
320
|
+
cls.QUASI_IDENTIFIERS,
|
|
321
|
+
cls.HEALTH_DATA,
|
|
322
|
+
cls.GENETIC_DATA,
|
|
323
|
+
cls.BIOMETRIC_DATA,
|
|
324
|
+
cls.FINANCIAL_DATA,
|
|
325
|
+
cls.LOCATION_DATA,
|
|
326
|
+
cls.COMMUNICATION_DATA,
|
|
327
|
+
cls.EMPLOYMENT_DATA,
|
|
328
|
+
cls.EDUCATION_DATA,
|
|
329
|
+
cls.RACIAL_ETHNIC_DATA,
|
|
330
|
+
cls.POLITICAL_DATA,
|
|
331
|
+
cls.RELIGIOUS_DATA,
|
|
332
|
+
cls.UNION_DATA,
|
|
333
|
+
cls.CHILDREN_DATA,
|
|
334
|
+
]
|
|
335
|
+
return [c for c in categories if c.applies_to(regulation)]
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
class ComplianceVerifier:
|
|
339
|
+
"""Verify anonymization compliance with regulations."""
|
|
340
|
+
|
|
341
|
+
def __init__(self, regulation: RegulationType):
|
|
342
|
+
"""Initialize verifier for specific regulation.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
regulation: Target regulation type
|
|
346
|
+
"""
|
|
347
|
+
self.regulation = regulation
|
|
348
|
+
self.categories = PersonalDataCategories.get_for_regulation(regulation)
|
|
349
|
+
|
|
350
|
+
def verify_anonymization(
|
|
351
|
+
self, original: dict[str, Any], anonymized: dict[str, Any]
|
|
352
|
+
) -> dict[str, Any]:
|
|
353
|
+
"""Verify that anonymization meets regulation requirements.
|
|
354
|
+
|
|
355
|
+
Args:
|
|
356
|
+
original: Original data before anonymization
|
|
357
|
+
anonymized: Data after anonymization
|
|
358
|
+
|
|
359
|
+
Returns:
|
|
360
|
+
Dictionary with compliance verification results
|
|
361
|
+
"""
|
|
362
|
+
issues = []
|
|
363
|
+
masked_fields = []
|
|
364
|
+
preserved_fields = []
|
|
365
|
+
|
|
366
|
+
for field, value in original.items():
|
|
367
|
+
original_val = str(value)
|
|
368
|
+
anon_val = str(anonymized.get(field, ""))
|
|
369
|
+
|
|
370
|
+
if original_val != anon_val:
|
|
371
|
+
masked_fields.append(field)
|
|
372
|
+
else:
|
|
373
|
+
preserved_fields.append(field)
|
|
374
|
+
|
|
375
|
+
# Check if sensitive categories are masked
|
|
376
|
+
for category in self.categories:
|
|
377
|
+
if category.requires_anonymization:
|
|
378
|
+
for example in category.examples or []:
|
|
379
|
+
if example in original and example not in masked_fields:
|
|
380
|
+
issues.append(f"'{example}' ({category.name}) should be anonymized")
|
|
381
|
+
|
|
382
|
+
return {
|
|
383
|
+
"compliant": len(issues) == 0,
|
|
384
|
+
"regulation": self.regulation.value,
|
|
385
|
+
"masked_fields": masked_fields,
|
|
386
|
+
"preserved_fields": preserved_fields,
|
|
387
|
+
"issues": issues,
|
|
388
|
+
"masked_count": len(masked_fields),
|
|
389
|
+
"preserved_count": len(preserved_fields),
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
def get_requirements(self) -> dict[str, Any]:
|
|
393
|
+
"""Get anonymization requirements for regulation.
|
|
394
|
+
|
|
395
|
+
Returns:
|
|
396
|
+
Dictionary with regulation requirements
|
|
397
|
+
"""
|
|
398
|
+
requires_consent = [c.name for c in self.categories if c.requires_consent]
|
|
399
|
+
requires_anonymization = [c.name for c in self.categories if c.requires_anonymization]
|
|
400
|
+
|
|
401
|
+
return {
|
|
402
|
+
"regulation": self.regulation.value,
|
|
403
|
+
"total_categories": len(self.categories),
|
|
404
|
+
"requires_anonymization": requires_anonymization,
|
|
405
|
+
"requires_explicit_consent": requires_consent,
|
|
406
|
+
"applicable_categories": [c.name for c in self.categories],
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
# Regulation-specific guidance
|
|
411
|
+
REGULATION_GUIDANCE = {
|
|
412
|
+
RegulationType.GDPR: {
|
|
413
|
+
"name": "General Data Protection Regulation (GDPR)",
|
|
414
|
+
"region": "European Union / European Economic Area",
|
|
415
|
+
"effective_date": "2018-05-25",
|
|
416
|
+
"scope": "Any organization processing data of EU residents",
|
|
417
|
+
"key_principles": [
|
|
418
|
+
"Lawfulness, fairness, transparency",
|
|
419
|
+
"Purpose limitation",
|
|
420
|
+
"Data minimization",
|
|
421
|
+
"Accuracy",
|
|
422
|
+
"Storage limitation",
|
|
423
|
+
"Integrity and confidentiality",
|
|
424
|
+
"Accountability",
|
|
425
|
+
],
|
|
426
|
+
"anonymization_standard": "Irreversible de-identification with no re-identification risk",
|
|
427
|
+
"consent_requirement": "Explicit opt-in for most processing",
|
|
428
|
+
"data_subject_rights": [
|
|
429
|
+
"Right to access",
|
|
430
|
+
"Right to rectification",
|
|
431
|
+
"Right to erasure (right to be forgotten)",
|
|
432
|
+
"Right to restrict processing",
|
|
433
|
+
"Right to data portability",
|
|
434
|
+
"Right to object",
|
|
435
|
+
"Rights related to automated decision making",
|
|
436
|
+
],
|
|
437
|
+
"penalty": "Up to €20M or 4% global revenue",
|
|
438
|
+
},
|
|
439
|
+
RegulationType.CCPA: {
|
|
440
|
+
"name": "California Consumer Privacy Act (CCPA)",
|
|
441
|
+
"region": "California, United States",
|
|
442
|
+
"effective_date": "2020-01-01",
|
|
443
|
+
"scope": "Businesses collecting data of California residents",
|
|
444
|
+
"key_principles": [
|
|
445
|
+
"Transparency",
|
|
446
|
+
"Consumer rights",
|
|
447
|
+
"Non-discrimination",
|
|
448
|
+
"Opt-out mechanism",
|
|
449
|
+
],
|
|
450
|
+
"anonymization_standard": "Aggregate consumer information where individual identity cannot be determined",
|
|
451
|
+
"consent_requirement": "Opt-out mechanism (right to delete, know, opt-out)",
|
|
452
|
+
"data_subject_rights": [
|
|
453
|
+
"Right to know",
|
|
454
|
+
"Right to delete",
|
|
455
|
+
"Right to opt-out",
|
|
456
|
+
"Right to non-discrimination",
|
|
457
|
+
],
|
|
458
|
+
"penalty": "Up to $7,500 per violation",
|
|
459
|
+
},
|
|
460
|
+
RegulationType.PIPEDA: {
|
|
461
|
+
"name": "Personal Information Protection and Electronic Documents Act",
|
|
462
|
+
"region": "Canada",
|
|
463
|
+
"effective_date": "2004-01-01",
|
|
464
|
+
"scope": "Private sector organizations in Canada",
|
|
465
|
+
"key_principles": [
|
|
466
|
+
"Accountability",
|
|
467
|
+
"Identifying purposes",
|
|
468
|
+
"Consent",
|
|
469
|
+
"Limiting collection",
|
|
470
|
+
"Limiting use",
|
|
471
|
+
"Accuracy",
|
|
472
|
+
"Safeguarding",
|
|
473
|
+
"Openness",
|
|
474
|
+
"Access",
|
|
475
|
+
"Challenging compliance",
|
|
476
|
+
],
|
|
477
|
+
"anonymization_standard": "Removal of identifying information with minimal re-identification risk",
|
|
478
|
+
"consent_requirement": "Informed consent for collection and use",
|
|
479
|
+
"data_subject_rights": [
|
|
480
|
+
"Right to access",
|
|
481
|
+
"Right to correct inaccuracies",
|
|
482
|
+
"Right to challenge non-compliance",
|
|
483
|
+
],
|
|
484
|
+
"penalty": "Up to CAD $100,000 per violation",
|
|
485
|
+
},
|
|
486
|
+
RegulationType.LGPD: {
|
|
487
|
+
"name": "Lei Geral de Proteção de Dados (LGPD)",
|
|
488
|
+
"region": "Brazil",
|
|
489
|
+
"effective_date": "2020-09-18",
|
|
490
|
+
"scope": "All organizations processing data of Brazilian residents",
|
|
491
|
+
"key_principles": [
|
|
492
|
+
"Respect for privacy",
|
|
493
|
+
"Self-determination",
|
|
494
|
+
"Free access",
|
|
495
|
+
"Quality",
|
|
496
|
+
"Transparency",
|
|
497
|
+
"Security",
|
|
498
|
+
"Prevention",
|
|
499
|
+
"Non-discrimination",
|
|
500
|
+
"Accountability",
|
|
501
|
+
],
|
|
502
|
+
"anonymization_standard": "Irreversible de-identification making re-identification impossible",
|
|
503
|
+
"consent_requirement": "Explicit consent required for most processing",
|
|
504
|
+
"data_subject_rights": [
|
|
505
|
+
"Right to access",
|
|
506
|
+
"Right to rectification",
|
|
507
|
+
"Right to deletion",
|
|
508
|
+
"Right to data portability",
|
|
509
|
+
"Right to oppose processing",
|
|
510
|
+
],
|
|
511
|
+
"penalty": "Up to BRL 50M or 2% annual revenue",
|
|
512
|
+
},
|
|
513
|
+
RegulationType.PIPL: {
|
|
514
|
+
"name": "Personal Information Protection Law (PIPL)",
|
|
515
|
+
"region": "China (People's Republic of)",
|
|
516
|
+
"effective_date": "2021-11-01",
|
|
517
|
+
"scope": "Entities processing personal information in China",
|
|
518
|
+
"key_principles": [
|
|
519
|
+
"Legal basis",
|
|
520
|
+
"Purpose limitation",
|
|
521
|
+
"Data minimization",
|
|
522
|
+
"Accuracy and timeliness",
|
|
523
|
+
"Integrity and confidentiality",
|
|
524
|
+
"Accountability",
|
|
525
|
+
],
|
|
526
|
+
"anonymization_standard": "Irreversible de-identification with no re-identification possibility",
|
|
527
|
+
"consent_requirement": "Explicit consent and transparency",
|
|
528
|
+
"data_subject_rights": [
|
|
529
|
+
"Right to access",
|
|
530
|
+
"Right to rectification",
|
|
531
|
+
"Right to deletion",
|
|
532
|
+
"Right to know processing rules",
|
|
533
|
+
],
|
|
534
|
+
"penalty": "Up to CNY 50M or 5% annual revenue",
|
|
535
|
+
},
|
|
536
|
+
RegulationType.PRIVACY_ACT: {
|
|
537
|
+
"name": "Privacy Act 1988 (as amended)",
|
|
538
|
+
"region": "Australia",
|
|
539
|
+
"effective_date": "1988-12-21",
|
|
540
|
+
"scope": "Australian government agencies and private sector organizations",
|
|
541
|
+
"key_principles": [
|
|
542
|
+
"Collection",
|
|
543
|
+
"Use and disclosure",
|
|
544
|
+
"Data quality",
|
|
545
|
+
"Data security",
|
|
546
|
+
"Openness",
|
|
547
|
+
"Access and correction",
|
|
548
|
+
"Unique identifiers",
|
|
549
|
+
"Anonymity",
|
|
550
|
+
"Transborder data flows",
|
|
551
|
+
],
|
|
552
|
+
"anonymization_standard": "De-identification making re-identification not practically possible",
|
|
553
|
+
"consent_requirement": "Generally required for personal information handling",
|
|
554
|
+
"data_subject_rights": [
|
|
555
|
+
"Right to access",
|
|
556
|
+
"Right to correction",
|
|
557
|
+
"Right to lodge complaints",
|
|
558
|
+
],
|
|
559
|
+
"penalty": "Up to AUD 2.5M for serious breaches",
|
|
560
|
+
},
|
|
561
|
+
RegulationType.POPIA: {
|
|
562
|
+
"name": "Protection of Personal Information Act (POPIA)",
|
|
563
|
+
"region": "South Africa",
|
|
564
|
+
"effective_date": "2020-07-01",
|
|
565
|
+
"scope": "All organizations processing personal information",
|
|
566
|
+
"key_principles": [
|
|
567
|
+
"Lawfulness",
|
|
568
|
+
"Purpose limitation",
|
|
569
|
+
"Accountability",
|
|
570
|
+
"Openness",
|
|
571
|
+
"Security",
|
|
572
|
+
"Access",
|
|
573
|
+
"Accuracy",
|
|
574
|
+
"Transience",
|
|
575
|
+
],
|
|
576
|
+
"anonymization_standard": "Complete removal of personal information with no re-identification risk",
|
|
577
|
+
"consent_requirement": "Informed consent required for processing",
|
|
578
|
+
"data_subject_rights": [
|
|
579
|
+
"Right to access",
|
|
580
|
+
"Right to object",
|
|
581
|
+
"Right to rectification",
|
|
582
|
+
"Right to erasure",
|
|
583
|
+
],
|
|
584
|
+
"penalty": "Up to ZAR 10M or 10% annual revenue",
|
|
585
|
+
},
|
|
586
|
+
}
|