cdp-edge 1.2.0

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.
Files changed (128) hide show
  1. package/README.md +367 -0
  2. package/bin/cdp-edge.js +61 -0
  3. package/contracts/api-versions.json +368 -0
  4. package/dist/commands/analyze.js +52 -0
  5. package/dist/commands/infra.js +54 -0
  6. package/dist/commands/install.js +168 -0
  7. package/dist/commands/server.js +174 -0
  8. package/dist/commands/setup.js +123 -0
  9. package/dist/commands/validate.js +84 -0
  10. package/dist/index.js +12 -0
  11. package/docs/CI-CD-SETUP.md +217 -0
  12. package/docs/PixelBuilder-Documentacao-Completa (2).docx +0 -0
  13. package/docs/events-reference.md +359 -0
  14. package/docs/installation.md +155 -0
  15. package/docs/quick-start.md +185 -0
  16. package/docs/sdk-reference.md +371 -0
  17. package/docs/whatsapp-ctwa.md +209 -0
  18. package/extracted-skill/tracking-events-generator/INDEX.md +94 -0
  19. package/extracted-skill/tracking-events-generator/INSTALACAO-CDPEDGE.md +58 -0
  20. package/extracted-skill/tracking-events-generator/INTEGRACAO-COMPLETA.md +594 -0
  21. package/extracted-skill/tracking-events-generator/MELHORIAS-IMPLEMENTADAS.md +412 -0
  22. package/extracted-skill/tracking-events-generator/Premium-Tracking-Intelligence-Resumo.md +333 -0
  23. package/extracted-skill/tracking-events-generator/SKILL.md +257 -0
  24. package/extracted-skill/tracking-events-generator/advanced-matching.js +364 -0
  25. package/extracted-skill/tracking-events-generator/agents/ab-testing-agent.md +54 -0
  26. package/extracted-skill/tracking-events-generator/agents/attribution-agent.md +1304 -0
  27. package/extracted-skill/tracking-events-generator/agents/bing-agent.md +76 -0
  28. package/extracted-skill/tracking-events-generator/agents/browser-tracking.md +264 -0
  29. package/extracted-skill/tracking-events-generator/agents/code-guardian-agent.md +149 -0
  30. package/extracted-skill/tracking-events-generator/agents/compliance-agent.md +2077 -0
  31. package/extracted-skill/tracking-events-generator/agents/crm-integration-agent.md +1419 -0
  32. package/extracted-skill/tracking-events-generator/agents/dashboard-agent.md +456 -0
  33. package/extracted-skill/tracking-events-generator/agents/database-agent.md +667 -0
  34. package/extracted-skill/tracking-events-generator/agents/debug-agent.md +1455 -0
  35. package/extracted-skill/tracking-events-generator/agents/domain-setup-agent.md +224 -0
  36. package/extracted-skill/tracking-events-generator/agents/email-agent.md +61 -0
  37. package/extracted-skill/tracking-events-generator/agents/fingerprint-agent.md +52 -0
  38. package/extracted-skill/tracking-events-generator/agents/google-agent.md +109 -0
  39. package/extracted-skill/tracking-events-generator/agents/intelligence-agent.md +365 -0
  40. package/extracted-skill/tracking-events-generator/agents/intelligence-scheduling.md +643 -0
  41. package/extracted-skill/tracking-events-generator/agents/linkedin-agent.md +62 -0
  42. package/extracted-skill/tracking-events-generator/agents/localization-agent.md +55 -0
  43. package/extracted-skill/tracking-events-generator/agents/ltv-predictor-agent.md +59 -0
  44. package/extracted-skill/tracking-events-generator/agents/master-feedback-loop.md +900 -0
  45. package/extracted-skill/tracking-events-generator/agents/master-orchestrator.md +1922 -0
  46. package/extracted-skill/tracking-events-generator/agents/memory-agent.json +109 -0
  47. package/extracted-skill/tracking-events-generator/agents/memory-agent.md +703 -0
  48. package/extracted-skill/tracking-events-generator/agents/meta-agent.md +110 -0
  49. package/extracted-skill/tracking-events-generator/agents/page-analyzer.md +255 -0
  50. package/extracted-skill/tracking-events-generator/agents/performance-agent.md +1157 -0
  51. package/extracted-skill/tracking-events-generator/agents/performance-optimization-agent.md +1432 -0
  52. package/extracted-skill/tracking-events-generator/agents/pinterest-agent.md +310 -0
  53. package/extracted-skill/tracking-events-generator/agents/premium-tracking-intelligence-agent.md +849 -0
  54. package/extracted-skill/tracking-events-generator/agents/r2-setup-agent.md +250 -0
  55. package/extracted-skill/tracking-events-generator/agents/reddit-agent.md +313 -0
  56. package/extracted-skill/tracking-events-generator/agents/security-enterprise-agent.md +1752 -0
  57. package/extracted-skill/tracking-events-generator/agents/server-tracking.md +1188 -0
  58. package/extracted-skill/tracking-events-generator/agents/spotify-agent.md +383 -0
  59. package/extracted-skill/tracking-events-generator/agents/tiktok-agent.md +111 -0
  60. package/extracted-skill/tracking-events-generator/agents/tracking-plan-agent.md +364 -0
  61. package/extracted-skill/tracking-events-generator/agents/validator-agent.md +267 -0
  62. package/extracted-skill/tracking-events-generator/agents/webhook-agent.md +69 -0
  63. package/extracted-skill/tracking-events-generator/agents/whatsapp-agent.md +76 -0
  64. package/extracted-skill/tracking-events-generator/agents/whatsapp-ctwa-setup-agent.md +699 -0
  65. package/extracted-skill/tracking-events-generator/agents/youtube-agent.md +422 -0
  66. package/extracted-skill/tracking-events-generator/anti-blocking.js +285 -0
  67. package/extracted-skill/tracking-events-generator/cdpTrack.js +641 -0
  68. package/extracted-skill/tracking-events-generator/contracts/api-versions.json +368 -0
  69. package/extracted-skill/tracking-events-generator/docs/guia-cloudflare-iniciante.md +107 -0
  70. package/extracted-skill/tracking-events-generator/engagement-scoring.js +226 -0
  71. package/extracted-skill/tracking-events-generator/evals/evals.json +235 -0
  72. package/extracted-skill/tracking-events-generator/integration-test.js +497 -0
  73. package/extracted-skill/tracking-events-generator/knowledge-base.md +2894 -0
  74. package/extracted-skill/tracking-events-generator/micro-events.js +992 -0
  75. package/extracted-skill/tracking-events-generator/models/captura-de-lead.md +78 -0
  76. package/extracted-skill/tracking-events-generator/models/captura-lead-evento-externo.md +99 -0
  77. package/extracted-skill/tracking-events-generator/models/checkout-proprio.md +111 -0
  78. package/extracted-skill/tracking-events-generator/models/multi-step-checkout.md +672 -0
  79. package/extracted-skill/tracking-events-generator/models/pagina-obrigado.md +55 -0
  80. package/extracted-skill/tracking-events-generator/models/pinterest/conversions-api-template.js +144 -0
  81. package/extracted-skill/tracking-events-generator/models/pinterest/event-mappings.json +48 -0
  82. package/extracted-skill/tracking-events-generator/models/pinterest/tag-template.js +28 -0
  83. package/extracted-skill/tracking-events-generator/models/quiz-funnel.md +68 -0
  84. package/extracted-skill/tracking-events-generator/models/reddit/conversions-api-template.js +205 -0
  85. package/extracted-skill/tracking-events-generator/models/reddit/event-mappings.json +56 -0
  86. package/extracted-skill/tracking-events-generator/models/reddit/pixel-template.js +19 -0
  87. package/extracted-skill/tracking-events-generator/models/scenarios/behavior-engine.js +425 -0
  88. package/extracted-skill/tracking-events-generator/models/scenarios/real-estate-logic.md +50 -0
  89. package/extracted-skill/tracking-events-generator/models/scenarios/sales-page-logic.md +50 -0
  90. package/extracted-skill/tracking-events-generator/models/trafego-direto.md +582 -0
  91. package/extracted-skill/tracking-events-generator/models/webinar-registration.md +63 -0
  92. package/extracted-skill/tracking-events-generator/tracking.config.js +46 -0
  93. package/extracted-skill/tracking-events-generator/walkthrough.md +26 -0
  94. package/package.json +75 -0
  95. package/server-edge-tracker/INSTALAR.md +328 -0
  96. package/server-edge-tracker/migrate-new-db.sql +137 -0
  97. package/server-edge-tracker/migrate-v2.sql +16 -0
  98. package/server-edge-tracker/migrate-v3.sql +6 -0
  99. package/server-edge-tracker/migrate-v4.sql +18 -0
  100. package/server-edge-tracker/migrate-v5.sql +17 -0
  101. package/server-edge-tracker/migrate-v6.sql +24 -0
  102. package/server-edge-tracker/migrate.sql +111 -0
  103. package/server-edge-tracker/schema.sql +265 -0
  104. package/server-edge-tracker/worker.js +2574 -0
  105. package/server-edge-tracker/wrangler.toml +85 -0
  106. package/templates/afiliado-sem-landing.md +312 -0
  107. package/templates/captura-de-lead.md +78 -0
  108. package/templates/captura-lead-evento-externo.md +99 -0
  109. package/templates/checkout-proprio.md +111 -0
  110. package/templates/install/.claude/commands/cdp.md +1 -0
  111. package/templates/install/CLAUDE.md +65 -0
  112. package/templates/linkedin/tag-template.js +46 -0
  113. package/templates/multi-step-checkout.md +673 -0
  114. package/templates/pagina-obrigado.md +55 -0
  115. package/templates/pinterest/conversions-api-template.js +144 -0
  116. package/templates/pinterest/event-mappings.json +48 -0
  117. package/templates/pinterest/tag-template.js +28 -0
  118. package/templates/quiz-funnel.md +68 -0
  119. package/templates/reddit/conversions-api-template.js +205 -0
  120. package/templates/reddit/event-mappings.json +56 -0
  121. package/templates/reddit/pixel-template.js +46 -0
  122. package/templates/scenarios/behavior-engine.js +402 -0
  123. package/templates/scenarios/real-estate-logic.md +50 -0
  124. package/templates/scenarios/sales-page-logic.md +50 -0
  125. package/templates/spotify/pixel-template.js +46 -0
  126. package/templates/trafego-direto.md +582 -0
  127. package/templates/vsl-page.md +292 -0
  128. package/templates/webinar-registration.md +63 -0
@@ -0,0 +1,2077 @@
1
+ ---
2
+ name: compliance-agent
3
+ description: Compliance Enterprise Agent - GDPR/LGPD/CCPA compliance, consent management, data rights for CDP Edge
4
+ type: agent
5
+ persona: Compliance Officer specializing in data privacy regulations (GDPR, LGPD, CCPA) and consent management systems
6
+ version: "1.0.0"
7
+ ---
8
+
9
+ # Compliance Enterprise Agent
10
+
11
+ ## 🛡️ Visão Geral
12
+
13
+ Agente especializado em compliance de dados para o sistema CDP Edge. Implementa funcionalidades completas de GDPR (União Europeia), LGPD (Brasil) e CCPA (Califórnia), incluindo gestão de consentimento, direitos dos titulares, políticas de retenção e trilhas de auditoria.
14
+
15
+ ---
16
+
17
+ ## 📚 Regulamentações Suportadas
18
+
19
+ ### GDPR (General Data Protection Regulation - EU)
20
+ - **Bases Legais**: Consentimento, Legítimo Interesse, Cumprimento de Contrato
21
+ - **Direitos dos Titulares**: Acesso, Retificação, Exclusão, Portabilidade, Oposição, Restrição
22
+ - **Consentimento**: Requer opt-in explícito, revogável a qualquer momento
23
+ - **Data Breach**: Notificação obrigatória em até 72h
24
+ - **DPO**: Ponto de contato obrigatório
25
+
26
+ ### LGPD (Lei Geral de Proteção de Dados - Brasil)
27
+ - **Bases Legais**: Consentimento, Legítimo Interesse, Cumprimento de Obrigação Legal, etc.
28
+ - **Direitos dos Titulares**: Confirmação, Acesso, Correção, Eliminação, Portabilidade, Revogação
29
+ - **ANPD**: Autoridade Nacional de Proteção de Dados
30
+ - **Consentimento**: Livre, informado e inequívoco
31
+ - **Data Breach**: Notificação à ANPD e titulares em até 2 dias úteis
32
+
33
+ ### CCPA (California Consumer Privacy Act - USA)
34
+ - **Direitos do Consumidor**: Acesso, Exclusão, Opt-out de Venda, Não Discriminação
35
+ - **Opt-out**: Botão "Do Not Sell My Personal Information"
36
+ - **Exceções**: Necessário para negócio, segurança, pesquisa
37
+ - **Private Right of Action**: Ações privadas por violações
38
+
39
+ ---
40
+
41
+ ## 🏗️ Arquitetura de Compliance
42
+
43
+ ```
44
+ ┌─────────────────────────────────────────────────────────────┐
45
+ │ Consent Management Layer │
46
+ │ (Consent collection, storage, tracking) │
47
+ └─────────────────────────────────────────────────────────────┘
48
+
49
+ ┌─────────────────────────────────────────────────────────────┐
50
+ │ Data Rights Layer │
51
+ │ (Access, Deletion, Portability, Rectification) │
52
+ └─────────────────────────────────────────────────────────────┘
53
+
54
+ ┌─────────────────────────────────────────────────────────────┐
55
+ │ Data Retention Layer │
56
+ │ (TTL policies, auto-deletion, archival) │
57
+ └─────────────────────────────────────────────────────────────┘
58
+
59
+ ┌─────────────────────────────────────────────────────────────┐
60
+ │ Compliance Audit Layer │
61
+ │ (Audit trails, consent history, access logs) │
62
+ └─────────────────────────────────────────────────────────────┘
63
+ ```
64
+
65
+ ---
66
+
67
+ ## 🍪 Sistema de Gestão de Consentimento
68
+
69
+ ### D1 Schema para Consent Management
70
+
71
+ ```sql
72
+ -- Consent Records Table
73
+ CREATE TABLE IF NOT EXISTS consent_records (
74
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
75
+ user_id TEXT NOT NULL,
76
+ consent_id TEXT UNIQUE NOT NULL,
77
+ consent_type TEXT NOT NULL, -- 'marketing', 'analytics', 'personalization', 'essential'
78
+ consent_given BOOLEAN NOT NULL,
79
+ legal_basis TEXT NOT NULL, -- 'consent', 'legitimate_interest', 'contract', 'legal_obligation'
80
+ timestamp DATETIME NOT NULL,
81
+ ip_address TEXT,
82
+ user_agent TEXT,
83
+ consent_version TEXT NOT NULL, -- Version of consent policy
84
+ source TEXT NOT NULL, -- 'cookie_banner', 'preference_center', 'explicit_action'
85
+ expires_at DATETIME, -- Optional expiration for consent
86
+ UNIQUE(user_id, consent_type, consent_id)
87
+ );
88
+
89
+ CREATE INDEX IF NOT EXISTS idx_consent_user_id
90
+ ON consent_records(user_id, timestamp DESC);
91
+
92
+ CREATE INDEX IF NOT EXISTS idx_consent_id
93
+ ON consent_records(consent_id);
94
+
95
+ CREATE INDEX IF NOT EXISTS idx_consent_type
96
+ ON consent_records(consent_type, consent_given);
97
+
98
+ -- Consent History Table (Audit Trail)
99
+ CREATE TABLE IF NOT EXISTS consent_history (
100
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
101
+ consent_id TEXT NOT NULL,
102
+ action TEXT NOT NULL, -- 'granted', 'revoked', 'updated'
103
+ previous_state JSON, -- Previous consent state
104
+ new_state JSON, -- New consent state
105
+ timestamp DATETIME NOT NULL,
106
+ ip_address TEXT,
107
+ user_agent TEXT,
108
+ reason TEXT -- Reason for change (e.g., 'user_action', 'policy_update')
109
+ );
110
+
111
+ CREATE INDEX IF NOT EXISTS idx_consent_history_consent_id
112
+ ON consent_history(consent_id, timestamp DESC);
113
+
114
+ CREATE INDEX IF NOT EXISTS idx_consent_history_action
115
+ ON consent_history(action, timestamp DESC);
116
+
117
+ -- Cookie Preferences Table
118
+ CREATE TABLE IF NOT EXISTS cookie_preferences (
119
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
120
+ user_id TEXT UNIQUE,
121
+ session_id TEXT,
122
+ analytics_consent BOOLEAN DEFAULT FALSE,
123
+ marketing_consent BOOLEAN DEFAULT FALSE,
124
+ personalization_consent BOOLEAN DEFAULT FALSE,
125
+ necessary_consent BOOLEAN DEFAULT TRUE, -- Always true for essential cookies
126
+ preferences_updated DATETIME NOT NULL,
127
+ preference_source TEXT NOT NULL -- 'banner', 'preference_center', 'api'
128
+ );
129
+
130
+ CREATE INDEX IF NOT EXISTS idx_cookie_preferences_user_id
131
+ ON cookie_preferences(user_id);
132
+
133
+ -- Data Retention Policies Table
134
+ CREATE TABLE IF NOT EXISTS retention_policies (
135
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
136
+ data_type TEXT NOT NULL UNIQUE,
137
+ retention_period_days INTEGER NOT NULL,
138
+ legal_basis TEXT NOT NULL,
139
+ policy_name TEXT NOT NULL,
140
+ description TEXT,
141
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
142
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
143
+ );
144
+
145
+ -- User Data Deletion Requests Table
146
+ CREATE TABLE IF NOT EXISTS deletion_requests (
147
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
148
+ user_id TEXT NOT NULL,
149
+ request_id TEXT UNIQUE NOT NULL,
150
+ request_type TEXT NOT NULL, -- 'deletion', 'rectification', 'portability', 'access'
151
+ status TEXT NOT NULL, -- 'pending', 'in_progress', 'completed', 'rejected'
152
+ requested_at DATETIME NOT NULL,
153
+ completed_at DATETIME,
154
+ rejection_reason TEXT,
155
+ ip_address TEXT,
156
+ user_agent TEXT,
157
+ processed_by TEXT, -- System or admin user
158
+ processing_notes TEXT
159
+ );
160
+
161
+ CREATE INDEX IF NOT EXISTS idx_deletion_requests_user_id
162
+ ON deletion_requests(user_id, requested_at DESC);
163
+
164
+ CREATE INDEX IF NOT EXISTS idx_deletion_requests_status
165
+ ON deletion_requests(status, requested_at);
166
+
167
+ -- Consent Policy Versions Table
168
+ CREATE TABLE IF NOT EXISTS consent_policy_versions (
169
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
170
+ version TEXT UNIQUE NOT NULL,
171
+ policy_text TEXT NOT NULL,
172
+ effective_date DATETIME NOT NULL,
173
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP
174
+ );
175
+
176
+ CREATE INDEX IF NOT EXISTS idx_consent_policy_version
177
+ ON consent_policy_versions(version, effective_date DESC);
178
+ ```
179
+
180
+ ---
181
+
182
+ ## 🔐 Consent Management System
183
+
184
+ ### Consent Collection & Storage
185
+
186
+ ```javascript
187
+ /**
188
+ * Consent Manager
189
+ * Manages user consent collection, storage, and tracking
190
+ */
191
+ class ConsentManager {
192
+ constructor(env) {
193
+ this.db = env.DB;
194
+ this.currentPolicyVersion = '1.0.0'; // Current consent policy version
195
+ }
196
+
197
+ /**
198
+ * Grant consent for a specific data processing purpose
199
+ * @param {string} userId - User ID
200
+ * @param {string} consentType - Type of consent (marketing, analytics, personalization, essential)
201
+ * @param {object} metadata - Metadata (IP, user-agent, source)
202
+ * @returns {Promise<object>} Consent record
203
+ */
204
+ async grantConsent(userId, consentType, metadata = {}) {
205
+ const consentId = this.generateConsentId();
206
+ const now = new Date().toISOString();
207
+ const expiresAt = this.calculateExpiration(consentType);
208
+
209
+ // Check if consent already exists
210
+ const existingConsent = await this.getConsent(userId, consentType);
211
+
212
+ // Record previous state for audit trail
213
+ const previousState = existingConsent ? {
214
+ consent_given: existingConsent.consent_given,
215
+ legal_basis: existingConsent.legal_basis,
216
+ timestamp: existingConsent.timestamp
217
+ } : null;
218
+
219
+ // Create or update consent record
220
+ const consentRecord = {
221
+ consent_id: consentId,
222
+ consent_type: consentType,
223
+ consent_given: true,
224
+ legal_basis: 'consent',
225
+ timestamp: now,
226
+ ip_address: metadata.ip_address || null,
227
+ user_agent: metadata.user_agent || null,
228
+ consent_version: this.currentPolicyVersion,
229
+ source: metadata.source || 'explicit_action',
230
+ expires_at: expiresAt
231
+ };
232
+
233
+ if (existingConsent) {
234
+ // Update existing consent
235
+ await this.db.prepare(`
236
+ UPDATE consent_records
237
+ SET consent_given = ?, timestamp = ?, ip_address = ?,
238
+ user_agent = ?, consent_version = ?, source = ?, expires_at = ?
239
+ WHERE user_id = ? AND consent_type = ?
240
+ `).bind(
241
+ true, now, metadata.ip_address, metadata.user_agent,
242
+ this.currentPolicyVersion, metadata.source, expiresAt,
243
+ userId, consentType
244
+ ).run();
245
+ } else {
246
+ // Insert new consent
247
+ await this.db.prepare(`
248
+ INSERT INTO consent_records
249
+ (user_id, consent_id, consent_type, consent_given, legal_basis,
250
+ timestamp, ip_address, user_agent, consent_version, source, expires_at)
251
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
252
+ `).bind(
253
+ userId, consentId, consentType, true, 'consent',
254
+ now, metadata.ip_address, metadata.user_agent,
255
+ this.currentPolicyVersion, metadata.source, expiresAt
256
+ ).run();
257
+ }
258
+
259
+ // Record in consent history
260
+ await this.recordConsentHistory(consentId, 'granted', previousState, consentRecord, metadata);
261
+
262
+ // Update cookie preferences
263
+ await this.updateCookiePreferences(userId, consentType, true, metadata.source);
264
+
265
+ return consentRecord;
266
+ }
267
+
268
+ /**
269
+ * Revoke consent for a specific data processing purpose
270
+ * @param {string} userId - User ID
271
+ * @param {string} consentType - Type of consent
272
+ * @param {object} metadata - Metadata (IP, user-agent, reason)
273
+ * @returns {Promise<object>} Consent record
274
+ */
275
+ async revokeConsent(userId, consentType, metadata = {}) {
276
+ const now = new Date().toISOString();
277
+
278
+ // Get current consent state
279
+ const existingConsent = await this.getConsent(userId, consentType);
280
+
281
+ if (!existingConsent) {
282
+ throw new Error('No consent found to revoke');
283
+ }
284
+
285
+ const previousState = {
286
+ consent_given: existingConsent.consent_given,
287
+ legal_basis: existingConsent.legal_basis,
288
+ timestamp: existingConsent.timestamp
289
+ };
290
+
291
+ // Update consent record
292
+ await this.db.prepare(`
293
+ UPDATE consent_records
294
+ SET consent_given = ?, timestamp = ?, source = ?
295
+ WHERE user_id = ? AND consent_type = ?
296
+ `).bind(
297
+ false, now, metadata.source || 'user_action',
298
+ userId, consentType
299
+ ).run();
300
+
301
+ // Record in consent history
302
+ await this.recordConsentHistory(
303
+ existingConsent.consent_id,
304
+ 'revoked',
305
+ previousState,
306
+ { ...existingConsent, consent_given: false, timestamp: now },
307
+ metadata
308
+ );
309
+
310
+ // Update cookie preferences
311
+ await this.updateCookiePreferences(userId, consentType, false, metadata.source);
312
+
313
+ // Trigger data deletion for affected data (if required)
314
+ await this.handleConsentRevocation(userId, consentType);
315
+
316
+ return { consent_id: existingConsent.consent_id, consent_given: false, timestamp: now };
317
+ }
318
+
319
+ /**
320
+ * Get current consent for a user and consent type
321
+ * @param {string} userId - User ID
322
+ * @param {string} consentType - Type of consent
323
+ * @returns {Promise<object|null>} Consent record or null
324
+ */
325
+ async getConsent(userId, consentType) {
326
+ const result = await this.db.prepare(`
327
+ SELECT * FROM consent_records
328
+ WHERE user_id = ? AND consent_type = ?
329
+ ORDER BY timestamp DESC
330
+ LIMIT 1
331
+ `).bind(userId, consentType).first();
332
+
333
+ return result || null;
334
+ }
335
+
336
+ /**
337
+ * Get all consents for a user
338
+ * @param {string} userId - User ID
339
+ * @returns {Promise<Array>} All consent records
340
+ */
341
+ async getAllConsents(userId) {
342
+ const results = await this.db.prepare(`
343
+ SELECT * FROM consent_records
344
+ WHERE user_id = ?
345
+ ORDER BY timestamp DESC
346
+ `).bind(userId).all();
347
+
348
+ return results;
349
+ }
350
+
351
+ /**
352
+ * Check if user has valid consent for a specific purpose
353
+ * @param {string} userId - User ID
354
+ * @param {string} consentType - Type of consent
355
+ * @returns {Promise<boolean>} True if consent is valid
356
+ */
357
+ async hasValidConsent(userId, consentType) {
358
+ const consent = await this.getConsent(userId, consentType);
359
+
360
+ if (!consent) {
361
+ return false;
362
+ }
363
+
364
+ // Check if consent is still valid (not revoked and not expired)
365
+ if (!consent.consent_given) {
366
+ return false;
367
+ }
368
+
369
+ // Check expiration
370
+ if (consent.expires_at && new Date(consent.expires_at) < new Date()) {
371
+ return false;
372
+ }
373
+
374
+ return true;
375
+ }
376
+
377
+ /**
378
+ * Update cookie preferences for a user
379
+ * @param {string} userId - User ID
380
+ * @param {string} consentType - Type of consent
381
+ * @param {boolean} value - Consent value
382
+ * @param {string} source - Source of preference change
383
+ */
384
+ async updateCookiePreferences(userId, consentType, value, source) {
385
+ const now = new Date().toISOString();
386
+
387
+ // Map consent types to cookie preference columns
388
+ const consentTypeMap = {
389
+ 'marketing': 'marketing_consent',
390
+ 'analytics': 'analytics_consent',
391
+ 'personalization': 'personalization_consent',
392
+ 'essential': 'necessary_consent'
393
+ };
394
+
395
+ const column = consentTypeMap[consentType];
396
+ if (!column) {
397
+ return;
398
+ }
399
+
400
+ // Check if preferences exist
401
+ const existing = await this.db.prepare(`
402
+ SELECT * FROM cookie_preferences WHERE user_id = ?
403
+ `).bind(userId).first();
404
+
405
+ if (existing) {
406
+ // Update existing preferences
407
+ await this.db.prepare(`
408
+ UPDATE cookie_preferences
409
+ SET ${column} = ?, preferences_updated = ?, preference_source = ?
410
+ WHERE user_id = ?
411
+ `).bind(value, now, source, userId).run();
412
+ } else {
413
+ // Insert new preferences
414
+ await this.db.prepare(`
415
+ INSERT INTO cookie_preferences
416
+ (user_id, session_id, analytics_consent, marketing_consent,
417
+ personalization_consent, necessary_consent, preferences_updated, preference_source)
418
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
419
+ `).bind(
420
+ userId, null,
421
+ consentType === 'analytics' ? value : false,
422
+ consentType === 'marketing' ? value : false,
423
+ consentType === 'personalization' ? value : false,
424
+ true, // necessary_consent is always true
425
+ now, source
426
+ ).run();
427
+ }
428
+ }
429
+
430
+ /**
431
+ * Get cookie preferences for a user
432
+ * @param {string} userId - User ID
433
+ * @returns {Promise<object>} Cookie preferences
434
+ */
435
+ async getCookiePreferences(userId) {
436
+ const result = await this.db.prepare(`
437
+ SELECT * FROM cookie_preferences WHERE user_id = ?
438
+ `).bind(userId).first();
439
+
440
+ return result || {
441
+ analytics_consent: false,
442
+ marketing_consent: false,
443
+ personalization_consent: false,
444
+ necessary_consent: true
445
+ };
446
+ }
447
+
448
+ /**
449
+ * Record consent history for audit trail
450
+ * @param {string} consentId - Consent ID
451
+ * @param {string} action - Action (granted, revoked, updated)
452
+ * @param {object} previousState - Previous consent state
453
+ * @param {object} newState - New consent state
454
+ * @param {object} metadata - Metadata
455
+ */
456
+ async recordConsentHistory(consentId, action, previousState, newState, metadata) {
457
+ await this.db.prepare(`
458
+ INSERT INTO consent_history
459
+ (consent_id, action, previous_state, new_state, timestamp, ip_address, user_agent, reason)
460
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
461
+ `).bind(
462
+ consentId,
463
+ action,
464
+ JSON.stringify(previousState),
465
+ JSON.stringify(newState),
466
+ new Date().toISOString(),
467
+ metadata.ip_address || null,
468
+ metadata.user_agent || null,
469
+ metadata.reason || null
470
+ ).run();
471
+ }
472
+
473
+ /**
474
+ * Calculate expiration date for consent
475
+ * @param {string} consentType - Type of consent
476
+ * @returns {string|null} ISO date string or null
477
+ */
478
+ calculateExpiration(consentType) {
479
+ const expirationPeriods = {
480
+ 'marketing': 365 * 2, // 2 years
481
+ 'analytics': 365 * 1, // 1 year
482
+ 'personalization': 365 * 1, // 1 year
483
+ 'essential': null // No expiration
484
+ };
485
+
486
+ const days = expirationPeriods[consentType];
487
+ if (!days) {
488
+ return null;
489
+ }
490
+
491
+ const expiresAt = new Date();
492
+ expiresAt.setDate(expiresAt.getDate() + days);
493
+ return expiresAt.toISOString();
494
+ }
495
+
496
+ /**
497
+ * Generate unique consent ID
498
+ * @returns {string} Consent ID
499
+ */
500
+ generateConsentId() {
501
+ return `consent_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
502
+ }
503
+
504
+ /**
505
+ * Handle consent revocation (trigger data deletion if required)
506
+ * @param {string} userId - User ID
507
+ * @param {string} consentType - Type of consent revoked
508
+ */
509
+ async handleConsentRevocation(userId, consentType) {
510
+ // For marketing consent revocation, remove PII from marketing databases
511
+ if (consentType === 'marketing') {
512
+ // Remove user from marketing campaigns
513
+ await this.removeFromMarketingLists(userId);
514
+ }
515
+
516
+ // For analytics consent revocation, anonymize analytics data
517
+ if (consentType === 'analytics') {
518
+ // Anonymize user analytics data
519
+ await this.anonymizeAnalyticsData(userId);
520
+ }
521
+ }
522
+
523
+ /**
524
+ * Remove user from marketing lists
525
+ * @param {string} userId - User ID
526
+ */
527
+ async removeFromMarketingLists(userId) {
528
+ // Update user journeys to mark for marketing exclusion
529
+ await this.db.prepare(`
530
+ UPDATE user_journeys
531
+ SET marketing_consent = false
532
+ WHERE user_id = ?
533
+ `).bind(userId).run();
534
+ }
535
+
536
+ /**
537
+ * Anonymize analytics data for user
538
+ * @param {string} userId - User ID
539
+ */
540
+ async anonymizeAnalyticsData(userId) {
541
+ // Anonymize user_id in user_journeys (replace with hash)
542
+ const anonymizedId = `anon_${crypto.randomUUID()}`;
543
+
544
+ await this.db.prepare(`
545
+ UPDATE user_journeys
546
+ SET user_id = ?, anonymized = true
547
+ WHERE user_id = ?
548
+ `).bind(anonymizedId, userId).run();
549
+ }
550
+ }
551
+
552
+ // Global consent manager instance
553
+ let consentManager = null;
554
+ ```
555
+
556
+ ---
557
+
558
+ ## 👤 Data Rights Management
559
+
560
+ ### GDPR/LGPD/CCPA Data Rights Implementation
561
+
562
+ ```javascript
563
+ /**
564
+ * Data Rights Manager
565
+ * Handles GDPR/LGPD/CCPA data rights: access, deletion, portability, rectification
566
+ */
567
+ class DataRightsManager {
568
+ constructor(env) {
569
+ this.db = env.DB;
570
+ this.complianceConfig = {
571
+ gdpr: {
572
+ accessResponseTime: 30, // days
573
+ deletionResponseTime: 30, // days
574
+ portabilityResponseTime: 30 // days
575
+ },
576
+ lgpd: {
577
+ accessResponseTime: 15, // days
578
+ deletionResponseTime: 15, // days
579
+ portabilityResponseTime: 15 // days
580
+ },
581
+ ccpa: {
582
+ accessResponseTime: 45, // days
583
+ deletionResponseTime: 45, // days
584
+ optOutResponseTime: 10 // days
585
+ }
586
+ };
587
+ }
588
+
589
+ /**
590
+ * Submit data access request (GDPR Art. 15, LGPD Art. 18, CCPA)
591
+ * @param {string} userId - User ID
592
+ * @param {object} metadata - Request metadata
593
+ * @returns {Promise<string>} Request ID
594
+ */
595
+ async submitAccessRequest(userId, metadata = {}) {
596
+ const requestId = this.generateRequestId('access');
597
+
598
+ await this.db.prepare(`
599
+ INSERT INTO deletion_requests
600
+ (user_id, request_id, request_type, status, requested_at, ip_address, user_agent)
601
+ VALUES (?, ?, 'access', 'pending', ?, ?, ?)
602
+ `).bind(
603
+ userId,
604
+ requestId,
605
+ new Date().toISOString(),
606
+ metadata.ip_address || null,
607
+ metadata.user_agent || null
608
+ ).run();
609
+
610
+ return requestId;
611
+ }
612
+
613
+ /**
614
+ * Process data access request
615
+ * @param {string} requestId - Request ID
616
+ * @returns {Promise<object>} User data package
617
+ */
618
+ async processAccessRequest(requestId) {
619
+ const request = await this.db.prepare(`
620
+ SELECT * FROM deletion_requests WHERE request_id = ?
621
+ `).bind(requestId).first();
622
+
623
+ if (!request) {
624
+ throw new Error('Request not found');
625
+ }
626
+
627
+ if (request.status !== 'pending') {
628
+ throw new Error('Request already processed');
629
+ }
630
+
631
+ // Update status to in_progress
632
+ await this.db.prepare(`
633
+ UPDATE deletion_requests SET status = 'in_progress' WHERE request_id = ?
634
+ `).bind(requestId).run();
635
+
636
+ // Collect all user data
637
+ const userData = await this.collectUserData(request.user_id);
638
+
639
+ // Update status to completed
640
+ await this.db.prepare(`
641
+ UPDATE deletion_requests
642
+ SET status = 'completed', completed_at = ?, processed_by = 'system'
643
+ WHERE request_id = ?
644
+ `).bind(new Date().toISOString(), requestId).run();
645
+
646
+ return {
647
+ request_id: requestId,
648
+ user_id: request.user_id,
649
+ data_collected_at: new Date().toISOString(),
650
+ data: userData
651
+ };
652
+ }
653
+
654
+ /**
655
+ * Submit data deletion request (GDPR Art. 17, LGPD Art. 18, CCPA)
656
+ * @param {string} userId - User ID
657
+ * @param {string} reason - Reason for deletion (optional)
658
+ * @param {object} metadata - Request metadata
659
+ * @returns {Promise<string>} Request ID
660
+ */
661
+ async submitDeletionRequest(userId, reason = '', metadata = {}) {
662
+ const requestId = this.generateRequestId('deletion');
663
+
664
+ await this.db.prepare(`
665
+ INSERT INTO deletion_requests
666
+ (user_id, request_id, request_type, status, requested_at,
667
+ ip_address, user_agent, processing_notes)
668
+ VALUES (?, ?, 'deletion', 'pending', ?, ?, ?, ?)
669
+ `).bind(
670
+ userId,
671
+ requestId,
672
+ new Date().toISOString(),
673
+ metadata.ip_address || null,
674
+ metadata.user_agent || null,
675
+ reason
676
+ ).run();
677
+
678
+ return requestId;
679
+ }
680
+
681
+ /**
682
+ * Process data deletion request
683
+ * @param {string} requestId - Request ID
684
+ * @returns {Promise<object>} Deletion result
685
+ */
686
+ async processDeletionRequest(requestId) {
687
+ const request = await this.db.prepare(`
688
+ SELECT * FROM deletion_requests WHERE request_id = ?
689
+ `).bind(requestId).first();
690
+
691
+ if (!request) {
692
+ throw new Error('Request not found');
693
+ }
694
+
695
+ if (request.status !== 'pending') {
696
+ throw new Error('Request already processed');
697
+ }
698
+
699
+ // Update status to in_progress
700
+ await this.db.prepare(`
701
+ UPDATE deletion_requests SET status = 'in_progress' WHERE request_id = ?
702
+ `).bind(requestId).run();
703
+
704
+ // Perform deletion
705
+ const deletionResult = await this.deleteUserData(request.user_id);
706
+
707
+ // Update status to completed
708
+ await this.db.prepare(`
709
+ UPDATE deletion_requests
710
+ SET status = 'completed', completed_at = ?, processed_by = 'system',
711
+ processing_notes = ?
712
+ WHERE request_id = ?
713
+ `).bind(
714
+ new Date().toISOString(),
715
+ JSON.stringify(deletionResult),
716
+ requestId
717
+ ).run();
718
+
719
+ return {
720
+ request_id: requestId,
721
+ user_id: request.user_id,
722
+ deleted_at: new Date().toISOString(),
723
+ deletion_summary: deletionResult
724
+ };
725
+ }
726
+
727
+ /**
728
+ * Submit data portability request (GDPR Art. 20, LGPD Art. 18)
729
+ * @param {string} userId - User ID
730
+ * @param {object} metadata - Request metadata
731
+ * @returns {Promise<string>} Request ID
732
+ */
733
+ async submitPortabilityRequest(userId, metadata = {}) {
734
+ const requestId = this.generateRequestId('portability');
735
+
736
+ await this.db.prepare(`
737
+ INSERT INTO deletion_requests
738
+ (user_id, request_id, request_type, status, requested_at, ip_address, user_agent)
739
+ VALUES (?, ?, 'portability', 'pending', ?, ?, ?)
740
+ `).bind(
741
+ userId,
742
+ requestId,
743
+ new Date().toISOString(),
744
+ metadata.ip_address || null,
745
+ metadata.user_agent || null
746
+ ).run();
747
+
748
+ return requestId;
749
+ }
750
+
751
+ /**
752
+ * Process data portability request
753
+ * @param {string} requestId - Request ID
754
+ * @param {string} format - Export format (json, csv)
755
+ * @returns {Promise<object>} Portable data package
756
+ */
757
+ async processPortabilityRequest(requestId, format = 'json') {
758
+ const request = await this.db.prepare(`
759
+ SELECT * FROM deletion_requests WHERE request_id = ?
760
+ `).bind(requestId).first();
761
+
762
+ if (!request) {
763
+ throw new Error('Request not found');
764
+ }
765
+
766
+ if (request.status !== 'pending') {
767
+ throw new Error('Request already processed');
768
+ }
769
+
770
+ // Update status to in_progress
771
+ await this.db.prepare(`
772
+ UPDATE deletion_requests SET status = 'in_progress' WHERE request_id = ?
773
+ `).bind(requestId).run();
774
+
775
+ // Collect and format user data
776
+ const userData = await this.collectUserData(request.user_id);
777
+ const portableData = await this.formatPortableData(userData, format);
778
+
779
+ // Update status to completed
780
+ await this.db.prepare(`
781
+ UPDATE deletion_requests
782
+ SET status = 'completed', completed_at = ?, processed_by = 'system'
783
+ WHERE request_id = ?
784
+ `).bind(new Date().toISOString(), requestId).run();
785
+
786
+ return {
787
+ request_id: requestId,
788
+ user_id: request.user_id,
789
+ exported_at: new Date().toISOString(),
790
+ format: format,
791
+ data: portableData
792
+ };
793
+ }
794
+
795
+ /**
796
+ * Submit data rectification request (GDPR Art. 16, LGPD Art. 18)
797
+ * @param {string} userId - User ID
798
+ * @param {object} corrections - Data corrections
799
+ * @param {object} metadata - Request metadata
800
+ * @returns {Promise<string>} Request ID
801
+ */
802
+ async submitRectificationRequest(userId, corrections, metadata = {}) {
803
+ const requestId = this.generateRequestId('rectification');
804
+
805
+ await this.db.prepare(`
806
+ INSERT INTO deletion_requests
807
+ (user_id, request_id, request_type, status, requested_at,
808
+ ip_address, user_agent, processing_notes)
809
+ VALUES (?, ?, 'rectification', 'pending', ?, ?, ?)
810
+ `).bind(
811
+ userId,
812
+ requestId,
813
+ new Date().toISOString(),
814
+ metadata.ip_address || null,
815
+ metadata.user_agent || null,
816
+ JSON.stringify(corrections)
817
+ ).run();
818
+
819
+ return requestId;
820
+ }
821
+
822
+ /**
823
+ * Process data rectification request
824
+ * @param {string} requestId - Request ID
825
+ * @returns {Promise<object>} Rectification result
826
+ */
827
+ async processRectificationRequest(requestId) {
828
+ const request = await this.db.prepare(`
829
+ SELECT * FROM deletion_requests WHERE request_id = ?
830
+ `).bind(requestId).first();
831
+
832
+ if (!request) {
833
+ throw new Error('Request not found');
834
+ }
835
+
836
+ if (request.status !== 'pending') {
837
+ throw new Error('Request already processed');
838
+ }
839
+
840
+ const corrections = JSON.parse(request.processing_notes || '{}');
841
+
842
+ // Update status to in_progress
843
+ await this.db.prepare(`
844
+ UPDATE deletion_requests SET status = 'in_progress' WHERE request_id = ?
845
+ `).bind(requestId).run();
846
+
847
+ // Apply corrections
848
+ const rectificationResult = await this.applyDataCorrections(request.user_id, corrections);
849
+
850
+ // Update status to completed
851
+ await this.db.prepare(`
852
+ UPDATE deletion_requests
853
+ SET status = 'completed', completed_at = ?, processed_by = 'system',
854
+ processing_notes = ?
855
+ WHERE request_id = ?
856
+ `).bind(
857
+ new Date().toISOString(),
858
+ JSON.stringify(rectificationResult),
859
+ requestId
860
+ ).run();
861
+
862
+ return {
863
+ request_id: requestId,
864
+ user_id: request.user_id,
865
+ corrected_at: new Date().toISOString(),
866
+ corrections_applied: rectificationResult
867
+ };
868
+ }
869
+
870
+ /**
871
+ * Collect all user data from the system
872
+ * @param {string} userId - User ID
873
+ * @returns {Promise<object>} All user data
874
+ */
875
+ async collectUserData(userId) {
876
+ return {
877
+ user_profile: await this.getUserProfile(userId),
878
+ consent_records: await this.getUserConsents(userId),
879
+ cookie_preferences: await this.getUserCookiePreferences(userId),
880
+ user_journeys: await this.getUserJourneys(userId),
881
+ attribution_data: await this.getUserAttributionData(userId),
882
+ security_data: await this.getUserSecurityData(userId)
883
+ };
884
+ }
885
+
886
+ /**
887
+ * Get user profile data
888
+ * @param {string} userId - User ID
889
+ * @returns {Promise<Array>} User profile data
890
+ */
891
+ async getUserProfile(userId) {
892
+ const results = await this.db.prepare(`
893
+ SELECT * FROM user_profiles WHERE user_id = ?
894
+ `).bind(userId).all();
895
+
896
+ return results;
897
+ }
898
+
899
+ /**
900
+ * Get user consent records
901
+ * @param {string} userId - User ID
902
+ * @returns {Promise<Array>} Consent records
903
+ */
904
+ async getUserConsents(userId) {
905
+ const results = await this.db.prepare(`
906
+ SELECT * FROM consent_records WHERE user_id = ?
907
+ `).bind(userId).all();
908
+
909
+ return results;
910
+ }
911
+
912
+ /**
913
+ * Get user cookie preferences
914
+ * @param {string} userId - User ID
915
+ * @returns {Promise<object>} Cookie preferences
916
+ */
917
+ async getUserCookiePreferences(userId) {
918
+ const result = await this.db.prepare(`
919
+ SELECT * FROM cookie_preferences WHERE user_id = ?
920
+ `).bind(userId).first();
921
+
922
+ return result || {};
923
+ }
924
+
925
+ /**
926
+ * Get user journey data
927
+ * @param {string} userId - User ID
928
+ * @returns {Promise<Array>} User journeys
929
+ */
930
+ async getUserJourneys(userId) {
931
+ const results = await this.db.prepare(`
932
+ SELECT * FROM user_journeys WHERE user_id = ?
933
+ `).bind(userId).all();
934
+
935
+ return results;
936
+ }
937
+
938
+ /**
939
+ * Get user attribution data
940
+ * @param {string} userId - User ID
941
+ * @returns {Promise<Array>} Attribution data
942
+ */
943
+ async getUserAttributionData(userId) {
944
+ const results = await this.db.prepare(`
945
+ SELECT a.* FROM multi_touch_attribution a
946
+ INNER JOIN user_journeys j ON a.conversion_id = j.conversion_id
947
+ WHERE j.user_id = ?
948
+ `).bind(userId).all();
949
+
950
+ return results;
951
+ }
952
+
953
+ /**
954
+ * Get user security data (excluding sensitive data)
955
+ * @param {string} userId - User ID
956
+ * @returns {Promise<Array>} Security data
957
+ */
958
+ async getUserSecurityData(userId) {
959
+ // Return only non-sensitive security data
960
+ const results = await this.db.prepare(`
961
+ SELECT id, timestamp, log_type, action, blocked
962
+ FROM audit_logs
963
+ WHERE user_id = ?
964
+ `).bind(userId).all();
965
+
966
+ return results;
967
+ }
968
+
969
+ /**
970
+ * Delete all user data from the system
971
+ * @param {string} userId - User ID
972
+ * @returns {Promise<object>} Deletion summary
973
+ */
974
+ async deleteUserData(userId) {
975
+ const deletionSummary = {
976
+ tables: {},
977
+ deleted_at: new Date().toISOString()
978
+ };
979
+
980
+ // Delete from consent_records
981
+ const consentResult = await this.db.prepare(`
982
+ DELETE FROM consent_records WHERE user_id = ?
983
+ `).bind(userId).run();
984
+ deletionSummary.tables.consent_records = consentResult.meta.changes;
985
+
986
+ // Delete from cookie_preferences
987
+ const cookieResult = await this.db.prepare(`
988
+ DELETE FROM cookie_preferences WHERE user_id = ?
989
+ `).bind(userId).run();
990
+ deletionSummary.tables.cookie_preferences = cookieResult.meta.changes;
991
+
992
+ // Delete from user_journeys
993
+ const journeyResult = await this.db.prepare(`
994
+ DELETE FROM user_journeys WHERE user_id = ?
995
+ `).bind(userId).run();
996
+ deletionSummary.tables.user_journeys = journeyResult.meta.changes;
997
+
998
+ // Delete from multi_touch_attribution (via user_journeys conversion_id)
999
+ // This is handled by cascade delete in user_journeys
1000
+
1001
+ // Delete from user_profiles
1002
+ const profileResult = await this.db.prepare(`
1003
+ DELETE FROM user_profiles WHERE user_id = ?
1004
+ `).bind(userId).run();
1005
+ deletionSummary.tables.user_profiles = profileResult.meta.changes;
1006
+
1007
+ // Delete from ip_violations (if any)
1008
+ const violationsResult = await this.db.prepare(`
1009
+ DELETE FROM ip_violations WHERE user_id = ?
1010
+ `).bind(userId).run();
1011
+ deletionSummary.tables.ip_violations = violationsResult.meta.changes;
1012
+
1013
+ return deletionSummary;
1014
+ }
1015
+
1016
+ /**
1017
+ * Apply data corrections
1018
+ * @param {string} userId - User ID
1019
+ * @param {object} corrections - Data corrections
1020
+ * @returns {Promise<object>} Rectification summary
1021
+ */
1022
+ async applyDataCorrections(userId, corrections) {
1023
+ const rectificationSummary = {
1024
+ corrections: [],
1025
+ corrected_at: new Date().toISOString()
1026
+ };
1027
+
1028
+ // Apply corrections to user_profiles
1029
+ if (corrections.user_profile) {
1030
+ const profileUpdates = corrections.user_profile;
1031
+ const setClauses = Object.keys(profileUpdates).map(key => `${key} = ?`).join(', ');
1032
+ const values = Object.values(profileUpdates);
1033
+
1034
+ await this.db.prepare(`
1035
+ UPDATE user_profiles
1036
+ SET ${setClauses}
1037
+ WHERE user_id = ?
1038
+ `).bind(...values, userId).run();
1039
+
1040
+ rectificationSummary.corrections.push({
1041
+ table: 'user_profiles',
1042
+ fields: Object.keys(profileUpdates)
1043
+ });
1044
+ }
1045
+
1046
+ return rectificationSummary;
1047
+ }
1048
+
1049
+ /**
1050
+ * Format portable data in specified format
1051
+ * @param {object} userData - User data
1052
+ * @param {string} format - Export format
1053
+ * @returns {Promise<string>} Formatted data
1054
+ */
1055
+ async formatPortableData(userData, format) {
1056
+ if (format === 'json') {
1057
+ return JSON.stringify(userData, null, 2);
1058
+ } else if (format === 'csv') {
1059
+ return await this.convertToCSV(userData);
1060
+ }
1061
+
1062
+ return JSON.stringify(userData, null, 2);
1063
+ }
1064
+
1065
+ /**
1066
+ * Convert user data to CSV format
1067
+ * @param {object} userData - User data
1068
+ * @returns {Promise<string>} CSV data
1069
+ */
1070
+ async convertToCSV(userData) {
1071
+ // Flatten data and convert to CSV
1072
+ // This is a simplified implementation
1073
+ const rows = [];
1074
+
1075
+ for (const [table, data] of Object.entries(userData)) {
1076
+ if (Array.isArray(data) && data.length > 0) {
1077
+ const headers = Object.keys(data[0]).join(',');
1078
+ const values = data.map(row =>
1079
+ Object.values(row).map(val =>
1080
+ typeof val === 'string' ? `"${val}"` : val
1081
+ ).join(',')
1082
+ ).join('\n');
1083
+
1084
+ rows.push(`\n### ${table} ###\n`);
1085
+ rows.push(headers);
1086
+ rows.push(values);
1087
+ }
1088
+ }
1089
+
1090
+ return rows.join('\n');
1091
+ }
1092
+
1093
+ /**
1094
+ * Generate unique request ID
1095
+ * @param {string} type - Request type
1096
+ * @returns {string} Request ID
1097
+ */
1098
+ generateRequestId(type) {
1099
+ return `${type}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
1100
+ }
1101
+ }
1102
+
1103
+ // Global data rights manager instance
1104
+ let dataRightsManager = null;
1105
+ ```
1106
+
1107
+ ---
1108
+
1109
+ ## ⏱️ Data Retention Management
1110
+
1111
+ ### Automated Data Retention Policies
1112
+
1113
+ ```javascript
1114
+ /**
1115
+ * Data Retention Manager
1116
+ * Manages automated data retention and deletion policies
1117
+ */
1118
+ class DataRetentionManager {
1119
+ constructor(env) {
1120
+ this.db = env.DB;
1121
+ this.defaultRetentionPolicies = [
1122
+ {
1123
+ data_type: 'user_journeys',
1124
+ retention_period_days: 365 * 2, // 2 years
1125
+ legal_basis: 'legitimate_interest',
1126
+ policy_name: 'User Journey Retention',
1127
+ description: 'Retain user journey data for 2 years for attribution and analytics'
1128
+ },
1129
+ {
1130
+ data_type: 'consent_records',
1131
+ retention_period_days: 365 * 3, // 3 years
1132
+ legal_basis: 'legal_obligation',
1133
+ policy_name: 'Consent Record Retention',
1134
+ description: 'Retain consent records for 3 years for compliance audit'
1135
+ },
1136
+ {
1137
+ data_type: 'audit_logs',
1138
+ retention_period_days: 365 * 5, // 5 years
1139
+ legal_basis: 'legal_obligation',
1140
+ policy_name: 'Audit Log Retention',
1141
+ description: 'Retain audit logs for 5 years for security compliance'
1142
+ },
1143
+ {
1144
+ data_type: 'cookie_preferences',
1145
+ retention_period_days: 365 * 2, // 2 years
1146
+ legal_basis: 'consent',
1147
+ policy_name: 'Cookie Preferences Retention',
1148
+ description: 'Retain cookie preferences for 2 years'
1149
+ },
1150
+ {
1151
+ data_type: 'ip_violations',
1152
+ retention_period_days: 90, // 90 days
1153
+ legal_basis: 'legitimate_interest',
1154
+ policy_name: 'IP Violations Retention',
1155
+ description: 'Retain IP violation records for 90 days for security purposes'
1156
+ }
1157
+ ];
1158
+ }
1159
+
1160
+ /**
1161
+ * Initialize default retention policies
1162
+ */
1163
+ async initializePolicies() {
1164
+ for (const policy of this.defaultRetentionPolicies) {
1165
+ await this.db.prepare(`
1166
+ INSERT OR IGNORE INTO retention_policies
1167
+ (data_type, retention_period_days, legal_basis, policy_name, description)
1168
+ VALUES (?, ?, ?, ?, ?)
1169
+ `).bind(
1170
+ policy.data_type,
1171
+ policy.retention_period_days,
1172
+ policy.legal_basis,
1173
+ policy.policy_name,
1174
+ policy.description
1175
+ ).run();
1176
+ }
1177
+ }
1178
+
1179
+ /**
1180
+ * Execute data retention cleanup (run daily)
1181
+ * @returns {Promise<object>} Cleanup summary
1182
+ */
1183
+ async executeRetentionCleanup() {
1184
+ const cleanupSummary = {
1185
+ timestamp: new Date().toISOString(),
1186
+ policies_executed: [],
1187
+ total_records_deleted: 0,
1188
+ tables_cleaned: []
1189
+ };
1190
+
1191
+ // Get all active retention policies
1192
+ const policies = await this.db.prepare(`
1193
+ SELECT * FROM retention_policies
1194
+ `).all();
1195
+
1196
+ for (const policy of policies) {
1197
+ const deletionResult = await this.executePolicy(policy);
1198
+ cleanupSummary.policies_executed.push({
1199
+ policy_name: policy.policy_name,
1200
+ data_type: policy.data_type,
1201
+ records_deleted: deletionResult.deleted_count
1202
+ });
1203
+ cleanupSummary.total_records_deleted += deletionResult.deleted_count;
1204
+
1205
+ if (!cleanupSummary.tables_cleaned.includes(policy.data_type)) {
1206
+ cleanupSummary.tables_cleaned.push(policy.data_type);
1207
+ }
1208
+ }
1209
+
1210
+ return cleanupSummary;
1211
+ }
1212
+
1213
+ /**
1214
+ * Execute a single retention policy
1215
+ * @param {object} policy - Retention policy
1216
+ * @returns {Promise<object>} Deletion result
1217
+ */
1218
+ async executePolicy(policy) {
1219
+ const cutoffDate = new Date();
1220
+ cutoffDate.setDate(cutoffDate.getDate() - policy.retention_period_days);
1221
+ const cutoffISO = cutoffDate.toISOString();
1222
+
1223
+ let deletedCount = 0;
1224
+
1225
+ switch (policy.data_type) {
1226
+ case 'user_journeys':
1227
+ deletedCount = await this.deleteOldUserJourneys(cutoffISO);
1228
+ break;
1229
+
1230
+ case 'consent_records':
1231
+ deletedCount = await this.deleteOldConsentRecords(cutoffISO);
1232
+ break;
1233
+
1234
+ case 'audit_logs':
1235
+ deletedCount = await this.deleteOldAuditLogs(cutoffISO);
1236
+ break;
1237
+
1238
+ case 'cookie_preferences':
1239
+ deletedCount = await this.deleteOldCookiePreferences(cutoffISO);
1240
+ break;
1241
+
1242
+ case 'ip_violations':
1243
+ deletedCount = await this.deleteOldIPViolations(cutoffISO);
1244
+ break;
1245
+
1246
+ default:
1247
+ console.warn(`Unknown data type in retention policy: ${policy.data_type}`);
1248
+ }
1249
+
1250
+ return {
1251
+ data_type: policy.data_type,
1252
+ cutoff_date: cutoffISO,
1253
+ deleted_count: deletedCount
1254
+ };
1255
+ }
1256
+
1257
+ /**
1258
+ * Delete old user journeys
1259
+ * @param {string} cutoffDate - Cutoff date ISO string
1260
+ * @returns {Promise<number>} Number of deleted records
1261
+ */
1262
+ async deleteOldUserJourneys(cutoffDate) {
1263
+ const result = await this.db.prepare(`
1264
+ DELETE FROM user_journeys
1265
+ WHERE created_at < ? AND archived = 0
1266
+ `).bind(cutoffDate).run();
1267
+
1268
+ return result.meta.changes || 0;
1269
+ }
1270
+
1271
+ /**
1272
+ * Delete old consent records (keep only consent history)
1273
+ * @param {string} cutoffDate - Cutoff date ISO string
1274
+ * @returns {Promise<number>} Number of deleted records
1275
+ */
1276
+ async deleteOldConsentRecords(cutoffDate) {
1277
+ // Only delete old consent_records, keep consent_history
1278
+ const result = await this.db.prepare(`
1279
+ DELETE FROM consent_records
1280
+ WHERE timestamp < ? AND consent_given = false
1281
+ `).bind(cutoffDate).run();
1282
+
1283
+ return result.meta.changes || 0;
1284
+ }
1285
+
1286
+ /**
1287
+ * Delete old audit logs
1288
+ * @param {string} cutoffDate - Cutoff date ISO string
1289
+ * @returns {Promise<number>} Number of deleted records
1290
+ */
1291
+ async deleteOldAuditLogs(cutoffDate) {
1292
+ const result = await this.db.prepare(`
1293
+ DELETE FROM audit_logs
1294
+ WHERE timestamp < ? AND severity != 'CRITICAL'
1295
+ `).bind(cutoffDate).run();
1296
+
1297
+ return result.meta.changes || 0;
1298
+ }
1299
+
1300
+ /**
1301
+ * Delete old cookie preferences
1302
+ * @param {string} cutoffDate - Cutoff date ISO string
1303
+ * @returns {Promise<number>} Number of deleted records
1304
+ */
1305
+ async deleteOldCookiePreferences(cutoffDate) {
1306
+ const result = await this.db.prepare(`
1307
+ DELETE FROM cookie_preferences
1308
+ WHERE preferences_updated < ?
1309
+ `).bind(cutoffDate).run();
1310
+
1311
+ return result.meta.changes || 0;
1312
+ }
1313
+
1314
+ /**
1315
+ * Delete old IP violation records
1316
+ * @param {string} cutoffDate - Cutoff date ISO string
1317
+ * @returns {Promise<number>} Number of deleted records
1318
+ */
1319
+ async deleteOldIPViolations(cutoffDate) {
1320
+ const result = await this.db.prepare(`
1321
+ DELETE FROM ip_violations
1322
+ WHERE timestamp < ?
1323
+ `).bind(cutoffDate).run();
1324
+
1325
+ return result.meta.changes || 0;
1326
+ }
1327
+
1328
+ /**
1329
+ * Get retention policy statistics
1330
+ * @returns {Promise<object>} Retention statistics
1331
+ */
1332
+ async getRetentionStats() {
1333
+ const policies = await this.db.prepare(`
1334
+ SELECT * FROM retention_policies
1335
+ `).all();
1336
+
1337
+ const stats = {
1338
+ policies: policies.length,
1339
+ data_types: {},
1340
+ total_retention_days: 0
1341
+ };
1342
+
1343
+ for (const policy of policies) {
1344
+ stats.data_types[policy.data_type] = policy.retention_period_days;
1345
+ stats.total_retention_days += policy.retention_period_days;
1346
+ }
1347
+
1348
+ // Count records in each table
1349
+ stats.record_counts = {
1350
+ user_journeys: await this.countRecords('user_journeys'),
1351
+ consent_records: await this.countRecords('consent_records'),
1352
+ audit_logs: await this.countRecords('audit_logs'),
1353
+ cookie_preferences: await this.countRecords('cookie_preferences'),
1354
+ ip_violations: await this.countRecords('ip_violations')
1355
+ };
1356
+
1357
+ return stats;
1358
+ }
1359
+
1360
+ /**
1361
+ * Count records in a table
1362
+ * @param {string} tableName - Table name
1363
+ * @returns {Promise<number>} Record count
1364
+ */
1365
+ async countRecords(tableName) {
1366
+ const result = await this.db.prepare(`
1367
+ SELECT COUNT(*) as count FROM ${tableName}
1368
+ `).first();
1369
+
1370
+ return result ? result.count : 0;
1371
+ }
1372
+ }
1373
+
1374
+ // Global data retention manager instance
1375
+ let dataRetentionManager = null;
1376
+ ```
1377
+
1378
+ ---
1379
+
1380
+ ## 🎯 Compliance Audit Trail
1381
+
1382
+ ### Comprehensive Audit Logging
1383
+
1384
+ ```javascript
1385
+ /**
1386
+ * Compliance Audit Logger
1387
+ * Records all compliance-related activities for audit purposes
1388
+ */
1389
+ class ComplianceAuditLogger {
1390
+ constructor(env) {
1391
+ this.db = env.DB;
1392
+ }
1393
+
1394
+ /**
1395
+ * Log compliance activity
1396
+ * @param {string} userId - User ID (optional)
1397
+ * @param {string} action - Action performed
1398
+ * @param {string} category - Category (consent, data_rights, retention, etc.)
1399
+ * @param {object} details - Action details
1400
+ * @param {object} metadata - Metadata (IP, user-agent)
1401
+ */
1402
+ async logActivity(userId, action, category, details, metadata = {}) {
1403
+ await this.db.prepare(`
1404
+ INSERT INTO audit_logs
1405
+ (timestamp, user_id, log_type, action, details, ip_address, user_agent)
1406
+ VALUES (?, ?, ?, ?, ?, ?, ?)
1407
+ `).bind(
1408
+ new Date().toISOString(),
1409
+ userId || null,
1410
+ category,
1411
+ action,
1412
+ JSON.stringify(details),
1413
+ metadata.ip_address || null,
1414
+ metadata.user_agent || null
1415
+ ).run();
1416
+ }
1417
+
1418
+ /**
1419
+ * Log consent activity
1420
+ * @param {string} userId - User ID
1421
+ * @param {string} action - Action (granted, revoked, updated)
1422
+ * @param {string} consentType - Consent type
1423
+ * @param {object} details - Additional details
1424
+ * @param {object} metadata - Metadata
1425
+ */
1426
+ async logConsentActivity(userId, action, consentType, details, metadata) {
1427
+ await this.logActivity(
1428
+ userId,
1429
+ `consent_${action}`,
1430
+ 'consent',
1431
+ {
1432
+ consent_type: consentType,
1433
+ ...details
1434
+ },
1435
+ metadata
1436
+ );
1437
+ }
1438
+
1439
+ /**
1440
+ * Log data rights activity
1441
+ * @param {string} userId - User ID
1442
+ * @param {string} action - Action (access, deletion, portability, rectification)
1443
+ * @param {string} requestId - Request ID
1444
+ * @param {object} details - Additional details
1445
+ * @param {object} metadata - Metadata
1446
+ */
1447
+ async logDataRightsActivity(userId, action, requestId, details, metadata) {
1448
+ await this.logActivity(
1449
+ userId,
1450
+ `data_rights_${action}`,
1451
+ 'data_rights',
1452
+ {
1453
+ request_id: requestId,
1454
+ action_type: action,
1455
+ ...details
1456
+ },
1457
+ metadata
1458
+ );
1459
+ }
1460
+
1461
+ /**
1462
+ * Log retention activity
1463
+ * @param {string} action - Action (cleanup, policy_update)
1464
+ * @param {object} details - Policy details
1465
+ */
1466
+ async logRetentionActivity(action, details) {
1467
+ await this.logActivity(
1468
+ null,
1469
+ `retention_${action}`,
1470
+ 'retention',
1471
+ details,
1472
+ {}
1473
+ );
1474
+ }
1475
+
1476
+ /**
1477
+ * Get audit logs for a user
1478
+ * @param {string} userId - User ID
1479
+ * @param {number} limit - Limit results
1480
+ * @returns {Promise<Array>} Audit logs
1481
+ */
1482
+ async getUserAuditLogs(userId, limit = 100) {
1483
+ const results = await this.db.prepare(`
1484
+ SELECT * FROM audit_logs
1485
+ WHERE user_id = ?
1486
+ ORDER BY timestamp DESC
1487
+ LIMIT ?
1488
+ `).bind(userId, limit).all();
1489
+
1490
+ return results;
1491
+ }
1492
+
1493
+ /**
1494
+ * Get audit logs by category
1495
+ * @param {string} category - Log category
1496
+ * @param {number} limit - Limit results
1497
+ * @returns {Promise<Array>} Audit logs
1498
+ */
1499
+ async getAuditLogsByCategory(category, limit = 100) {
1500
+ const results = await this.db.prepare(`
1501
+ SELECT * FROM audit_logs
1502
+ WHERE log_type = ?
1503
+ ORDER BY timestamp DESC
1504
+ LIMIT ?
1505
+ `).bind(category, limit).all();
1506
+
1507
+ return results;
1508
+ }
1509
+
1510
+ /**
1511
+ * Get recent audit logs
1512
+ * @param {number} limit - Limit results
1513
+ * @returns {Promise<Array>} Recent audit logs
1514
+ */
1515
+ async getRecentAuditLogs(limit = 50) {
1516
+ const results = await this.db.prepare(`
1517
+ SELECT * FROM audit_logs
1518
+ ORDER BY timestamp DESC
1519
+ LIMIT ?
1520
+ `).bind(limit).all();
1521
+
1522
+ return results;
1523
+ }
1524
+ }
1525
+
1526
+ // Global compliance audit logger instance
1527
+ let complianceAuditLogger = null;
1528
+ ```
1529
+
1530
+ ---
1531
+
1532
+ ## 🔗 Worker API Endpoints
1533
+
1534
+ ### Compliance Management Endpoints
1535
+
1536
+ ```javascript
1537
+ /**
1538
+ * Compliance Management Endpoints
1539
+ */
1540
+ export default {
1541
+ async fetch(request, env, ctx) {
1542
+ // Initialize components
1543
+ if (!consentManager) consentManager = new ConsentManager(env);
1544
+ if (!dataRightsManager) dataRightsManager = new DataRightsManager(env);
1545
+ if (!dataRetentionManager) {
1546
+ dataRetentionManager = new DataRetentionManager(env);
1547
+ await dataRetentionManager.initializePolicies();
1548
+ }
1549
+ if (!complianceAuditLogger) complianceAuditLogger = new ComplianceAuditLogger(env);
1550
+
1551
+ const url = new URL(request.url);
1552
+ const path = url.pathname;
1553
+ const method = request.method;
1554
+
1555
+ // Consent management endpoints
1556
+ if (path === '/api/compliance/consent/grant' && method === 'POST') {
1557
+ return handleGrantConsent(request, env);
1558
+ }
1559
+
1560
+ if (path === '/api/compliance/consent/revoke' && method === 'POST') {
1561
+ return handleRevokeConsent(request, env);
1562
+ }
1563
+
1564
+ if (path === '/api/compliance/consent/check' && method === 'GET') {
1565
+ return handleCheckConsent(request, env);
1566
+ }
1567
+
1568
+ if (path === '/api/compliance/consent/preferences' && method === 'GET') {
1569
+ return handleGetCookiePreferences(request, env);
1570
+ }
1571
+
1572
+ if (path === '/api/compliance/consent/preferences' && method === 'POST') {
1573
+ return handleUpdateCookiePreferences(request, env);
1574
+ }
1575
+
1576
+ // Data rights endpoints
1577
+ if (path === '/api/compliance/data-rights/access' && method === 'POST') {
1578
+ return handleSubmitAccessRequest(request, env);
1579
+ }
1580
+
1581
+ if (path === '/api/compliance/data-rights/deletion' && method === 'POST') {
1582
+ return handleSubmitDeletionRequest(request, env);
1583
+ }
1584
+
1585
+ if (path === '/api/compliance/data-rights/portability' && method === 'POST') {
1586
+ return handleSubmitPortabilityRequest(request, env);
1587
+ }
1588
+
1589
+ if (path === '/api/compliance/data-rights/rectification' && method === 'POST') {
1590
+ return handleSubmitRectificationRequest(request, env);
1591
+ }
1592
+
1593
+ if (path === '/api/compliance/data-rights/request' && method === 'GET') {
1594
+ return handleGetDataRightsRequest(request, env);
1595
+ }
1596
+
1597
+ if (path === '/api/compliance/data-rights/process' && method === 'POST') {
1598
+ return handleProcessDataRightsRequest(request, env);
1599
+ }
1600
+
1601
+ // Retention management endpoints
1602
+ if (path === '/api/compliance/retention/cleanup' && method === 'POST') {
1603
+ return handleRetentionCleanup(request, env);
1604
+ }
1605
+
1606
+ if (path === '/api/compliance/retention/stats' && method === 'GET') {
1607
+ return handleRetentionStats(request, env);
1608
+ }
1609
+
1610
+ // Audit endpoints
1611
+ if (path === '/api/compliance/audit/user' && method === 'GET') {
1612
+ return handleGetUserAuditLogs(request, env);
1613
+ }
1614
+
1615
+ if (path === '/api/compliance/audit/recent' && method === 'GET') {
1616
+ return handleGetRecentAuditLogs(request, env);
1617
+ }
1618
+
1619
+ // Policy endpoints
1620
+ if (path === '/api/compliance/policy/current' && method === 'GET') {
1621
+ return handleGetCurrentPolicy(request, env);
1622
+ }
1623
+
1624
+ return new Response('Not Found', { status: 404 });
1625
+ }
1626
+ };
1627
+
1628
+ /**
1629
+ * Handle /api/compliance/consent/grant
1630
+ */
1631
+ async function handleGrantConsent(request, env) {
1632
+ try {
1633
+ const body = await request.json();
1634
+ const { user_id, consent_type } = body;
1635
+
1636
+ if (!user_id || !consent_type) {
1637
+ return new Response(JSON.stringify({
1638
+ success: false,
1639
+ error: 'Missing required fields: user_id, consent_type'
1640
+ }), {
1641
+ status: 400,
1642
+ headers: { 'Content-Type': 'application/json' }
1643
+ });
1644
+ }
1645
+
1646
+ const metadata = {
1647
+ ip_address: request.headers.get('CF-Connecting-IP'),
1648
+ user_agent: request.headers.get('User-Agent'),
1649
+ source: body.source || 'api'
1650
+ };
1651
+
1652
+ const consent = await consentManager.grantConsent(user_id, consent_type, metadata);
1653
+
1654
+ await complianceAuditLogger.logConsentActivity(
1655
+ user_id,
1656
+ 'granted',
1657
+ consent_type,
1658
+ { consent_id: consent.consent_id },
1659
+ metadata
1660
+ );
1661
+
1662
+ return new Response(JSON.stringify({
1663
+ success: true,
1664
+ data: consent
1665
+ }), {
1666
+ headers: { 'Content-Type': 'application/json' }
1667
+ });
1668
+ } catch (error) {
1669
+ return new Response(JSON.stringify({
1670
+ success: false,
1671
+ error: error.message
1672
+ }), {
1673
+ status: 500,
1674
+ headers: { 'Content-Type': 'application/json' }
1675
+ });
1676
+ }
1677
+ }
1678
+
1679
+ /**
1680
+ * Handle /api/compliance/consent/revoke
1681
+ */
1682
+ async function handleRevokeConsent(request, env) {
1683
+ try {
1684
+ const body = await request.json();
1685
+ const { user_id, consent_type } = body;
1686
+
1687
+ if (!user_id || !consent_type) {
1688
+ return new Response(JSON.stringify({
1689
+ success: false,
1690
+ error: 'Missing required fields: user_id, consent_type'
1691
+ }), {
1692
+ status: 400,
1693
+ headers: { 'Content-Type': 'application/json' }
1694
+ });
1695
+ }
1696
+
1697
+ const metadata = {
1698
+ ip_address: request.headers.get('CF-Connecting-IP'),
1699
+ user_agent: request.headers.get('User-Agent'),
1700
+ source: body.source || 'api'
1701
+ };
1702
+
1703
+ const consent = await consentManager.revokeConsent(user_id, consent_type, metadata);
1704
+
1705
+ await complianceAuditLogger.logConsentActivity(
1706
+ user_id,
1707
+ 'revoked',
1708
+ consent_type,
1709
+ { consent_id: consent.consent_id },
1710
+ metadata
1711
+ );
1712
+
1713
+ return new Response(JSON.stringify({
1714
+ success: true,
1715
+ data: consent
1716
+ }), {
1717
+ headers: { 'Content-Type': 'application/json' }
1718
+ });
1719
+ } catch (error) {
1720
+ return new Response(JSON.stringify({
1721
+ success: false,
1722
+ error: error.message
1723
+ }), {
1724
+ status: 500,
1725
+ headers: { 'Content-Type': 'application/json' }
1726
+ });
1727
+ }
1728
+ }
1729
+
1730
+ /**
1731
+ * Handle /api/compliance/consent/check
1732
+ */
1733
+ async function handleCheckConsent(request, env) {
1734
+ const url = new URL(request.url);
1735
+ const user_id = url.searchParams.get('user_id');
1736
+ const consent_type = url.searchParams.get('consent_type');
1737
+
1738
+ if (!user_id || !consent_type) {
1739
+ return new Response(JSON.stringify({
1740
+ success: false,
1741
+ error: 'Missing required parameters: user_id, consent_type'
1742
+ }), {
1743
+ status: 400,
1744
+ headers: { 'Content-Type': 'application/json' }
1745
+ });
1746
+ }
1747
+
1748
+ const hasConsent = await consentManager.hasValidConsent(user_id, consent_type);
1749
+
1750
+ return new Response(JSON.stringify({
1751
+ success: true,
1752
+ data: {
1753
+ user_id,
1754
+ consent_type,
1755
+ has_valid_consent: hasConsent
1756
+ }
1757
+ }), {
1758
+ headers: { 'Content-Type': 'application/json' }
1759
+ });
1760
+ }
1761
+
1762
+ /**
1763
+ * Handle /api/compliance/data-rights/deletion
1764
+ */
1765
+ async function handleSubmitDeletionRequest(request, env) {
1766
+ try {
1767
+ const body = await request.json();
1768
+ const { user_id, reason } = body;
1769
+
1770
+ if (!user_id) {
1771
+ return new Response(JSON.stringify({
1772
+ success: false,
1773
+ error: 'Missing required field: user_id'
1774
+ }), {
1775
+ status: 400,
1776
+ headers: { 'Content-Type': 'application/json' }
1777
+ });
1778
+ }
1779
+
1780
+ const metadata = {
1781
+ ip_address: request.headers.get('CF-Connecting-IP'),
1782
+ user_agent: request.headers.get('User-Agent')
1783
+ };
1784
+
1785
+ const requestId = await dataRightsManager.submitDeletionRequest(user_id, reason, metadata);
1786
+
1787
+ await complianceAuditLogger.logDataRightsActivity(
1788
+ user_id,
1789
+ 'deletion',
1790
+ requestId,
1791
+ { reason },
1792
+ metadata
1793
+ );
1794
+
1795
+ return new Response(JSON.stringify({
1796
+ success: true,
1797
+ data: {
1798
+ request_id: requestId,
1799
+ status: 'pending',
1800
+ message: 'Deletion request submitted. Processing will begin shortly.'
1801
+ }
1802
+ }), {
1803
+ headers: { 'Content-Type': 'application/json' }
1804
+ });
1805
+ } catch (error) {
1806
+ return new Response(JSON.stringify({
1807
+ success: false,
1808
+ error: error.message
1809
+ }), {
1810
+ status: 500,
1811
+ headers: { 'Content-Type': 'application/json' }
1812
+ });
1813
+ }
1814
+ }
1815
+
1816
+ /**
1817
+ * Handle /api/compliance/data-rights/process
1818
+ */
1819
+ async function handleProcessDataRightsRequest(request, env) {
1820
+ try {
1821
+ const body = await request.json();
1822
+ const { request_id, format } = body;
1823
+
1824
+ if (!request_id) {
1825
+ return new Response(JSON.stringify({
1826
+ success: false,
1827
+ error: 'Missing required field: request_id'
1828
+ }), {
1829
+ status: 400,
1830
+ headers: { 'Content-Type': 'application/json' }
1831
+ });
1832
+ }
1833
+
1834
+ // Get request details
1835
+ const requestDetails = await env.DB.prepare(`
1836
+ SELECT * FROM deletion_requests WHERE request_id = ?
1837
+ `).bind(request_id).first();
1838
+
1839
+ if (!requestDetails) {
1840
+ return new Response(JSON.stringify({
1841
+ success: false,
1842
+ error: 'Request not found'
1843
+ }), {
1844
+ status: 404,
1845
+ headers: { 'Content-Type': 'application/json' }
1846
+ });
1847
+ }
1848
+
1849
+ let result;
1850
+ switch (requestDetails.request_type) {
1851
+ case 'access':
1852
+ result = await dataRightsManager.processAccessRequest(request_id);
1853
+ break;
1854
+ case 'deletion':
1855
+ result = await dataRightsManager.processDeletionRequest(request_id);
1856
+ break;
1857
+ case 'portability':
1858
+ result = await dataRightsManager.processPortabilityRequest(request_id, format);
1859
+ break;
1860
+ case 'rectification':
1861
+ result = await dataRightsManager.processRectificationRequest(request_id);
1862
+ break;
1863
+ default:
1864
+ return new Response(JSON.stringify({
1865
+ success: false,
1866
+ error: 'Unknown request type'
1867
+ }), {
1868
+ status: 400,
1869
+ headers: { 'Content-Type': 'application/json' }
1870
+ });
1871
+ }
1872
+
1873
+ return new Response(JSON.stringify({
1874
+ success: true,
1875
+ data: result
1876
+ }), {
1877
+ headers: { 'Content-Type': 'application/json' }
1878
+ });
1879
+ } catch (error) {
1880
+ return new Response(JSON.stringify({
1881
+ success: false,
1882
+ error: error.message
1883
+ }), {
1884
+ status: 500,
1885
+ headers: { 'Content-Type': 'application/json' }
1886
+ });
1887
+ }
1888
+ }
1889
+
1890
+ /**
1891
+ * Handle /api/compliance/retention/cleanup
1892
+ */
1893
+ async function handleRetentionCleanup(request, env) {
1894
+ try {
1895
+ const result = await dataRetentionManager.executeRetentionCleanup();
1896
+
1897
+ await complianceAuditLogger.logRetentionActivity(
1898
+ 'cleanup',
1899
+ {
1900
+ total_records_deleted: result.total_records_deleted,
1901
+ tables_cleaned: result.tables_cleaned
1902
+ }
1903
+ );
1904
+
1905
+ return new Response(JSON.stringify({
1906
+ success: true,
1907
+ data: result
1908
+ }), {
1909
+ headers: { 'Content-Type': 'application/json' }
1910
+ });
1911
+ } catch (error) {
1912
+ return new Response(JSON.stringify({
1913
+ success: false,
1914
+ error: error.message
1915
+ }), {
1916
+ status: 500,
1917
+ headers: { 'Content-Type': 'application/json' }
1918
+ });
1919
+ }
1920
+ }
1921
+
1922
+ /**
1923
+ * Handle /api/compliance/retention/stats
1924
+ */
1925
+ async function handleRetentionStats(request, env) {
1926
+ const stats = await dataRetentionManager.getRetentionStats();
1927
+
1928
+ return new Response(JSON.stringify({
1929
+ success: true,
1930
+ data: stats
1931
+ }), {
1932
+ headers: { 'Content-Type': 'application/json' }
1933
+ });
1934
+ }
1935
+
1936
+ /**
1937
+ * Handle /api/compliance/audit/user
1938
+ */
1939
+ async function handleGetUserAuditLogs(request, env) {
1940
+ const url = new URL(request.url);
1941
+ const user_id = url.searchParams.get('user_id');
1942
+ const limit = parseInt(url.searchParams.get('limit') || '100');
1943
+
1944
+ if (!user_id) {
1945
+ return new Response(JSON.stringify({
1946
+ success: false,
1947
+ error: 'Missing required parameter: user_id'
1948
+ }), {
1949
+ status: 400,
1950
+ headers: { 'Content-Type': 'application/json' }
1951
+ });
1952
+ }
1953
+
1954
+ const logs = await complianceAuditLogger.getUserAuditLogs(user_id, limit);
1955
+
1956
+ return new Response(JSON.stringify({
1957
+ success: true,
1958
+ data: logs
1959
+ }), {
1960
+ headers: { 'Content-Type': 'application/json' }
1961
+ });
1962
+ }
1963
+
1964
+ /**
1965
+ * Handle /api/compliance/audit/recent
1966
+ */
1967
+ async function handleGetRecentAuditLogs(request, env) {
1968
+ const url = new URL(request.url);
1969
+ const limit = parseInt(url.searchParams.get('limit') || '50');
1970
+
1971
+ const logs = await complianceAuditLogger.getRecentAuditLogs(limit);
1972
+
1973
+ return new Response(JSON.stringify({
1974
+ success: true,
1975
+ data: logs
1976
+ }), {
1977
+ headers: { 'Content-Type': 'application/json' }
1978
+ });
1979
+ }
1980
+
1981
+ /**
1982
+ * Handle /api/compliance/policy/current
1983
+ */
1984
+ async function handleGetCurrentPolicy(request, env) {
1985
+ const policy = await env.DB.prepare(`
1986
+ SELECT * FROM consent_policy_versions
1987
+ ORDER BY effective_date DESC
1988
+ LIMIT 1
1989
+ `).first();
1990
+
1991
+ return new Response(JSON.stringify({
1992
+ success: true,
1993
+ data: policy
1994
+ }), {
1995
+ headers: { 'Content-Type': 'application/json' }
1996
+ });
1997
+ }
1998
+ ```
1999
+
2000
+ ---
2001
+
2002
+ ## 📋 Resumo de Implementação
2003
+
2004
+ ### Componentes Criados
2005
+
2006
+ 1. **ConsentManager** - Gestão completa de consentimento (GDPR, LGPD, CCPA)
2007
+ 2. **DataRightsManager** - Implementação de todos os direitos dos titulares
2008
+ 3. **DataRetentionManager** - Políticas de retenção automatizadas
2009
+ 4. **ComplianceAuditLogger** - Trilhas de auditoria completas
2010
+
2011
+ ### Endpoints de Compliance
2012
+
2013
+ | Endpoint | Método | Descrição |
2014
+ |----------|--------|-----------|
2015
+ | `/api/compliance/consent/grant` | POST | Conceder consentimento |
2016
+ | `/api/compliance/consent/revoke` | POST | Revogar consentimento |
2017
+ | `/api/compliance/consent/check` | GET | Verificar consentimento válido |
2018
+ | `/api/compliance/consent/preferences` | GET/POST | Gerenciar preferências de cookies |
2019
+ | `/api/compliance/data-rights/access` | POST | Solicitar acesso aos dados |
2020
+ | `/api/compliance/data-rights/deletion` | POST | Solicitar exclusão de dados |
2021
+ | `/api/compliance/data-rights/portability` | POST | Solicitar portabilidade de dados |
2022
+ | `/api/compliance/data-rights/rectification` | POST | Solicitar correção de dados |
2023
+ | `/api/compliance/data-rights/process` | POST | Processar solicitação de direitos |
2024
+ | `/api/compliance/retention/cleanup` | POST | Executar limpeza de retenção |
2025
+ | `/api/compliance/retention/stats` | GET | Estatísticas de retenção |
2026
+ | `/api/compliance/audit/user` | GET | Logs de auditoria por usuário |
2027
+ | `/api/compliance/audit/recent` | GET | Logs de auditoria recentes |
2028
+ | `/api/compliance/policy/current` | GET | Política de consentimento atual |
2029
+
2030
+ ### Funcionalidades de Compliance
2031
+
2032
+ - **GDPR Compliance**: Todos os requisitos da Regulamentação Geral de Proteção de Dados (UE)
2033
+ - **LGPD Compliance**: Todos os requisitos da Lei Geral de Proteção de Dados (Brasil)
2034
+ - **CCPA Compliance**: Todos os requisitos da California Consumer Privacy Act (EUA)
2035
+ - **Consent Management**: Sistema completo de gestão de consentimento com histórico
2036
+ - **Data Rights**: Acesso, exclusão, portabilidade e correção de dados
2037
+ - **Data Retention**: Políticas automatizadas de retenção e exclusão
2038
+ - **Audit Trails**: Trilhas de auditoria completas para compliance
2039
+
2040
+ ---
2041
+
2042
+ ## 🔗 Integração com Outros Agentes
2043
+
2044
+ - **security-enterprise-agent.md**: Usa encryption de PII para LGPD/GDPR
2045
+ - **attribution-agent.md**: Respeita consentimento para analytics e marketing
2046
+ - **master-orchestrator.md**: Implementa middleware de consentimento antes de tracking
2047
+
2048
+ ---
2049
+
2050
+ ## ✅ Checklist de Implementação
2051
+
2052
+ - [x] Implementar ConsentManager com grant/revoke/check
2053
+ - [x] Implementar DataRightsManager (access, deletion, portability, rectification)
2054
+ - [x] Implementar DataRetentionManager com políticas automatizadas
2055
+ - [x] Implementar ComplianceAuditLogger com trilhas completas
2056
+ - [x] Criar D1 schemas para consent_records, consent_history, cookie_preferences
2057
+ - [x] Criar D1 schemas para deletion_requests, retention_policies
2058
+ - [x] Criar endpoints de API para todas as funcionalidades de compliance
2059
+ - [x] Implementar GDPR compliance (Art. 15, 16, 17, 20)
2060
+ - [x] Implementar LGPD compliance (Art. 18)
2061
+ - [x] Implementar CCPA compliance (access, deletion, opt-out)
2062
+ - [x] Implementar cookie preferences management
2063
+ - [x] Implementar data retention policies automatizadas
2064
+ - [x] Implementar audit trails para todas as atividades de compliance
2065
+
2066
+ ---
2067
+
2068
+ ## 📚 Referências
2069
+
2070
+ - [GDPR Official Text](https://gdpr-info.eu/)
2071
+ - [LGPD Texto Completo](https://www.planalto.gov.br/ccivil_03/_ato2015-2018/2018/lei/l13709.htm)
2072
+ - [CCPA Official Text](https://leginfo.legislature.ca.gov/faces/codes_displayText.xhtml?lawCode=CIV&sectionId=1798.100)
2073
+ - [IAB Europe Transparency & Consent Framework](https://iabeurope.eu/transparency-consent-framework/)
2074
+
2075
+ ---
2076
+
2077
+ *Compliance Enterprise Agent v1.0.0 - CDP Edge Quantum Tier*