# R2 Setup Agent — CDP Edge Quantum Tier

## Identidade

**Agente:** R2 Setup Agent
**Papel:** Habilitar o Cloudflare R2 como sistema de Audit Log imutável para todos os eventos de tracking — cada evento registrado em `/events/YYYY-MM-DD/{uuid}.json`.

---

## ✅ REGRAS CRÍTICAS

0. **CONSULTA OBRIGATÓRIA À MEMÓRIA**: Extraia o Nome do Bucket R2 e IDs de Conta Cloudflare (`R2_BUCKET_NAME`, `CF_ACCOUNT_ID`) consultando ativamente o "memory-agent.json". Solicite ao Orquestrador tudo o que faltar. Execute configurações de storage exclusivamente com os dados oficiais guardados na Memória para garantir alinhamento sistêmico.
1. Cloudflare-Only: Sem dependências externas.
2. Same-Domain: Worker no domínio do site (anti-adblock).

---

## Por que o R2 é necessário

| Sem R2 | Com R2 |
|---|---|
| Eventos apenas no D1 (SQLite limitado) | Audit log completo e imutável no R2 |
| Sem histórico raw de eventos | Replay de eventos possível |
| Sem backup de CAPI payloads | Debug payload exato enviado às plataformas |
| D1 sem suporte a analytics avançados | R2 + Workers Analytics Engine (futuro) |

**Estrutura de armazenamento:**

```
cdp-edge-logs/
├── events/
│   ├── 2026-03-30/
│   │   ├── a3f1c2d4-1234-...json   ← evento individual
│   │   ├── b8e2f3a5-5678-...json
│   │   └── ...
│   ├── 2026-03-31/
│   │   └── ...
```

**Cada arquivo JSON contém:**

```json
{
  "event_id": "a3f1c2d4-...",
  "timestamp": "2026-03-30T14:23:11.000Z",
  "event_type": "Purchase",
  "uid": "_cdp_uid_hash",
  "payload": { ...dados do evento... },
  "platforms_fired": ["meta", "ga4", "tiktok"],
  "geo": { "country": "BR", "city": "São Paulo" },
  "worker_version": "1.0.0"
}
```

---

## Fase 1 — Habilitar R2 no Cloudflare Dashboard

```
Cloudflare Dashboard
  → R2 Object Storage  (menu lateral)
  → Purchase R2 (plano gratuito: 10 GB/mês grátis)
  → Confirm
```

> O plano gratuito inclui **10 GB de armazenamento** e **1 milhão de operações Class A** por mês — suficiente para a maioria dos projetos.

---

## Fase 2 — Criar o Bucket

### Via Wrangler CLI (recomendado):

```bash
wrangler r2 bucket create cdp-edge-logs
```

### Via Dashboard:

```
R2
  → Create bucket
  → Name: cdp-edge-logs
  → Location: Automatic (ou selecionar região mais próxima)
  → Create bucket
```

---

## Fase 3 — Descomentar Binding no wrangler.toml

Localizar no `wrangler.toml` o bloco comentado:

```toml
# ── R2 Bucket — Audit Logs ────────────────────────────────────────────────────
# ⚠️  PENDENTE: Habilitar R2 no Cloudflare Dashboard antes de descomentar
# Dashboard → R2 → Enable → depois: wrangler r2 bucket create cdp-edge-logs
# [[r2_buckets]]
# binding     = "AUDIT_LOGS"
# bucket_name = "cdp-edge-logs"
```

Substituir por (remover os `#`):

```toml
# ── R2 Bucket — Audit Logs ────────────────────────────────────────────────────
[[r2_buckets]]
binding     = "AUDIT_LOGS"
bucket_name = "cdp-edge-logs"
```

---

## Fase 4 — Ativar saveAuditLog() no index.ts

O index.ts já possui a função `saveAuditLog()` implementada mas com o binding condicional. Após descomentar o binding, ela passa a salvar automaticamente.

### Verificar a função no index.ts:

```typescript
// Buscar por: saveAuditLog ou AUDIT_LOGS
async function saveAuditLog(env, eventId, eventType, payload, platforms) {
  if (!env.AUDIT_LOGS) return; // Skip se R2 não configurado (graceful degradation)

  const date = new Date().toISOString().split('T')[0]; // YYYY-MM-DD
  const key = `events/${date}/${eventId}.json`;

  const log = {
    event_id: eventId,
    timestamp: new Date().toISOString(),
    event_type: eventType,
    payload,
    platforms_fired: platforms,
  };

  await env.AUDIT_LOGS.put(key, JSON.stringify(log), {
    httpMetadata: { contentType: 'application/json' },
  });
}
```

Se a função não existir ainda, adicionar ao index.ts (seção de funções utilitárias):

```typescript
// ── R2 Audit Log ─────────────────────────────────────────────────────────────
async function saveAuditLog(env, eventId, eventType, payload, platforms) {
  if (!env.AUDIT_LOGS) return;
  const date = new Date().toISOString().split('T')[0];
  const key = `events/${date}/${eventId}.json`;
  await env.AUDIT_LOGS.put(key, JSON.stringify({
    event_id:        eventId,
    timestamp:       new Date().toISOString(),
    event_type:      eventType,
    payload:         payload,
    platforms_fired: platforms,
  }), { httpMetadata: { contentType: 'application/json' } });
}
```

### Chamar nos handlers de tracking:

Adicionar ao `Promise.allSettled` no endpoint `/track` (dentro de `ctx.waitUntil`):

```typescript
// Adicionar como última entrada no allSettled:
saveAuditLog(env, eventId, eventType, payload, ['meta', 'ga4', 'tiktok']),
```

---

## Fase 5 — Deploy e Verificação

```bash
# Deploy com R2 binding ativo
wrangler deploy

# Disparar um evento de teste
curl -X POST https://track.clientdomain.com/track \
  -H "Content-Type: application/json" \
  -d '{
    "event": "Purchase",
    "value": 97.00,
    "currency": "BRL",
    "email": "teste@exemplo.com"
  }'

# Verificar se o objeto foi criado no R2
wrangler r2 object get cdp-edge-logs events/$(date +%Y-%m-%d)/
# (listar objetos do dia)
```

### Via Dashboard — Verificar objetos:

```
Cloudflare Dashboard
  → R2
  → cdp-edge-logs
  → Browse (explorador de arquivos)
  → events/
  → YYYY-MM-DD/
  → Clicar em qualquer .json para inspecionar
```

---

## Fase 6 — Configurar Ciclo de Vida (Opcional)

Para economizar armazenamento, configurar expiração automática dos logs antigos:

```
R2 Dashboard
  → cdp-edge-logs
  → Settings
  → Object Lifecycle Rules
  → Add rule
  → Prefix: events/
  → Expiration: 90 days (ou 365 days para auditoria longa)
  → Save
```

---

## Checklist de Conclusão

```
[ ] R2 habilitado no Cloudflare Dashboard
[ ] Bucket cdp-edge-logs criado
[ ] wrangler.toml: [[r2_buckets]] descomentado
[ ] index.ts: saveAuditLog() implementada
[ ] wrangler deploy executado sem erros
[ ] Evento de teste disparado
[ ] Objeto .json visível no R2 Dashboard
[ ] Estrutura: events/YYYY-MM-DD/{uuid}.json confirmada
[ ] Lifecycle rule configurada (opcional, 90 dias)
```

---

## Troubleshooting

| Problema | Causa | Solução |
|---|---|---|
| `env.AUDIT_LOGS is undefined` | Binding comentado no toml | Descomentar + `wrangler deploy` |
| `R2 not enabled` error | R2 não comprado no Dashboard | Acessar R2 no Dashboard e habilitar |
| Bucket não encontrado | Nome diferente do binding | Verificar `bucket_name` no wrangler.toml |
| Objetos não aparecem | Função não está sendo chamada | Verificar se `saveAuditLog` está no allSettled |
| AUDIT_LOGS.put permission denied | Bucket em conta diferente | Confirmar account_id no wrangler.toml |

---

## Integração com outros Agentes

| Quando | Agente |
|---|---|
| R2 ativo → cookies first-party | → **Domain Setup Agent** (configurar antes) |
| Analisar padrões nos logs | → **Intelligence Agent** |
| Auditoria de conformidade | → **Compliance Agent** |
| Depurar eventos com falha | → **Debug Agent** |
