cdp-edge 2.0.0 → 2.0.1

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.
@@ -32,8 +32,7 @@ function printBanner() {
32
32
  console.log(chalk.cyan('╚██████╗██████╔╝██║ ███████╗██████╔╝╚██████╔╝███████╗'));
33
33
  console.log(chalk.cyan(' ╚═════╝╚═════╝ ╚═╝ ╚══════╝╚═════╝ ╚═════╝╚══════╝'));
34
34
  console.log('');
35
- console.log(chalk.gray(' Customer Data Platform on the Edge · Quantum Tracking · Cloudflare Native'));
36
- console.log(chalk.gray(` Installer v2.0.0`));
35
+ console.log(chalk.gray(' Customer Data Platform on the Edge · Global Edge Tracking · v2.0.1'));
37
36
  console.log('');
38
37
  console.log(chalk.gray('═'.repeat(68)));
39
38
  console.log('');
@@ -19,8 +19,7 @@ function printBanner() {
19
19
  console.log(chalk.cyan('╚██████╗██████╔╝██║ ███████╗██████╔╝╚██████╔╝███████╗'));
20
20
  console.log(chalk.cyan(' ╚═════╝╚═════╝ ╚═╝ ╚══════╝╚═════╝ ╚═════╝╚══════╝'));
21
21
  console.log('');
22
- console.log(chalk.gray(' Customer Data Platform on the Edge · Quantum Tracking · Cloudflare Native'));
23
- console.log(chalk.gray(' Setup Wizard v2.0.0'));
22
+ console.log(chalk.gray(' Customer Data Platform on the Edge · Global Edge Tracking · v2.0.1'));
24
23
  console.log('');
25
24
  console.log(chalk.gray('═'.repeat(68)));
26
25
  console.log('');
@@ -109,99 +109,199 @@ Implementado via `anti-blocking.js`:
109
109
 
110
110
  ## 💻 EXEMPLO DE CÓDIGO GERADO
111
111
 
112
- ### `cdpTrack.js` (SDK Principal)
112
+ ### `cdpTrack.js` (SDK Principal — Padrão Multi-Plataforma)
113
+
114
+ > Este é o padrão canônico do cdpTrack SDK para Meta, TikTok e GA4.
115
+ > Cada agente de plataforma injeta seus eventos neste SDK via Browser Tracking Agent.
113
116
 
114
117
  ```javascript
115
118
  /**
116
119
  * cdpTrack SDK - CDP Edge Quantum Tier
117
120
  * Browser Tracking SDK Principal
121
+ * Suporta: Meta Pixel, TikTok Pixel, GA4, Pinterest Tag, Reddit Pixel, Spotify Pixel
118
122
  */
119
123
 
120
- (function(w, d, s, l) {
121
- w._pbq = w._pbq || [];
122
- w._pbq.push = w._pbq.push || [];
123
- w._spotify = w._spotify || {};
124
-
125
- // Carregar configuração
126
- const config = window.cdpTrack?.config || {};
124
+ (function(w) {
125
+ 'use strict';
127
126
 
128
- // Inicializar Spotify Pixel (se configurado)
129
- if (config.spotifyPixelId) {
130
- w._spotify.pixelId = config.spotifyPixelId;
131
- w._spotify.currency = config.currency || 'USD';
127
+ // ──────────────────────────────────────────────
128
+ // CORE: Geração de event_id único (deduplicação)
129
+ // O mesmo event_id deve ser usado no browser E no servidor (CAPI)
130
+ // ──────────────────────────────────────────────
131
+ function generateEventId() {
132
+ return 'evt_' + Date.now() + '_' + Math.random().toString(36).substring(2, 11);
132
133
  }
133
134
 
134
- // Função principal de envio
135
- w._spotify.trackEvent = function(eventName, params) {
136
- const eventId = cdpTrack.generateEventId();
137
-
138
- // Track localmente
139
- w._spq.push({
140
- e: eventName,
141
- params: params,
142
- eventId: eventId,
143
- platform: 'spotify'
144
- });
145
-
146
- // Enviar para servidor (via cdpTrack)
147
- if (window.cdpTrack && window.cdpTrack.submit) {
148
- window.cdpTrack.submit('spotify', {
149
- event: eventName,
150
- event_id: eventId,
151
- ...params
135
+ // ──────────────────────────────────────────────
136
+ // CORE: Envio para Cloudflare Worker (same-domain)
137
+ // Usa /track no mesmo domínio — imune a ad-blockers
138
+ // ──────────────────────────────────────────────
139
+ async function sendToWorker(eventName, payload) {
140
+ const eventId = generateEventId();
141
+
142
+ const body = {
143
+ event: eventName,
144
+ event_id: eventId, // CRÍTICO: mesmo ID usado nas CAPIs
145
+ url: window.location.href,
146
+ referrer: document.referrer,
147
+ timestamp: Date.now(),
148
+ ...payload
149
+ };
150
+
151
+ try {
152
+ // Tentativa primária: fetch
153
+ await fetch('/track', {
154
+ method: 'POST',
155
+ headers: { 'Content-Type': 'application/json' },
156
+ body: JSON.stringify(body),
157
+ keepalive: true
152
158
  });
159
+ } catch (_) {
160
+ // Fallback: Beacon API (funciona mesmo no unload da página)
161
+ navigator.sendBeacon('/track', JSON.stringify(body));
153
162
  }
154
- };
155
163
 
156
- // Eventos Padrão Spotify
157
- w._spotify.Content = function(contentName, contentId, params) {
158
- w._spotify.trackEvent('ViewContent', {
159
- content_name: contentName,
160
- content_id: contentId,
161
- ...params
162
- });
163
- };
164
+ return eventId;
165
+ }
164
166
 
165
- w._spotify.AddToCart = function(contentName, contentId, cartId, params) {
166
- w._spotify.trackEvent('AddToCart', {
167
- content_name: contentName,
168
- content_id: contentId,
169
- cart_id: cartId,
170
- ...params
171
- });
172
- };
167
+ // ──────────────────────────────────────────────
168
+ // CORE: Captura de cookies first-party
169
+ // ──────────────────────────────────────────────
170
+ function getCookie(name) {
171
+ const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
172
+ return match ? decodeURIComponent(match[2]) : null;
173
+ }
173
174
 
174
- w._spotify.Purchase = function(contentName, contentId, value, currency, params) {
175
- w._spotify.trackEvent('Purchase', {
176
- content_name: contentName,
177
- content_id: contentId,
178
- value: value,
179
- currency: currency,
180
- ...params
181
- });
182
- };
175
+ // ──────────────────────────────────────────────
176
+ // CORE: Captura de click IDs da URL (Meta, TikTok, Google)
177
+ // ──────────────────────────────────────────────
178
+ function getClickIds() {
179
+ const params = new URLSearchParams(window.location.search);
180
+ return {
181
+ fbclid: params.get('fbclid') || getCookie('fbclid') || null,
182
+ ttclid: params.get('ttclid') || getCookie('ttclid') || null,
183
+ gclid: params.get('gclid') || null,
184
+ gbraid: params.get('gbraid') || null,
185
+ wbraid: params.get('wbraid') || null,
186
+ fbp: getCookie('_fbp') || null,
187
+ fbc: getCookie('_fbc') || null,
188
+ ttp: getCookie('_ttp') || null,
189
+ uid: getCookie('_cdp_uid') || null // Identity Graph first-party cookie
190
+ };
191
+ }
183
192
 
184
- w._spotify.Lead = function(contentName, contentId, leadType, params) {
185
- w._spotify.trackEvent('Lead', {
186
- content_name: contentName,
187
- content_id: contentId,
188
- lead_type: leadType,
189
- ...params
190
- });
191
- };
193
+ // ──────────────────────────────────────────────
194
+ // API PÚBLICA
195
+ // ──────────────────────────────────────────────
196
+ const cdpTrack = {
197
+ generateEventId,
198
+
199
+ /**
200
+ * Rastrear evento genérico — enviado para o Worker
201
+ * O Worker despacha para Meta CAPI, GA4 MP, TikTok Events API etc.
202
+ *
203
+ * @param {string} eventName - Nome do evento (ex: 'Lead', 'Purchase', 'PageView')
204
+ * @param {Object} params - Parâmetros adicionais do evento
205
+ */
206
+ track(eventName, params = {}) {
207
+ const clickIds = getClickIds();
208
+ return sendToWorker(eventName, { ...clickIds, ...params });
209
+ },
210
+
211
+ /**
212
+ * Rastrear Lead (captura de formulário)
213
+ * Enviar dados PII crus — o Worker faz SHA-256 no servidor
214
+ */
215
+ trackLead(userData = {}) {
216
+ const clickIds = getClickIds();
217
+ return sendToWorker('Lead', {
218
+ ...clickIds,
219
+ email: userData.email || null, // Worker aplica SHA-256
220
+ phone: userData.phone || null, // Worker aplica E.164 + SHA-256
221
+ first_name: userData.first_name || null,
222
+ last_name: userData.last_name || null,
223
+ city: userData.city || null,
224
+ state: userData.state || null,
225
+ zip: userData.zip || null,
226
+ country: userData.country || 'BR'
227
+ });
228
+ },
192
229
 
193
- w._spotify.Signup = function(contentName, contentId, signupType, params) {
194
- w._spotify.trackEvent('Signup', {
195
- content_name: contentName,
196
- content_id: contentId,
197
- signup_type: signupType,
198
- ...params
199
- });
230
+ /**
231
+ * Rastrear Purchase (confirmação de compra)
232
+ */
233
+ trackPurchase(orderData = {}) {
234
+ const clickIds = getClickIds();
235
+ return sendToWorker('Purchase', {
236
+ ...clickIds,
237
+ value: orderData.value || 0,
238
+ currency: orderData.currency || 'BRL',
239
+ order_id: orderData.order_id || null,
240
+ content_name: orderData.product || null
241
+ });
242
+ },
243
+
244
+ /**
245
+ * Rastrear PageView — chamar no load da página
246
+ */
247
+ trackPageView() {
248
+ const clickIds = getClickIds();
249
+ return sendToWorker('PageView', { ...clickIds });
250
+ },
251
+
252
+ /**
253
+ * Rastrear InitiateCheckout
254
+ */
255
+ trackInitiateCheckout(checkoutData = {}) {
256
+ const clickIds = getClickIds();
257
+ return sendToWorker('InitiateCheckout', {
258
+ ...clickIds,
259
+ value: checkoutData.value || 0,
260
+ currency: checkoutData.currency || 'BRL'
261
+ });
262
+ }
200
263
  };
201
264
 
202
- })(window, document, 'script', 'location');
265
+ // Expor no window
266
+ w.cdpTrack = cdpTrack;
267
+
268
+ // Auto page_view no load
269
+ if (document.readyState === 'loading') {
270
+ document.addEventListener('DOMContentLoaded', () => cdpTrack.trackPageView());
271
+ } else {
272
+ cdpTrack.trackPageView();
273
+ }
274
+
275
+ })(window);
203
276
  ```
204
277
 
278
+ ### Uso típico no HTML do cliente
279
+
280
+ ```html
281
+ <!-- 1. Carregar o SDK -->
282
+ <script src="/tracking/cdpTrack.js"></script>
283
+
284
+ <!-- 2. Rastrear lead ao submeter formulário -->
285
+ <script>
286
+ document.getElementById('lead-form').addEventListener('submit', function(e) {
287
+ cdpTrack.trackLead({
288
+ email: document.getElementById('email').value,
289
+ phone: document.getElementById('phone').value,
290
+ first_name: document.getElementById('name').value
291
+ });
292
+ });
293
+ </script>
294
+
295
+ <!-- 3. Rastrear checkout (botão de compra) -->
296
+ <script>
297
+ document.getElementById('buy-btn').addEventListener('click', function() {
298
+ cdpTrack.trackInitiateCheckout({ value: 97.00, currency: 'BRL' });
299
+ });
300
+ </script>
301
+ ```
302
+
303
+ > **Nota:** O Worker recebe os dados crus, aplica SHA-256, e despacha para Meta CAPI v22.0, GA4 MP, TikTok Events API v1.3 e demais plataformas configuradas — tudo em paralelo via `Promise.allSettled`.
304
+
205
305
  ---
206
306
 
207
307
  ## 🔧 INTEGRAÇÃO COM OUTROS AGENTES
@@ -43,6 +43,124 @@ if (isVersionConflict) {
43
43
 
44
44
  ---
45
45
 
46
+ ## 🛡️ GOOGLE CONSENT MODE V2 — IMPLEMENTAÇÃO OBRIGATÓRIA
47
+
48
+ > **CRÍTICO**: Sem Consent Mode v2, campanhas Google Ads em audiências europeias são rejeitadas.
49
+ > Obrigatório para conformidade com GDPR (UE), LGPD (BR) e CCPA (EUA).
50
+
51
+ ### PASSO 1 — Inicialização (ANTES do gtag.js)
52
+
53
+ Inserir **antes** do snippet do gtag.js no `<head>`:
54
+
55
+ ```html
56
+ <!-- Google Consent Mode v2 — Inicializar NEGADO por padrão -->
57
+ <script>
58
+ window.dataLayer = window.dataLayer || [];
59
+ function gtag() { dataLayer.push(arguments); }
60
+
61
+ // OBRIGATÓRIO: definir consent ANTES de qualquer gtag() de medição
62
+ gtag('consent', 'default', {
63
+ 'ad_storage': 'denied', // cookies de anúncio bloqueados até opt-in
64
+ 'analytics_storage': 'denied', // cookies de analytics bloqueados até opt-in
65
+ 'ad_user_data': 'denied', // envio de dados de usuário para Google Ads
66
+ 'ad_personalization': 'denied', // personalização de anúncios
67
+ 'wait_for_update': 500 // aguardar CMP atualizar consentimento (ms)
68
+ });
69
+
70
+ // url_passthrough: preserva gclid/gbraid/wbraid na URL sem cookie
71
+ // Permite atribuição de cliques mesmo sem consent de analytics_storage
72
+ gtag('set', 'url_passthrough', true);
73
+
74
+ // ads_data_redaction: quando ad_storage=denied, reduz dados de clique enviados
75
+ gtag('set', 'ads_data_redaction', true);
76
+ </script>
77
+
78
+ <!-- Carregar gtag.js normalmente após o bloco acima -->
79
+ <script async src="https://www.googletagmanager.com/gtag/js?id=GA4_MEASUREMENT_ID"></script>
80
+ <script>
81
+ window.dataLayer = window.dataLayer || [];
82
+ function gtag() { dataLayer.push(arguments); }
83
+ gtag('js', new Date());
84
+ gtag('config', 'GA4_MEASUREMENT_ID', {
85
+ 'send_page_view': false // cdpTrack controla page_view manualmente
86
+ });
87
+ </script>
88
+ ```
89
+
90
+ ### PASSO 2 — Atualizar Consent após Opt-in do usuário
91
+
92
+ Integrar com o banner de cookies do site (LGPD/GDPR):
93
+
94
+ ```javascript
95
+ // Chamar quando usuário ACEITAR todos os cookies
96
+ function onConsentAccepted() {
97
+ gtag('consent', 'update', {
98
+ 'ad_storage': 'granted',
99
+ 'analytics_storage': 'granted',
100
+ 'ad_user_data': 'granted',
101
+ 'ad_personalization': 'granted'
102
+ });
103
+
104
+ // Opcional: disparar page_view após consent (se necessário)
105
+ gtag('event', 'page_view');
106
+ }
107
+
108
+ // Chamar quando usuário RECUSAR cookies não essenciais
109
+ function onConsentDeclined() {
110
+ gtag('consent', 'update', {
111
+ 'ad_storage': 'denied',
112
+ 'analytics_storage': 'denied',
113
+ 'ad_user_data': 'denied',
114
+ 'ad_personalization': 'denied'
115
+ });
116
+ }
117
+
118
+ // Aceitar apenas cookies analíticos (sem ads)
119
+ function onConsentAnalyticsOnly() {
120
+ gtag('consent', 'update', {
121
+ 'ad_storage': 'denied',
122
+ 'analytics_storage': 'granted',
123
+ 'ad_user_data': 'denied',
124
+ 'ad_personalization': 'denied'
125
+ });
126
+ }
127
+ ```
128
+
129
+ ### PASSO 3 — Verificação (via Intelligence Agent)
130
+
131
+ O Intelligence Agent verifica mensalmente se o Consent Mode está implementado:
132
+
133
+ ```javascript
134
+ // Checklist mínimo no código gerado (browser tracking):
135
+ // ✅ gtag('consent', 'default', {...}) ANTES do gtag.js
136
+ // ✅ ad_storage: 'denied' no default
137
+ // ✅ analytics_storage: 'denied' no default
138
+ // ✅ ad_user_data: 'denied' no default
139
+ // ✅ ad_personalization: 'denied' no default
140
+ // ✅ url_passthrough: true ativo
141
+ // ✅ gtag('consent', 'update', {...}) no callback do CMP/banner
142
+ ```
143
+
144
+ ### PASSO 4 — Integração com cdpTrack (Preservação de gclid)
145
+
146
+ ```javascript
147
+ // O cdpTrack.js deve capturar gclid/gbraid/wbraid da URL mesmo sem consent
148
+ // url_passthrough: true garante que os parâmetros são passados como parâmetros de URL,
149
+ // não como cookies — respeitando consent de analytics_storage
150
+
151
+ function captureGoogleClickId() {
152
+ const params = new URLSearchParams(window.location.search);
153
+ return {
154
+ gclid: params.get('gclid') || null,
155
+ gbraid: params.get('gbraid') || null,
156
+ wbraid: params.get('wbraid') || null
157
+ };
158
+ }
159
+ // Esses IDs são enviados para o Worker e salvos no D1 para Enhanced Conversions offline
160
+ ```
161
+
162
+ ---
163
+
46
164
  ## 🛠️ O QUE VOCÊ GERA
47
165
 
48
166
  ### 1. Browser (Direct SDK)
@@ -363,3 +363,89 @@ INTELLIGENCE_SCHEDULE_MONTHLY = "0 3 1 * *"
363
363
  3. **Alerta Pré-ativo**: Antes de uma API ser descontinuada, alertar com 30 dias de antecedência
364
364
  4. **False-Positive Safe**: Se houver dúvida sobre versão de API, marcar como "verificação manual necessária" em vez de alerta
365
365
  5. **Backoff de Check**: Se o check falhar (API indisponível), tentar novamente em 1 hora (não disparar alerta imediato)
366
+ 6. **Anti-Spam**: Não disparar alerta se o mesmo problema já foi reportado nas últimas 24h
367
+ 7. **Prioridade Correta**: CRITICAL (agora), HIGH (até 1h), MEDIUM (no relatório)
368
+ 8. **Log de Falhas de Alerta**: Se WhatsApp falhar 3× consecutivas, registrar no D1 e tentar via CallMeBot fallback
369
+
370
+ ---
371
+
372
+ ## 🗄️ SCHEMA D1 — intelligence_logs
373
+
374
+ Adicionar ao `server-edge-tracker/schema.sql`:
375
+
376
+ ```sql
377
+ -- TABELA DE LOGS DO INTELLIGENCE AGENT
378
+ CREATE TABLE IF NOT EXISTS intelligence_logs (
379
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
380
+ run_type TEXT NOT NULL, -- 'weekly' | 'monthly' | 'on-demand'
381
+ platforms_checked TEXT, -- JSON array de plataformas verificadas
382
+ issues_found TEXT, -- JSON array de issues encontradas
383
+ issues_count INTEGER DEFAULT 0,
384
+ created_at TEXT DEFAULT (datetime('now'))
385
+ );
386
+
387
+ CREATE INDEX IF NOT EXISTS idx_intel_logs_type ON intelligence_logs(run_type);
388
+ CREATE INDEX IF NOT EXISTS idx_intel_logs_created ON intelligence_logs(created_at);
389
+ ```
390
+
391
+ ---
392
+
393
+ ## ✅ CHECKLIST DE IMPLEMENTAÇÃO
394
+
395
+ Antes de considerar o scheduling implementado, verificar:
396
+
397
+ - [ ] Cron triggers adicionados ao `wrangler.toml` (`0 2 * * 7` e `0 3 1 * *`)
398
+ - [ ] Handlers `scheduled()` adicionados ao `worker.js` (Cloudflare usa `scheduled`, não `fetch`)
399
+ - [ ] Schema D1 atualizado com tabela `intelligence_logs`
400
+ - [ ] Funções de check de versão implementadas com endpoints reais
401
+ - [ ] Funções de auditoria de privacidade implementadas
402
+ - [ ] Sistema de alerta (WhatsApp/CallMeBot) integrado com anti-spam 24h
403
+ - [ ] Logs de execução sendo salvos no D1
404
+ - [ ] Memory Agent atualizado após cada check
405
+ - [ ] Backoff implementado para evitar spam de alertas
406
+ - [ ] Teste manual executado (`GET /api/intelligence/check`)
407
+
408
+ ---
409
+
410
+ ## INPUTS RECEBIDOS
411
+
412
+ - `wrangler.toml` do Worker (para injetar Cron Triggers)
413
+ - `worker.js` (para injetar handlers de `scheduled` events)
414
+ - `schema.sql` (para adicionar tabela `intelligence_logs`)
415
+ - Secrets: `WA_PHONE_ID`, `WA_ACCESS_TOKEN`, `ADMIN_PHONE_NUMBER` (para alertas)
416
+ - `contracts/api-versions.json` (fonte de verdade das versões atuais)
417
+
418
+ ## RESPONSABILIDADE
419
+
420
+ - Configurar Cron Triggers no `wrangler.toml`: semanal (domingo 02:00 UTC) e mensal (1º do mês 03:00 UTC)
421
+ - Implementar handler `scheduled(event, env, ctx)` no Worker
422
+ - Chamar `runIntelligenceWeekly()` quando `event.cron === "0 2 * * 7"`
423
+ - Chamar `runIntelligenceMonthly()` quando `event.cron === "0 3 1 * *"`
424
+ - Adicionar tabela `intelligence_logs` ao schema D1
425
+ - Disparar alertas WhatsApp/CallMeBot ao admin apenas quando houver issues críticos
426
+ - Evitar spam: não repetir alerta do mesmo issue em menos de 24h
427
+ - Registrar resultado de cada execução no D1 (`intelligence_logs`)
428
+
429
+ ## SAÍDA
430
+
431
+ ```json
432
+ {
433
+ "arquivos_modificados": [
434
+ "wrangler.toml (cron triggers adicionados)",
435
+ "worker.js (handler scheduled() adicionado)",
436
+ "schema.sql (tabela intelligence_logs adicionada)"
437
+ ],
438
+ "crons_configurados": {
439
+ "semanal": "0 2 * * 7 (domingo 02:00 UTC — check de versões)",
440
+ "mensal": "0 3 1 * * (dia 1 03:00 UTC — auditoria privacidade)"
441
+ },
442
+ "endpoint_manual": "GET /api/intelligence/check",
443
+ "alertas": {
444
+ "canal_primario": "WhatsApp Meta Cloud API v22.0",
445
+ "canal_fallback": "CallMeBot",
446
+ "anti_spam": "24h cooldown por issue"
447
+ },
448
+ "d1_tabela": "intelligence_logs",
449
+ "secrets_necessarios": ["WA_PHONE_ID", "WA_ACCESS_TOKEN", "ADMIN_PHONE_NUMBER"]
450
+ }
451
+ ```
@@ -1,643 +1,10 @@
1
- # Intelligence Agent — Configuração de Scheduling Automático
1
+ # Intelligence Agent — Scheduling (REDIRECIONAMENTO)
2
2
 
3
- Este arquivo documenta como configurar o Intelligence Agent para rodar automaticamente em intervalos regulares, garantindo que o ecossistema CDP Edge esteja sempre atualizado com as últimas versões de API e conformidades de privacidade.
3
+ > ⚠️ **Este arquivo foi consolidado.**
4
+ >
5
+ > Todo o conteúdo de scheduling automático do Intelligence Agent foi unificado em:
6
+ > **[intelligence-agent.md](./intelligence-agent.md)**
7
+ >
8
+ > Consulte a seção `## 📅 PROTOCOLO DE SCHEDULING` dentro de `intelligence-agent.md`.
4
9
 
5
- ---
6
-
7
- ## 📅 VISÃO GERAL DO SCHEDULING
8
-
9
- O Intelligence Agent possui três níveis de execução automática:
10
-
11
- | Tipo | Frequência | Horário | Objetivo | Impacto |
12
- |-------|-------------|----------|-----------|----------|
13
- | **Semanal** | Domingo 02:00 UTC | Verificação completa de versões | 🔴 CRÍTICO |
14
- | **Mensal** | 1º do mês 03:00 UTC | Auditoria de privacidade + depreciações | 🔴 CRÍTICO |
15
- | **On-Demand** | A qualquer momento | Check específico quando houver suspeita | 🟠 HIGH |
16
-
17
- ---
18
-
19
- ## 🚀 IMPLEMENTAÇÃO NO CLOUDFLARE WORKER
20
-
21
- ### PASSO 1 — Configurar Triggers no wrangler.toml
22
-
23
- Adicionar ao arquivo `server-edge-tracker/wrangler.toml` (ou `wrangler.toml` do Worker):
24
-
25
- ```toml
26
- # ===========================================
27
- # INTELLIGENCE AGENT — SCHEDULING
28
- # ===========================================
29
-
30
- # Trigger Semanal — Domingo 02:00 UTC (Verificação de versões de API)
31
- [[triggers.crons]]
32
- cron = "0 2 * * 0"
33
- schedule = "weekly-intelligence-check"
34
-
35
- # Trigger Mensal — 1º do mês 03:00 UTC (Auditoria de privacidade + depreciações)
36
- [[triggers.crons]]
37
- cron = "0 3 1 * *"
38
- schedule = "monthly-privacy-audit"
39
-
40
- # Variáveis de ambiente para controlar o scheduling
41
- [vars]
42
- INTELLIGENCE_ENABLED = true
43
- INTELLIGENCE_WEEKLY_CRON = "0 2 * * 0"
44
- INTELLIGENCE_MONTHLY_CRON = "0 3 1 * *"
45
- INTELLIGENCE_ALERT_ENABLED = true
46
- ```
47
-
48
- ---
49
-
50
- ### PASSO 2 — Adicionar Handlers no worker.js
51
-
52
- Adicionar ao arquivo `server-edge-tracker/worker.js`:
53
-
54
- ```javascript
55
- // ===========================================
56
- // INTELLIGENCE AGENT — SCHEDULING
57
- // ===========================================
58
-
59
- /**
60
- * Handler Semanal — Check completo de versões de API
61
- * Roda: Domingo 02:00 UTC
62
- * Objetivo: Garantir que todas as APIs estejam atualizadas
63
- */
64
- export async function runIntelligenceWeekly(env, ctx) {
65
- console.log('🕵️‍♂️ Intelligence Agent — Check Semanal iniciado');
66
- console.log('📅 Horário:', new Date().toISOString());
67
-
68
- try {
69
- const platforms = ['meta', 'google', 'tiktok', 'pinterest', 'reddit'];
70
- const issues = [];
71
-
72
- for (const platform of platforms) {
73
- const result = await checkApiVersion(platform, env);
74
- if (result.issue) {
75
- issues.push(result);
76
- }
77
- console.log(`✅ ${platform.toUpperCase()}: ${result.status}`);
78
- }
79
-
80
- // Se houver problemas, disparar alerta
81
- if (issues.length > 0) {
82
- await dispatchIntelligenceAlert('API_VERSION_CHECK', issues, env);
83
- }
84
-
85
- // Logar resultado no D1
86
- await logIntelligenceRun('weekly', platforms, issues, env);
87
-
88
- console.log('✅ Intelligence Agent — Check Semanal concluído');
89
-
90
- } catch (error) {
91
- console.error('❌ Erro no Check Semanal:', error);
92
- await dispatchIntelligenceAlert('WEEKLY_CHECK_ERROR', error.message, env);
93
- }
94
- }
95
-
96
- /**
97
- * Handler Mensal — Auditoria de privacidade + depreciações
98
- * Roda: 1º do mês 03:00 UTC
99
- * Objetivo: Garantir conformidade LGPD/GDPR/CCPA e verificar depreciações
100
- */
101
- export async function runIntelligenceMonthly(env, ctx) {
102
- console.log('🕵️‍♂️ Intelligence Agent — Auditoria Mensal iniciado');
103
- console.log('📅 Horário:', new Date().toISOString());
104
-
105
- try {
106
- const issues = [];
107
-
108
- // 1. Check de privacidade
109
- const privacyIssues = await auditPrivacyCompliance(env);
110
- issues.push(...privacyIssues);
111
-
112
- // 2. Check de depreciações de API
113
- const deprecationIssues = await checkApiDepreciations(env);
114
- issues.push(...deprecationIssues);
115
-
116
- // 3. Check de novos parâmetros de Event Match Quality
117
- const matchQualityIssues = await checkNewMatchQualityParams(env);
118
- issues.push(...matchQualityIssues);
119
-
120
- // Se houver problemas, disparar alerta
121
- if (issues.length > 0) {
122
- await dispatchIntelligenceAlert('MONTHLY_AUDIT', issues, env);
123
- }
124
-
125
- // Logar resultado no D1
126
- await logIntelligenceRun('monthly', [], issues, env);
127
-
128
- console.log('✅ Intelligence Agent — Auditoria Mensal concluída');
129
-
130
- } catch (error) {
131
- console.error('❌ Erro na Auditoria Mensal:', error);
132
- await dispatchIntelligenceAlert('MONTHLY_AUDIT_ERROR', error.message, env);
133
- }
134
- }
135
-
136
- // ===========================================
137
- // FUNÇÕES DE CHECK DE API VERSION
138
- // ===========================================
139
-
140
- async function checkApiVersion(platform, env) {
141
- const apiUrls = {
142
- meta: 'https://graph.facebook.com/v22.0/',
143
- google: 'https://www.google-analytics.com/mp/collect',
144
- tiktok: 'https://business-api.tiktok.com/open_api/v1.3/',
145
- pinterest: 'https://api.pinterest.com/v5/',
146
- reddit: 'https://ads-api.reddit.com/api/v2.0/'
147
- };
148
-
149
- const minimumVersions = {
150
- meta: 'v22.0',
151
- google: 'v2',
152
- tiktok: 'v1.3',
153
- pinterest: 'v5',
154
- reddit: 'v2.0'
155
- };
156
-
157
- try {
158
- const response = await fetch(apiUrls[platform], {
159
- method: 'GET',
160
- headers: {
161
- 'User-Agent': 'CDP Edge/1.0-Intelligence-Agent'
162
- }
163
- });
164
-
165
- if (response.ok) {
166
- return {
167
- platform,
168
- status: 'current',
169
- issue: false
170
- };
171
- } else {
172
- return {
173
- platform,
174
- status: 'error',
175
- issue: true,
176
- error: `HTTP ${response.status}`
177
- };
178
- }
179
-
180
- } catch (error) {
181
- return {
182
- platform,
183
- status: 'unreachable',
184
- issue: true,
185
- error: error.message
186
- };
187
- }
188
- }
189
-
190
- // ===========================================
191
- // FUNÇÕES DE AUDITORIA DE PRIVACIDADE
192
- // ===========================================
193
-
194
- async function auditPrivacyCompliance(env) {
195
- const issues = [];
196
-
197
- // 1. Check: Google Consent Mode v2
198
- const consentModeFiles = [
199
- 'tracking.js',
200
- 'tracking.config.js'
201
- ];
202
-
203
- for (const file of consentModeFiles) {
204
- try {
205
- const content = await readFile(file);
206
- const hasConsentMode = content.includes('ad_storage') &&
207
- content.includes('analytics_storage') &&
208
- content.includes('ad_user_data') &&
209
- content.includes('ad_personalization');
210
-
211
- const hasUrlPassthrough = content.includes('url_passthrough: true');
212
-
213
- if (!hasConsentMode) {
214
- issues.push({
215
- platform: 'google',
216
- issue: 'Consent Mode v2 não está implementado',
217
- severity: 'CRITICAL',
218
- fix: 'Implementar ad_storage=denied, analytics_storage=denied, etc. no browser-tracking.md',
219
- file: file
220
- });
221
- }
222
-
223
- if (!hasUrlPassthrough) {
224
- issues.push({
225
- platform: 'google',
226
- issue: 'url_passthrough: true não está ativo',
227
- severity: 'HIGH',
228
- fix: 'Adicionar url_passthrough: true no gtag config',
229
- file: file
230
- });
231
- }
232
-
233
- } catch (error) {
234
- console.log(`⚠️ Não foi possível auditar ${file}:`, error.message);
235
- }
236
- }
237
-
238
- // 2. Check: Hashing de PII no servidor
239
- const serverFiles = ['worker.js', 'meta-dispatcher.js'];
240
- const hashCheck = content.includes('crypto.subtle.digest');
241
-
242
- for (const file of serverFiles) {
243
- try {
244
- const content = await readFile(file);
245
-
246
- if (!hashCheck) {
247
- issues.push({
248
- platform: 'meta/tiktok/pinterest/reddit',
249
- issue: 'PII enviada sem SHA-256 hashing',
250
- severity: 'CRITICAL',
251
- fix: 'Usar crypto.subtle.digest para email/phone no worker.js',
252
- file: file
253
- });
254
- }
255
-
256
- } catch (error) {
257
- console.log(`⚠️ Não foi possível auditar ${file}:`, error.message);
258
- }
259
- }
260
-
261
- return issues;
262
- }
263
-
264
- // ===========================================
265
- // FUNÇÕES DE CHECK DE DEPRECIAÇÕES
266
- // ===========================================
267
-
268
- async function checkApiDepreciations(env) {
269
- const deprecationSchedule = {
270
- meta: {
271
- 'v20.0': { deprecated: true, cutoff: '2024-01-01', replacement: 'v22.0' },
272
- 'v21.0': { deprecated: true, cutoff: '2024-06-01', replacement: 'v22.0' }
273
- },
274
- tiktok: {
275
- 'v1.2': { deprecated: true, cutoff: '2024-03-01', replacement: 'v1.3' }
276
- },
277
- pinterest: {
278
- 'v4': { deprecated: true, cutoff: '2024-01-01', replacement: 'v5' }
279
- },
280
- reddit: {
281
- 'v1.0': { deprecated: true, cutoff: '2024-06-01', replacement: 'v2.0' }
282
- }
283
- };
284
-
285
- const currentVersions = {
286
- meta: env.META_API_VERSION || 'unknown',
287
- tiktok: env.TIKTOK_API_VERSION || 'unknown',
288
- pinterest: env.PINTEREST_API_VERSION || 'unknown',
289
- reddit: env.REDDIT_API_VERSION || 'unknown'
290
- };
291
-
292
- const issues = [];
293
-
294
- for (const [platform, version] of Object.entries(currentVersions)) {
295
- if (deprecationSchedule[platform]?.[version]) {
296
- const { deprecated, cutoff, replacement } = deprecationSchedule[platform][version];
297
-
298
- if (deprecated) {
299
- issues.push({
300
- platform,
301
- issue: `API version ${version} está descontinuada`,
302
- severity: 'CRITICAL',
303
- cutoff_date: cutoff,
304
- replacement_version: replacement,
305
- fix: `Atualizar para ${replacement}`,
306
- action_required: 'IMEDIATO',
307
- deadline: cutoff
308
- });
309
- }
310
- }
311
- }
312
-
313
- return issues;
314
- }
315
-
316
- // ===========================================
317
- // FUNÇÕES DE CHECK DE NOVOS PARÂMETROS
318
- // ===========================================
319
-
320
- async function checkNewMatchQualityParams(env) {
321
- const platforms = {
322
- meta: 'https://developers.facebook.com/docs/marketing-api/conversions-api/parameters',
323
- google: 'https://support.google.com/analytics/answer/9267733',
324
- tiktok: 'https://ads.tiktok.com/marketing_api/docs?id=1740465605569281'
325
- };
326
-
327
- const issues = [];
328
-
329
- for (const [platform, docsUrl] of Object.entries(platforms)) {
330
- try {
331
- // Em produção, usar WebFetch/MCP para parsing mais preciso
332
- const response = await fetch(docsUrl);
333
-
334
- if (!response.ok) {
335
- continue;
336
- }
337
-
338
- // Placeholder para parsear novos parâmetros
339
- // Na implementação real, extrair parâmetros novos da documentação
340
- const newParams = extractNewParametersFromDocs(await response.text(), platform);
341
-
342
- if (newParams.length > 0) {
343
- issues.push({
344
- platform,
345
- issue: 'Novos parâmetros de Event Match Quality disponíveis',
346
- severity: 'MEDIUM',
347
- new_params: newParams,
348
- fix: `Adicionar novos parâmetros: ${newParams.join(', ')}`,
349
- documentation_url: docsUrl
350
- });
351
- }
352
-
353
- } catch (error) {
354
- console.log(`⚠️ Não foi possível verificar docs de ${platform}:`, error.message);
355
- }
356
- }
357
-
358
- return issues;
359
- }
360
-
361
- // ===========================================
362
- // FUNÇÕES DE ALERTA
363
- // ===========================================
364
-
365
- async function dispatchIntelligenceAlert(alertType, data, env) {
366
- const alertMessages = {
367
- 'API_VERSION_CHECK': '🚨 VERIFICAÇÃO DE VERSÃO DE API',
368
- 'MONTHLY_AUDIT': '🔍 AUDITORIA MENSAL DE PRIVACIDADE',
369
- 'WEEKLY_CHECK_ERROR': '❌ ERRO NO CHECK SEMANAL',
370
- 'MONTHLY_AUDIT_ERROR': '❌ ERRO NA AUDITORIA MENSAL'
371
- };
372
-
373
- const message = `
374
- ${alertMessages[alertType]}
375
-
376
- Timestamp: ${new Date().toISOString()}
377
- Details: ${JSON.stringify(data, null, 2)}
378
-
379
- Ação necessária: Verificar os detalhes acima e implementar correções.
380
- `.trim();
381
-
382
- // Enviar via WhatsApp Agent (se configurado)
383
- if (env.WA_PHONE_ID && env.ADMIN_PHONE_NUMBER) {
384
- await fetch(`https://graph.facebook.com/v22.0/${env.WA_PHONE_ID}/messages`, {
385
- method: 'POST',
386
- headers: {
387
- 'Content-Type': 'application/json',
388
- 'Authorization': `Bearer ${env.WA_ACCESS_TOKEN}`
389
- },
390
- body: JSON.stringify({
391
- messaging_product: 'whatsapp',
392
- to: env.ADMIN_PHONE_NUMBER,
393
- type: 'text',
394
- text: message
395
- })
396
- });
397
- }
398
-
399
- // Fallback para CallMeBot
400
- else if (env.ADMIN_PHONE_NUMBER) {
401
- await fetch(`https://api.callmebot.com/send.php`, {
402
- method: 'POST',
403
- body: new URLSearchParams({
404
- phone: env.ADMIN_PHONE_NUMBER,
405
- text: message
406
- })
407
- });
408
- }
409
-
410
- console.log('📤 Alerta enviado:', alertType);
411
- }
412
-
413
- // ===========================================
414
- // FUNÇÕES DE LOGGING
415
- // ===========================================
416
-
417
- async function logIntelligenceRun(runType, platforms, issues, env) {
418
- if (!env.DB) return;
419
-
420
- await env.DB.prepare(`
421
- INSERT INTO intelligence_logs (run_type, platforms_checked, issues_found, created_at)
422
- VALUES (?, ?, ?, ?)
423
- `).bind(
424
- runType,
425
- JSON.stringify(platforms),
426
- JSON.stringify(issues),
427
- new Date().toISOString()
428
- ).run();
429
- }
430
- ```
431
-
432
- ---
433
-
434
- ### PASSO 3 — Atualizar Schema D1 (se necessário)
435
-
436
- Adicionar ao `server-edge-tracker/schema.sql`:
437
-
438
- ```sql
439
- -- TABELA DE LOGS DO INTELLIGENCE AGENT
440
- CREATE TABLE IF NOT EXISTS intelligence_logs (
441
- id INTEGER PRIMARY KEY AUTOINCREMENT,
442
- run_type TEXT NOT NULL, -- 'weekly' | 'monthly' | 'on-demand'
443
- platforms_checked TEXT, -- JSON array de plataformas verificadas
444
- issues_found TEXT, -- JSON array de issues encontradas
445
- issues_count INTEGER DEFAULT 0,
446
- created_at TEXT DEFAULT (datetime('now'))
447
- );
448
-
449
- -- ÍNDICE PARA QUERIES EFICIENTES
450
- CREATE INDEX IF NOT EXISTS idx_intel_logs_type ON intelligence_logs(run_type);
451
- CREATE INDEX IF NOT EXISTS idx_intel_logs_created ON intelligence_logs(created_at);
452
- ```
453
-
454
- ---
455
-
456
- ### PASSO 4 — Atualizar Main Fetch Handler
457
-
458
- Adicionar ao handler principal do worker:
459
-
460
- ```javascript
461
- export default {
462
- async fetch(request, env, ctx) {
463
- const url = new URL(request.url);
464
-
465
- // Handler principal de tracking
466
- if (url.pathname === '/api/track') {
467
- return handleTracking(request, env, ctx);
468
- }
469
-
470
- // Handlers de Intelligence Agent (schedulados)
471
- if (url.pathname === '/cron/intelligence-weekly') {
472
- return await runIntelligenceWeekly(env, ctx);
473
- }
474
-
475
- if (url.pathname === '/cron/intelligence-monthly') {
476
- return await runIntelligenceMonthly(env, ctx);
477
- }
478
-
479
- // Endpoint manual de check on-demand
480
- if (url.pathname === '/api/intelligence/check') {
481
- return await runIntelligenceWeekly(env, ctx);
482
- }
483
-
484
- return new Response('Not Found', { status: 404 });
485
- }
486
- };
487
- ```
488
-
489
- ---
490
-
491
- ## 🎯 CRITÉRIOS DE SUCESSO DO SCHEDULING
492
-
493
- ### Check Semanal (Versões de API)
494
-
495
- - [ ] Todas as plataformas configuradas foram verificadas
496
- - [ ] Endpoints estão respondendo (200 OK)
497
- - [ ] Versões atuais estão documentadas no Memory Agent
498
- - [ ] Alertas foram disparados se houver problemas
499
- - [ ] Log foi salvo no D1 (intelligence_logs)
500
-
501
- ### Auditoria Mensal (Privacidade + Depreciações)
502
-
503
- - [ ] Google Consent Mode v2 foi verificado
504
- - [ ] Hashing de PII foi verificado em todas as APIs
505
- - [ ] Depreciações foram verificadas (com cutoff date)
506
- - [ ] Novos parâmetros de Match Quality foram pesquisados
507
- - [ ] Todos os issues encontrados foram documentados
508
- - [ ] Alerta consolidado foi enviado ao admin
509
-
510
- ### Métricas de Eficiência
511
-
512
- O Intelligence Agent deve calcular e reportar:
513
-
514
- ```json
515
- {
516
- "intelligence_metrics": {
517
- "weekly_checks": {
518
- "total": 52,
519
- "successful": 50,
520
- "failed": 2,
521
- "issues_detected": 3,
522
- "uptime_percentage": "96.15%"
523
- },
524
- "monthly_audits": {
525
- "total": 12,
526
- "successful": 12,
527
- "failed": 0,
528
- "privacy_issues": 0,
529
- "deprecation_issues": 1,
530
- "compliance_rate": "100%"
531
- },
532
- "avg_response_time_minutes": 2.3,
533
- "alert_sent_rate": "100%"
534
- }
535
- }
536
- ```
537
-
538
- ---
539
-
540
- ## 🔧 CONFIGURAÇÃO DE VARIÁVEIS DE AMBIENTE
541
-
542
- Adicionar ao `wrangler.toml` ou via `wrangler secret put`:
543
-
544
- ```bash
545
- # Secrets necessários para o Intelligence Agent
546
- wrangler secret put INTELLIGENCE_ENABLED --name server-edge-tracker
547
- wrangler secret put WA_PHONE_ID --name server-edge-tracker
548
- wrangler secret put WA_ACCESS_TOKEN --name server-edge-tracker
549
- wrangler secret put ADMIN_PHONE_NUMBER --name server-edge-tracker
550
-
551
- # Valores recomendados:
552
- # INTELLIGENCE_ENABLED = true
553
- # WA_PHONE_ID = seu_phone_id_do_whatsapp
554
- # WA_ACCESS_TOKEN = seu_access_token_da_meta
555
- # ADMIN_PHONE_NUMBER = +5511999999999
556
- ```
557
-
558
- ---
559
-
560
- ## 📈 MONITORAMENTO DOS SCHEDULES
561
-
562
- Após implementar, monitorar via Cloudflare Dashboard:
563
-
564
- 1. **Cron Triggers**: Verificar se os jobs estão rodando nos horários programados
565
- 2. **Success Rate**: Verificar se as chamadas estão terminando com sucesso
566
- 3. **Execution Time**: Monitorar o tempo de execução (deve ser < 5 minutos)
567
- 4. **Error Logs**: Verificar logs do Worker para erros nos handlers de intelligence
568
- 5. **Database Growth**: Monitorar crescimento da tabela `intelligence_logs`
569
-
570
- ---
571
-
572
- ## 🚨 REGRAS DE ALERTA
573
-
574
- 1. **Não Spam**: Não disparar alerta se o mesmo problema já foi reportado nas últimas 24h
575
- 2. **Prioridade Correta**: CRITICAL (agora), HIGH (até 1h), MEDIUM (relatório)
576
- 3. **Informação Útil**: Incluir sempre timestamp, plataforma, e ação necessária
577
- 4. **Backoff de Tentativa**: Se o envio de alerta falhar, tentar novamente em 10 minutos (máximo 3 tentativas)
578
- 5. **Log de Falhas de Alerta**: Se o WhatsApp Agent falhar 3 vezes consecutivas, registrar no D1 e notificar via outro canal
579
-
580
- ---
581
-
582
- ## ✅ CHECKLIST DE IMPLEMENTAÇÃO DO SCHEDULING
583
-
584
- Antes de considerar o scheduling implementado, verificar:
585
-
586
- - [ ] Cron triggers adicionados ao wrangler.toml
587
- - [ ] Handlers de weekly/monthly adicionados ao worker.js
588
- - [ ] Schema D1 atualizado com tabela intelligence_logs
589
- - [ ] Funções de check de versão implementadas
590
- - [ ] Funções de auditoria de privacidade implementadas
591
- - [ ] Sistema de alerta (WhatsApp/CallMeBot) integrado
592
- - [ ] Logs de execução sendo salvos no D1
593
- - [ ] Memory Agent está sendo atualizado após cada check
594
- - [ ] Backoff implementado para evitar spam de alertas
595
- - [ ] Teste manual executado (/api/intelligence/check)
596
- - [ ] Documentação atualizada com instruções de troubleshooting
597
-
598
- ---
599
-
600
- > 📅 **Objetivo Final:** Garantir que o ecossistema CDP Edge esteja sempre atualizado com as últimas versões de API e em conformidade com LGPD/GDPR/CCPA, sem necessidade de intervenção manual constante.
601
-
602
- ---
603
-
604
- ## INPUTS RECEBIDOS
605
-
606
- - `wrangler.toml` do Worker (para injetar Cron Triggers)
607
- - `worker.js` (para injetar handlers de scheduled events)
608
- - `schema.sql` (para adicionar tabela `intelligence_logs`)
609
- - Secrets: `WA_PHONE_ID`, `WA_ACCESS_TOKEN`, `ADMIN_PHONE_NUMBER` (para alertas)
610
- - `contracts/api-versions.json` (fonte de verdade das versões atuais)
611
-
612
- ## RESPONSABILIDADE
613
-
614
- - Configurar Cron Triggers no `wrangler.toml`: semanal (domingo 02:00 UTC) e mensal (dia 1 às 03:00 UTC)
615
- - Implementar `runIntelligenceWeekly()` e `runIntelligenceMonthly()` no Worker
616
- - Adicionar tabela `intelligence_logs` ao schema D1
617
- - Disparar alertas WhatsApp/CallMeBot ao admin apenas quando houver issues críticos
618
- - Evitar spam: não repetir alerta do mesmo issue em menos de 24h
619
- - Registrar resultado de cada execução no D1 (`intelligence_logs`)
620
-
621
- ## SAÍDA
622
-
623
- ```json
624
- {
625
- "arquivos_modificados": [
626
- "wrangler.toml (cron triggers adicionados)",
627
- "worker.js (handlers weekly/monthly adicionados)",
628
- "schema.sql (tabela intelligence_logs adicionada)"
629
- ],
630
- "crons_configurados": {
631
- "semanal": "0 2 * * 0 (domingo 02:00 UTC — check de versões)",
632
- "mensal": "0 3 1 * * (dia 1 03:00 UTC — auditoria privacidade)"
633
- },
634
- "endpoint_manual": "GET /api/intelligence/check",
635
- "alertas": {
636
- "canal_primario": "WhatsApp Meta Cloud API v22.0",
637
- "canal_fallback": "CallMeBot",
638
- "anti_spam": "24h cooldown por issue"
639
- },
640
- "d1_tabela": "intelligence_logs",
641
- "secrets_necessarios": ["WA_PHONE_ID", "WA_ACCESS_TOKEN", "ADMIN_PHONE_NUMBER"]
642
- }
643
- ```
10
+ Motivo: duplicação eliminada para manter uma única fonte de verdade.
@@ -54,6 +54,52 @@ Quando o Master Orchestrator solicitar um deploy, você fornece os dados ao DevO
54
54
 
55
55
  ---
56
56
 
57
+ ## ⚡ QUICK REFERENCE — API DE CONSULTA (para outros agentes)
58
+
59
+ Qualquer agente pode consultar o Memory Agent com a seguinte chamada:
60
+
61
+ ```javascript
62
+ // Consultar qualquer dado salvo na memória da sessão
63
+ const memoryQuery = async (query) => {
64
+ const checkpoint = await readMemoryCheckpoint(); // lê memory-agent.json
65
+
66
+ switch (query.type) {
67
+ case 'get_secret':
68
+ // query: { type: 'get_secret', platform: 'meta', secret_name: 'access_token' }
69
+ return checkpoint.secrets_configured?.[query.platform]?.[query.secret_name];
70
+
71
+ case 'get_api_version':
72
+ // query: { type: 'get_api_version', platform: 'tiktok' }
73
+ return checkpoint.api_versions?.[query.platform];
74
+
75
+ case 'get_infra':
76
+ // query: { type: 'get_infra', key: 'd1_database_id' }
77
+ return checkpoint.cloudflare_infrastructure?.bindings?.[query.key];
78
+
79
+ case 'check_if_implemented':
80
+ // query: { type: 'check_if_implemented', item: 'meta_capi' }
81
+ return checkpoint.context_state?.platforms_configured?.includes(query.item);
82
+
83
+ case 'get_technical_decision':
84
+ // query: { type: 'get_technical_decision', decision_id: 'decision_001' }
85
+ return checkpoint.technical_decisions?.find(d => d.id === query.decision_id);
86
+
87
+ default:
88
+ throw new Error(`Query type desconhecido: ${query.type}. Tipos válidos: get_secret | get_api_version | get_infra | check_if_implemented | get_technical_decision`);
89
+ }
90
+ };
91
+
92
+ // Exemplo de uso em qualquer agente — NUNCA inventar credenciais:
93
+ const metaToken = await memoryQuery({ type: 'get_secret', platform: 'meta', secret_name: 'access_token' });
94
+ if (!metaToken || metaToken === 'NOT_SET') {
95
+ throw new Error('META_ACCESS_TOKEN não configurado. Solicite ao usuário antes de continuar.');
96
+ }
97
+ ```
98
+
99
+ > **Regra Anti-Alucinação:** Se `memoryQuery()` retornar `null`, `undefined` ou `NOT_SET` → **NÃO INVENTAR**. Solicitar ao usuário explicitamente.
100
+
101
+ ---
102
+
57
103
  ## 🧠 OBJETIVO PRINCIPAL: ELIMINAR RETRABALHO E ALUCINAÇÃO
58
104
 
59
105
  Sua única função é registrar absolutamente TUDO o que importa. Você é o banco de dados centralizado da sessão de chat.
@@ -144,6 +190,30 @@ O Memory Agent não é só um conceito — ele tem uma implementação técnica
144
190
  "pixel": "v2",
145
191
  "conversions_api": "v2.0",
146
192
  "verified_at": null
193
+ },
194
+ "linkedin": {
195
+ "insight_tag": "latest",
196
+ "conversions_api": "v2",
197
+ "verified_at": null
198
+ },
199
+ "spotify": {
200
+ "pixel": "v1",
201
+ "conversions_api": "v1",
202
+ "verified_at": null
203
+ },
204
+ "whatsapp": {
205
+ "cloud_api": "v22.0",
206
+ "verified_at": null
207
+ },
208
+ "bing": {
209
+ "uet": "latest",
210
+ "conversions_api": "v2",
211
+ "verified_at": null
212
+ },
213
+ "youtube": {
214
+ "ga4_integration": "latest",
215
+ "customer_match": "SHA-256",
216
+ "verified_at": null
147
217
  }
148
218
  },
149
219
 
@@ -181,6 +251,34 @@ O Memory Agent não é só um conceito — ele tem uma implementação técnica
181
251
  "pixel_id": "NOT_SET",
182
252
  "access_token": "NOT_SET",
183
253
  "verified_at": null
254
+ },
255
+ "pinterest": {
256
+ "tag_id": "NOT_SET",
257
+ "access_token": "NOT_SET",
258
+ "ad_account_id": "NOT_SET",
259
+ "verified_at": null
260
+ },
261
+ "reddit": {
262
+ "pixel_id": "NOT_SET",
263
+ "access_token": "NOT_SET",
264
+ "ad_account_id": "NOT_SET",
265
+ "verified_at": null
266
+ },
267
+ "linkedin": {
268
+ "access_token": "NOT_SET",
269
+ "conversion_id": "NOT_SET",
270
+ "ad_account_id": "NOT_SET",
271
+ "verified_at": null
272
+ },
273
+ "spotify": {
274
+ "ad_account_id": "NOT_SET",
275
+ "access_token": "NOT_SET",
276
+ "verified_at": null
277
+ },
278
+ "whatsapp": {
279
+ "phone_number_id": "NOT_SET",
280
+ "token": "NOT_SET",
281
+ "verified_at": null
184
282
  }
185
283
  },
186
284
 
@@ -12,6 +12,48 @@ Você é o especialista em Webhooks do CDP Edge. Sua missão é capturar vendas
12
12
 
13
13
  ---
14
14
 
15
+ ## 🔐 NORMALIZAÇÃO E HASHING DE PII (OBRIGATÓRIO)
16
+
17
+ Antes de qualquer dispatch para CAPI, normalizar e hashear PII extraída do webhook:
18
+
19
+ ```javascript
20
+ // Hashing SHA-256 para PII — usar WebCrypto (disponível em Cloudflare Workers)
21
+ async function hashPII(value) {
22
+ if (!value) return null;
23
+ const normalized = value.toString().toLowerCase().trim();
24
+ const encoder = new TextEncoder();
25
+ const data = encoder.encode(normalized);
26
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
27
+ return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
28
+ }
29
+
30
+ // Normalização E.164 para telefone (Brasil)
31
+ function normalizePhone(phone) {
32
+ if (!phone) return null;
33
+ const digits = phone.replace(/\D/g, '');
34
+ // Adicionar +55 se não tiver código de país
35
+ if (digits.length === 10 || digits.length === 11) return `+55${digits}`;
36
+ if (digits.startsWith('55') && (digits.length === 12 || digits.length === 13)) return `+${digits}`;
37
+ return `+${digits}`;
38
+ }
39
+
40
+ // Exemplo de uso no handler de webhook:
41
+ async function hashWebhookUserData(webhookPayload) {
42
+ const email = webhookPayload.buyer?.email || webhookPayload.email;
43
+ const phone = webhookPayload.buyer?.phone || webhookPayload.phone;
44
+ return {
45
+ em: email ? await hashPII(email) : null, // SHA-256 lowercase+trim
46
+ ph: phone ? await hashPII(normalizePhone(phone)) : null, // SHA-256 após E.164
47
+ fn: webhookPayload.buyer?.first_name ? await hashPII(webhookPayload.buyer.first_name) : null,
48
+ ln: webhookPayload.buyer?.last_name ? await hashPII(webhookPayload.buyer.last_name) : null,
49
+ };
50
+ }
51
+ ```
52
+
53
+ > **Regra:** NUNCA enviar email ou telefone em plaintext para Meta CAPI, GA4 MP ou TikTok Events API. Sempre normalizar → hashear → enviar.
54
+
55
+ ---
56
+
15
57
  ## 🏗️ PADRÕES TÉCNICOS (Quantum Tier)
16
58
 
17
59
  1. **D1 Identity Cross-Check**: Utilize o e-mail ou telefone do webhook para buscar no banco **D1** os identificadores originais (`fbp`, `fbc`, `ttp`). Isso garante a precisão da atribuição.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cdp-edge",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "CDP Edge - Quantum Tracking - Sistema multi-agente para tracking digital Cloudflare Native (Workers + D1)",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",