Skip to content

Infraestrutura — Brandvelia

Documento operacional dos serviços conectados a este monorepo. Atualizar quando a infra mudar.

Serviços

Serviço Conta/Projeto Ref
GitHub EuVinicios/mypaidtraffic (privado)
Vercel team vinicios-silveiras-projects, projeto mypaidtraffic prj_Ho3yFRvdhSqOA046uBeeRgOws4zp
Supabase projeto panoptes (compartilhado, São Paulo) koknxysqvdvxrtgyjbsv
Cloudflare zona brandvelia.com (Registrar + DNS) zona f5424150e857d92628718facac2fdf42

Domínios

Domínio Uso Configuração
brandvelia.com Site público, landing/bridge pages DNS: A @ → 76.76.21.21 (DNS only)
app.brandvelia.com Central administrativa (fase 1) DNS: CNAME app → cname.vercel-dns.com (DNS only)
www.brandvelia.com Redirect 308 → apex DNS: CNAME www → cname.vercel-dns.com (DNS only)
  • Deploy: push para main (via PR) → produção em brandvelia.com e app.brandvelia.com.
  • Protection: URLs *.vercel.app exigem SSO; domínios custom são públicos (all_except_custom_domains).
  • Root directory do projeto Vercel: apps/web.

Supabase (regras de banco compartilhado)

  • O projeto panoptes atende outros sistemas em produção (Finanças, Conexao, Radar, Viagens, Z900, Panoptes/ações). Nunca alterar/dropar objetos fora do schema brandvelia.
  • Migrations: additive-only, aplicadas com supabase db push (a partir da raiz).
  • Antes de migrations estruturais: supabase db dump --linked -f backup.sql.
  • Placeholders _shared_panoptes.sql em supabase/migrations/ representam o histórico de migrations de outros sistemas — não editar, não remover.

Padrão de acesso a dados (importante)

O projeto não altera a configuração de schemas expostos da API do Supabase (configuração compartilhada). Em vez disso:

  • Tabelas vivem no schema brandvelia com RLS habilitado (isolamento por workspace_id via workspace_members).
  • A API REST as acessa por views auto-atualizáveis public.bv_* com security_invoker = true — o RLS das tabelas base se aplica normalmente.
  • Funções SQL têm wrappers públicos: bv_create_workspace, bv_get_dashboard_summary.
  • anon só enxerga landing pages published (via policy específica). authenticated só vê dados dos workspaces em que é membro. service_role é usado apenas nos endpoints públicos server-side (/api/track, /api/leads).
  • Métricas financeiras são calculadas em SQL (bv_get_dashboard_summary) — nunca por LLM.
  • Ao adicionar colunas em tabelas existentes, recriar a view bv_* correspondente (views congelam a lista de colunas).

IA (OpenRouter)

  • packages/ai — gateway server-only (OpenRouterProvider), structured outputs com JSON Schema.
  • Model registry: tabela bv_ai_models (seed com 4 modelos; preços aproximados — revisar em openrouter.ai/models).
  • Uso por chamada registrado em bv_ai_runs (tokens, custo, latência) + agregado em bv_ai_usage.
  • Env var obrigatória para IA: OPENROUTER_API_KEY (server-side, Vercel).

Secrets

Segredo Onde vive Env var
Supabase anon key Vercel (encrypted, 3 ambientes) + .env.local (dev) NEXT_PUBLIC_SUPABASE_ANON_KEY
Supabase service role Vercel (encrypted, 3 ambientes) + .env.local (dev) SUPABASE_SERVICE_ROLE_KEY
Cloudflare DNS API token ~/.cloudflare/brandvelia-dns-token (local, 600) — (infra)
OpenRouter API key Vercel (sensitive/encrypted, 3 ambientes) + .env.local (dev) OPENROUTER_API_KEY
ClickBank INS secret ~/.brandvelia/clickbank-ins-secret (local, 600) + Vercel (3 ambientes) — mesmo valor configurado no painel do ClickBank CLICKBANK_NOTIFICATION_SECRET
Turnstile keys pendente (opcional; formulários públicos) NEXT_PUBLIC_TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY
ClickBank API keys (Key 1 + Key 2) ~/.brandvelia/clickbank-api.json (local, 600) + Vercel (3 ambientes) CLICKBANK_API_KEY_1 / CLICKBANK_API_KEY_2

IA (validação E2E)

Pipeline do Copilot testado ponta a ponta (jun/2026): sessão → workspace → transações → chamada OpenRouter (google/gemini-2.5-flash) → resposta citando os valores exatos calculados em SQL → registro em bv_ai_runs (tokens, custo, latência). Custo por chamada calculado a partir do model registry.

ClickBank INS (fase 2)

  • Webhook de produção: https://brandvelia.com/api/webhooks/clickbank
  • Formato: envelope JSON {notification, iv} (AES-256-CBC, key = sha1(secret)[:32]); legado form-encoded também aceito
  • Secret key: máx. 16 caracteres (limite da UI do ClickBank) — valor em ~/.brandvelia/clickbank-ins-secret
  • Pipeline: raw event (dedup_key único, replay-safe) → normalização (SALE/BILL/RFND/CGBK/INSF/CANCEL-REBILL/TEST_*/unmapped) → conversão → atribuição (INS 8.0: affiliateTrackingParameters.extclid + campaign nomeado; legado: trackingCodes) → transação (external_ref = receipt) → lead_events
  • TEST (botão Test URL) cria conversão com notes=test_notification, sem transação
  • Configuração no ClickBank (docs oficiais abril/2025 — INS é UI-only):
  • Login → selecionar o account nickname na aba Accounts
  • Aba Vendor SettingsMy Site → seção Advanced ToolsEdit
  • Clique em "Request Access" ao lado do campo Instant Notification URL (o recurso não é habilitado por padrão) → preencha o formulário e concorde com os termos → Save Changes & Request API Access
  • Depois do acesso concedido: informe a Secret Key (≤16 chars) e salve
  • Entre a URL acima no campo Instant Notification URL → clique em Test URL (envia uma notificação TEST; a URL fica marcada como Verified) → Save Changes
  • Reconciliação: Finance → Importar CSV (relatório ClickBank) → matched/missing_in_app/missing_in_source

ClickBank API (fase 2)

Specs oficiais salvas em docs/clickbank-api/ (baixadas de docs.clickbank.net/docs/docs-manifest.json):

  • analytics-v1.jsonGET /rest/1.3/analytics/{role}/{dimension} (role: vendor|affiliate; dimension: tracking_id, vendor, product_sku, customer_country, …); param obrigatório account (nickname)
  • orders-v2.jsonGET /v2/orders (lista pedidos por período/tipo: SALE, BILL, RFND, CGBK, TEST_*)
  • products-v2.json — catálogo de produtos por seller

Autenticação (verificada na spec): header Authorization: <dev-key>:<api-key> — sem prefixo "Basic". Duas chaves distintas (Clerk API Key 1 e 2).

Descobertas de sondagem (ago/2026):

  • developer.clickbank.com bloqueado por Cloudflare; docs reais em docs.clickbank.net (SPA; dados em /docs/*.json) e em support.clickbank.com/en/articles/10535400 (ClickBank APIs)
  • QuickStats API (GET /rest/1.3/quickstats/accounts|count|list) — lista nicknames de contas com acesso do API user + totais diários sale/refund/chargeback; quickstats/accounts revela o nickname necessário para o parâmetro account da Analytics API. Role necessária: API Order Read
  • Namespace /2.0/* de api.clickbank.com retorna 403 no nginx mesmo sem auth (bloqueado no gateway)
  • Sandbox (sandbox.clickbank.com) descontinuado
  • Keys em ~/.brandvelia/clickbank-api.json (local, 600) → env vars CLICKBANK_API_KEY_1 / CLICKBANK_API_KEY_2 no Vercel

Email (fase 2)

  • Unsubscribe público: /unsubscribe?token=… → POST /api/email/unsubscribe (revoga consentimento, registra email_events, atualiza lead)
  • Platform é source of truth; ESP (envio real) será adapter quando um provedor for escolhido

Comandos úteis

# DNS (token em ~/.cloudflare/brandvelia-dns-token)
TOKEN=$(cat ~/.cloudflare/brandvelia-dns-token)
curl -s "https://api.cloudflare.com/client/v4/zones/f5424150e857d92628718facac2fdf42/dns_records" \
  -H "Authorization: Bearer $TOKEN" | jq -r '.result[] | "\(.type) \(.name) -> \(.content)"'

# Vercel
vercel ls                    # deployments
vercel env ls                # variáveis
vercel logs <deployment-url> # logs

# Supabase
supabase db push --linked --dry-run   # preview do que será aplicado
supabase migration list --linked      # estado local vs remoto