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 embrandvelia.comeapp.brandvelia.com. - Protection: URLs
*.vercel.appexigem 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
panoptesatende outros sistemas em produção (Finanças, Conexao, Radar, Viagens, Z900, Panoptes/ações). Nunca alterar/dropar objetos fora do schemabrandvelia. - 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.sqlemsupabase/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
brandveliacom RLS habilitado (isolamento porworkspace_idviaworkspace_members). - A API REST as acessa por views auto-atualizáveis
public.bv_*comsecurity_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 embv_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+campaignnomeado; 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 Settings → My Site → seção Advanced Tools → Edit
- 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.json—GET /rest/1.3/analytics/{role}/{dimension}(role: vendor|affiliate; dimension: tracking_id, vendor, product_sku, customer_country, …); param obrigatórioaccount(nickname)orders-v2.json—GET /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.combloqueado por Cloudflare; docs reais emdocs.clickbank.net(SPA; dados em/docs/*.json) e emsupport.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/accountsrevela o nickname necessário para o parâmetroaccountda Analytics API. Role necessária: API Order Read - Namespace
/2.0/*deapi.clickbank.comretorna 403 no nginx mesmo sem auth (bloqueado no gateway) - Sandbox (
sandbox.clickbank.com) descontinuado - Keys em
~/.brandvelia/clickbank-api.json(local, 600) → env varsCLICKBANK_API_KEY_1/CLICKBANK_API_KEY_2no Vercel
Email (fase 2)¶
- Unsubscribe público:
/unsubscribe?token=…→ POST/api/email/unsubscribe(revoga consentimento, registraemail_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