fraiseql-confiture 0.3.4__cp311-cp311-win_amd64.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.cp311-win_amd64.pyd +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 +1656 -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 +132 -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 +793 -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 +0 -0
- confiture/models/lint.py +193 -0
- confiture/models/migration.py +180 -0
- confiture/models/schema.py +203 -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 +38 -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/utils/__init__.py +0 -0
- fraiseql_confiture-0.3.4.dist-info/METADATA +438 -0
- fraiseql_confiture-0.3.4.dist-info/RECORD +119 -0
- fraiseql_confiture-0.3.4.dist-info/WHEEL +4 -0
- fraiseql_confiture-0.3.4.dist-info/entry_points.txt +2 -0
- fraiseql_confiture-0.3.4.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
"""SaaS (Software-as-a-Service) user data anonymization scenario.
|
|
2
|
+
|
|
3
|
+
Real-world use case: Anonymizing user accounts, billing, and usage data for analytics.
|
|
4
|
+
|
|
5
|
+
Data Types:
|
|
6
|
+
- User names (PII)
|
|
7
|
+
- Email addresses (PII)
|
|
8
|
+
- Phone numbers (PII)
|
|
9
|
+
- Organization names (sensitive - may be identifying)
|
|
10
|
+
- Billing addresses (PII)
|
|
11
|
+
- Payment methods (PCI-DSS)
|
|
12
|
+
- IP addresses (tracking/privacy)
|
|
13
|
+
- User agents (sensitive)
|
|
14
|
+
- Usage metrics (preserve for analytics)
|
|
15
|
+
- Subscription tier (preserve for analysis)
|
|
16
|
+
- Account creation date (preserve)
|
|
17
|
+
- Last login (sensitive - preserve year/month)
|
|
18
|
+
- Feature usage (preserve for product analytics)
|
|
19
|
+
- Billing amounts (preserve for financial analysis)
|
|
20
|
+
|
|
21
|
+
Strategy:
|
|
22
|
+
- Names: Firstname/lastname masking
|
|
23
|
+
- Email: Email redaction
|
|
24
|
+
- Phone: Phone masking
|
|
25
|
+
- Organization: Name initials
|
|
26
|
+
- Billing address: Address masking
|
|
27
|
+
- Credit cards: Last 4 only
|
|
28
|
+
- IP addresses: Complete masking
|
|
29
|
+
- Timestamps: Preserve year/month
|
|
30
|
+
- Usage metrics: Preserve for analytics
|
|
31
|
+
- Subscription data: Preserve
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
from confiture.core.anonymization.factory import StrategyFactory, StrategyProfile
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class SaaSScenario:
|
|
38
|
+
"""SaaS user data anonymization scenario.
|
|
39
|
+
|
|
40
|
+
Demonstrates anonymizing user and account data while preserving product
|
|
41
|
+
analytics and usage metrics.
|
|
42
|
+
|
|
43
|
+
Example:
|
|
44
|
+
>>> scenario = SaaSScenario()
|
|
45
|
+
>>> data = {
|
|
46
|
+
... "user_id": "USR-789456",
|
|
47
|
+
... "user_name": "john.smith",
|
|
48
|
+
... "first_name": "John",
|
|
49
|
+
... "last_name": "Smith",
|
|
50
|
+
... "text_redaction": "john.smith@acmecorp.com",
|
|
51
|
+
... "text_redaction": "555-123-4567",
|
|
52
|
+
... "organization_name": "Acme Corporation",
|
|
53
|
+
... "organization_type": "Enterprise",
|
|
54
|
+
... "billing_address": "123 Business Park",
|
|
55
|
+
... "billing_city": "San Francisco",
|
|
56
|
+
... "billing_state": "CA",
|
|
57
|
+
... "billing_country": "US",
|
|
58
|
+
... "card_last4": "4242",
|
|
59
|
+
... "card_type": "Visa",
|
|
60
|
+
... "subscription_tier": "Enterprise",
|
|
61
|
+
... "monthly_cost": 999,
|
|
62
|
+
... "seats": 50,
|
|
63
|
+
... "created_at": "2023-01-15",
|
|
64
|
+
... "last_login": "2024-12-15",
|
|
65
|
+
... "login_ip": "192.168.1.100",
|
|
66
|
+
... "monthly_api_calls": 5000000,
|
|
67
|
+
... "storage_gb": 500,
|
|
68
|
+
... "features_enabled": ["analytics", "api", "sso"],
|
|
69
|
+
... }
|
|
70
|
+
>>> anonymized = scenario.anonymize(data)
|
|
71
|
+
>>> # PII masked, usage data preserved
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def get_profile() -> StrategyProfile:
|
|
76
|
+
"""Get SaaS data anonymization profile.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
StrategyProfile configured for SaaS user and account data.
|
|
80
|
+
|
|
81
|
+
Strategy Mapping:
|
|
82
|
+
- user_id: preserve (business identifier)
|
|
83
|
+
- user_name: email or hash (username anonymization)
|
|
84
|
+
- first_name: firstname masking
|
|
85
|
+
- last_name: lastname masking
|
|
86
|
+
- email: email redaction
|
|
87
|
+
- phone: phone masking
|
|
88
|
+
- organization_name: name initials
|
|
89
|
+
- billing_address: address masking
|
|
90
|
+
- billing_city: preserve (location for reporting)
|
|
91
|
+
- billing_state: preserve
|
|
92
|
+
- billing_country: preserve
|
|
93
|
+
- card: credit card (last 4)
|
|
94
|
+
- subscription_tier: preserve (business data)
|
|
95
|
+
- monthly_cost: preserve (financial data)
|
|
96
|
+
- seats: preserve (business metric)
|
|
97
|
+
- created_at: preserve (business metric)
|
|
98
|
+
- last_login: date masking (preserve year/month)
|
|
99
|
+
- login_ip: IP masking
|
|
100
|
+
- api_calls: preserve (usage metric)
|
|
101
|
+
- storage: preserve (usage metric)
|
|
102
|
+
- features: preserve (product data)
|
|
103
|
+
"""
|
|
104
|
+
return StrategyProfile(
|
|
105
|
+
name="saas_users",
|
|
106
|
+
seed=42, # Fixed seed for reproducibility
|
|
107
|
+
columns={
|
|
108
|
+
# User identifiers - preserve
|
|
109
|
+
"user_id": "preserve",
|
|
110
|
+
"account_id": "preserve",
|
|
111
|
+
"tenant_id": "preserve",
|
|
112
|
+
"organization_id": "preserve",
|
|
113
|
+
# User PII - mask
|
|
114
|
+
"user_name": "text_redaction",
|
|
115
|
+
"username": "text_redaction",
|
|
116
|
+
"handle": "text_redaction",
|
|
117
|
+
"first_name": "name",
|
|
118
|
+
"last_name": "name",
|
|
119
|
+
"full_name": "name",
|
|
120
|
+
"display_name": "name",
|
|
121
|
+
# Contact - redact
|
|
122
|
+
"email": "text_redaction",
|
|
123
|
+
"backup_email": "text_redaction",
|
|
124
|
+
"phone": "text_redaction",
|
|
125
|
+
"phone_number": "text_redaction",
|
|
126
|
+
"mobile": "text_redaction",
|
|
127
|
+
# Organization - mask name
|
|
128
|
+
"organization_name": "name",
|
|
129
|
+
"org_name": "name",
|
|
130
|
+
"company_name": "name",
|
|
131
|
+
"team_name": "name",
|
|
132
|
+
"workspace_name": "name",
|
|
133
|
+
# Organization metadata - preserve
|
|
134
|
+
"organization_type": "preserve",
|
|
135
|
+
"industry": "preserve",
|
|
136
|
+
"company_size": "preserve",
|
|
137
|
+
"organization_role": "preserve",
|
|
138
|
+
"role": "preserve",
|
|
139
|
+
"permission_level": "preserve",
|
|
140
|
+
# Billing address - mask
|
|
141
|
+
"billing_address": "address",
|
|
142
|
+
"billing_street": "address",
|
|
143
|
+
"billing_address2": "address",
|
|
144
|
+
"billing_city": "preserve",
|
|
145
|
+
"billing_state": "preserve",
|
|
146
|
+
"billing_zip": "preserve",
|
|
147
|
+
"billing_country": "preserve",
|
|
148
|
+
# Shipping address - mask
|
|
149
|
+
"shipping_address": "address",
|
|
150
|
+
"shipping_city": "preserve",
|
|
151
|
+
"shipping_state": "preserve",
|
|
152
|
+
"shipping_country": "preserve",
|
|
153
|
+
# Payment - PCI-DSS compliant
|
|
154
|
+
"card_number": "credit_card",
|
|
155
|
+
"card_last4": "preserve",
|
|
156
|
+
"card_type": "preserve",
|
|
157
|
+
"card_brand": "preserve",
|
|
158
|
+
"card_expiry": "preserve",
|
|
159
|
+
"billing_method": "preserve",
|
|
160
|
+
# Subscription/pricing - preserve
|
|
161
|
+
"subscription_id": "preserve",
|
|
162
|
+
"subscription_tier": "preserve",
|
|
163
|
+
"subscription_plan": "preserve",
|
|
164
|
+
"subscription_status": "preserve",
|
|
165
|
+
"monthly_cost": "preserve",
|
|
166
|
+
"annual_cost": "preserve",
|
|
167
|
+
"price": "preserve",
|
|
168
|
+
"seats": "preserve",
|
|
169
|
+
"licenses": "preserve",
|
|
170
|
+
"user_limit": "preserve",
|
|
171
|
+
"api_limit": "preserve",
|
|
172
|
+
"storage_limit": "preserve",
|
|
173
|
+
# Dates - preserve year/month
|
|
174
|
+
"created_at": "preserve",
|
|
175
|
+
"created_date": "preserve",
|
|
176
|
+
"signup_date": "date",
|
|
177
|
+
"updated_at": "preserve",
|
|
178
|
+
"deleted_at": "preserve",
|
|
179
|
+
"last_login": "date",
|
|
180
|
+
"last_login_date": "date",
|
|
181
|
+
"last_activity": "date",
|
|
182
|
+
"trial_end_date": "date",
|
|
183
|
+
"billing_cycle_date": "preserve",
|
|
184
|
+
# Usage metrics - preserve for analytics
|
|
185
|
+
"monthly_api_calls": "preserve",
|
|
186
|
+
"api_calls": "preserve",
|
|
187
|
+
"requests_used": "preserve",
|
|
188
|
+
"storage_gb": "preserve",
|
|
189
|
+
"storage_used": "preserve",
|
|
190
|
+
"data_transferred": "preserve",
|
|
191
|
+
"sessions": "preserve",
|
|
192
|
+
"active_users": "preserve",
|
|
193
|
+
"page_views": "preserve",
|
|
194
|
+
"events_processed": "preserve",
|
|
195
|
+
# Activity - preserve for analytics
|
|
196
|
+
"login_count": "preserve",
|
|
197
|
+
"failed_login_count": "preserve",
|
|
198
|
+
"actions_count": "preserve",
|
|
199
|
+
"documents_created": "preserve",
|
|
200
|
+
"integrations_active": "preserve",
|
|
201
|
+
# Technical - mask
|
|
202
|
+
"login_ip": "ip_address",
|
|
203
|
+
"ip_address": "ip_address",
|
|
204
|
+
"last_ip": "ip_address",
|
|
205
|
+
"user_agent": "text_redaction",
|
|
206
|
+
"device_id": "custom",
|
|
207
|
+
"device_type": "preserve",
|
|
208
|
+
"browser": "preserve",
|
|
209
|
+
"os": "preserve",
|
|
210
|
+
# Features - preserve
|
|
211
|
+
"features_enabled": "preserve",
|
|
212
|
+
"add_ons": "preserve",
|
|
213
|
+
"integrations": "preserve",
|
|
214
|
+
"api_key_count": "preserve",
|
|
215
|
+
"sso_enabled": "preserve",
|
|
216
|
+
"mfa_enabled": "preserve",
|
|
217
|
+
"audit_logs": "preserve",
|
|
218
|
+
# Status/metadata - preserve
|
|
219
|
+
"status": "preserve",
|
|
220
|
+
"account_status": "preserve",
|
|
221
|
+
"verified": "preserve",
|
|
222
|
+
"is_admin": "preserve",
|
|
223
|
+
"is_active": "preserve",
|
|
224
|
+
"tags": "preserve",
|
|
225
|
+
},
|
|
226
|
+
defaults="preserve",
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
@classmethod
|
|
230
|
+
def create_factory(cls) -> StrategyFactory:
|
|
231
|
+
"""Create factory for SaaS data anonymization.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
Configured StrategyFactory for SaaS user/account data.
|
|
235
|
+
"""
|
|
236
|
+
profile = cls.get_profile()
|
|
237
|
+
return StrategyFactory(profile)
|
|
238
|
+
|
|
239
|
+
@classmethod
|
|
240
|
+
def anonymize(cls, data: dict) -> dict:
|
|
241
|
+
"""Anonymize SaaS user/account data.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
data: User, account, or organization data dictionary.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Anonymized data with PII masked and usage metrics preserved.
|
|
248
|
+
|
|
249
|
+
Example:
|
|
250
|
+
>>> data = {
|
|
251
|
+
... "user_id": "USR-789456",
|
|
252
|
+
... "first_name": "John",
|
|
253
|
+
... "text_redaction": "john@example.com",
|
|
254
|
+
... "organization_name": "Acme Corp",
|
|
255
|
+
... "monthly_cost": 999,
|
|
256
|
+
... "api_calls": 5000000,
|
|
257
|
+
... }
|
|
258
|
+
>>> result = SaaSScenario.anonymize(data)
|
|
259
|
+
>>> result["user_id"] # Preserved
|
|
260
|
+
'USR-789456'
|
|
261
|
+
>>> result["first_name"] # Anonymized
|
|
262
|
+
'Michael'
|
|
263
|
+
>>> result["text_redaction"] # Redacted
|
|
264
|
+
'[EMAIL]'
|
|
265
|
+
>>> result["organization_name"] # Masked
|
|
266
|
+
'ABC'
|
|
267
|
+
>>> result["monthly_cost"] # Preserved
|
|
268
|
+
999
|
|
269
|
+
"""
|
|
270
|
+
factory = cls.create_factory()
|
|
271
|
+
return factory.anonymize(data)
|
|
272
|
+
|
|
273
|
+
@classmethod
|
|
274
|
+
def anonymize_batch(cls, data_list: list[dict]) -> list[dict]:
|
|
275
|
+
"""Anonymize batch of SaaS records.
|
|
276
|
+
|
|
277
|
+
Args:
|
|
278
|
+
data_list: List of user/account/organization records.
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
List of anonymized SaaS data records.
|
|
282
|
+
"""
|
|
283
|
+
factory = cls.create_factory()
|
|
284
|
+
return [factory.anonymize(record) for record in data_list]
|
|
285
|
+
|
|
286
|
+
@classmethod
|
|
287
|
+
def get_strategy_info(cls) -> dict:
|
|
288
|
+
"""Get information about strategies used.
|
|
289
|
+
|
|
290
|
+
Returns:
|
|
291
|
+
Dictionary mapping column names to strategy names.
|
|
292
|
+
"""
|
|
293
|
+
profile = cls.get_profile()
|
|
294
|
+
factory = StrategyFactory(profile)
|
|
295
|
+
return factory.list_column_strategies()
|