Relatório de Auditoria Técnica
PRD 01 — O pescador de ofertas
Versão 1.0 · 06/11/2026
A. Arquitetura Encontrada
Stack: React 18 + Vite + Tailwind CSS + shadcn/ui, rodando na plataforma Base44 (BaaS).
Estrutura de pastas:
src/pages/→ 12 páginas (Home, OfferDetail, Dashboard, Blog, BlogDetail, BlogDashboard, About, PrivacyPolicy, TermsOfUse, Login, Register, ForgotPassword, ResetPassword)src/components/→ Componentes UI (Hero, OfferCard, OfferModal, OfferMarquee, SearchBar, Filters, BotSection, Layout, dashboard/*, blog/*)base44/entities/→ 6 entidades (Offer, Click, Lead, BlogPost, CommentReply, BotState)base44/functions/→ 11 funções backendbase44/shared/→ 3 módulos compartilhados (offerUtils, shopeeAffiliateApi, marketplaceScraper)base44/workflows/→ 6 workflows
Autenticação: Base44 Auth nativa (AuthProvider, ProtectedRoute). Usuários admin têm acesso ao Dashboard e BlogAdmin. Login via email/senha + Google OAuth. Rotas públicas não exigem login.
Navegação: React Router com Layout como wrapper (header + footer + Outlet). Navegação responsiva (mobile e desktop).
B. Banco de Dados
1. Entidade Offer (núcleo do catálogo)
Finalidade: Armazena todas as ofertas/produtos curados.
Campos principais: title, slug, description, detailed_description, image_url, additional_images, price_original, price_current, discount_percent, rating, review_count, niche (13 categorias), marketplace (shopee/amazon/mercadolivre), affiliate_url, social_caption, is_featured, is_expired, stock_status, click_count, post_status, post_priority, instagram_media_id.
Relacionamentos: Referenciada por Click.offer_id e CommentReply.offer_id.
Status: ✅ Preservar. Expansível — campos podem ser adicionados sem quebrar nada.
2. Entidade Click (rastreamento de cliques)
Finalidade: Registra cliques em links de afiliado.
Campos: offer_id, offer_title, lead_id, origem (enum: homepage, instagram, tiktok, facebook, direct, organic).
Status: ✅ Preservar. Expansível — faltam campos para PRD 02 (session_id, visitor_id, utm_*).
3. Entidade Lead (captura de leads)
Finalidade: Captura de leads e interessados.
Campos: name, email, preferred_niches (array), origem, status (pending, converted).
Status: ✅ Preservar. Expansível.
4. Entidade BlogPost (conteúdo)
Finalidade: Artigos do blog (prévias, unboxings, comparações).
Campos: title, slug, excerpt, content (HTML), cover_image, media_type, video_url, category, author, tags, is_published, views.
Status: ✅ Preservar.
5. Entidade CommentReply (Instagram)
Finalidade: Registra respostas enviadas a comentários do Instagram (evitar duplicidade).
Campos: comment_id, offer_id, media_id, username, comment_text, reply_text.
Status: ✅ Preservar.
6. Entidade BotState (estado do bot)
Finalidade: Estado simples do bot (chave/valor numérico).
Campos: key, value.
Status: ✅ Preservar.
7. Entidade User (sistema — built-in)
Finalidade: Usuários da plataforma. Apenas admins acessam o painel.
Status: ✅ Preservar (read-only, gerenciado pela plataforma).
C. Catálogo — Como os produtos entram
Existem 3 fluxos de entrada de produtos:
Fluxo 1: Sincronização automática via API Shopee (primário)
Função: syncOffersFromShopeeAPI → chama fetchShopeeProductOffers (GraphQL productOfferV2).
Como funciona: Busca 50 ofertas da Shopee Affiliate API, filtra por desconto maior que 0, verifica duplicidade por affiliate_url e title, cria registros com dados reais.
Fluxo 2: Sincronização via IA com web search (secundário)
Função: syncOffersFromWeb → usa InvokeLLM (gemini_3_flash + web search) para encontrar ofertas da Shopee e Amazon, depois faz scraping real, fallback para imagem gerada por IA.
Fluxo 3: Importação manual por URL
Função: importOfferFromUrl → admin cola URL de produto, resolve short links, extrai itemId/shopId, busca dados reais via API Shopee, se não encontrar, fallback para LLM + scraping.
| Campo | Shopee API | LLM/Scraping | Disponível? |
|---|---|---|---|
| ID externo (itemId) | ✅ | ❌ | Parcial |
| Nome | ✅ | ✅ | ✅ |
| Imagem | ✅ (real) | Scraping/AI | ✅ |
| Categoria (niche) | Detectada | LLM | ✅ |
| Preço atual | ✅ | ✅ | ✅ |
| Preço original | Calculado | LLM | ✅ |
| Desconto % | ✅ | LLM | ✅ |
| Link afiliado | ✅ (API) | Scraping+tag | ✅ |
| Vendedor (shopName) | ✅ | ❌ | Parcial |
| Avaliação (ratingStar) | ✅ | LLM | ✅ |
| Qtd vendida (sales) | ✅ | ❌ | Parcial |
| Comissão (commissionRate) | ✅ (não salvo) | ❌ | Disponível mas não salvo |
| Disponibilidade | Default | Default | Não real |
D. Afiliados — Como os links funcionam
Shopee
- Onde é gerado: O link chega pronto pela API (offerLink do productOfferV2).
- Transformação: Nenhuma — o link da API já contém o tracking.
- Sub-ID / Tracking ID: Não implementado.
- Saída do usuário: Direta — window.open sem redirecionamento interno.
Amazon
- Onde é gerado: URL do produto do scraper (ASIN) ou LLM.
- Transformação: buildAffiliateUrl injeta tag=fishnet0f-20 (hardcoded).
- ID de afiliado: fishnet0f-20 (Amazon Associates).
- Saída do usuário: Direta — window.open.
Mercado Livre
- Status: Enum existe mas não há integração ativa (conta suspensa). Aparece no rodapé mas não no catálogo.
Registro de clique
- Sim, existe: Ao clicar em "Comprar", cria um registro Click com offer_id, offer_title e origem.
- Origem registrada: homepage (OfferModal), direct (OfferDetail). Outros valores do enum existem mas não são populados.
E. APIs — Integrações existentes
| Integração | Tipo | Estado | Função |
|---|---|---|---|
| Shopee Affiliate API | GraphQL + SHA256 | ✅ Funcionando | shopeeAffiliateApi.ts |
| Instagram Graph API | OAuth Connector | ✅ Autorizado | postToInstagram, replyToComments |
| Link direto | ✅ Funcionando | Compartilhamento e reservas | |
| Amazon Scraper | HTTP scraping | ⚠️ Frágil | marketplaceScraper.ts |
| InvokeLLM (Gemini) | Base44 Integration | ✅ Funcionando | Web search + legendas |
| GenerateImage | Base44 Integration | ✅ Funcionando | Imagens de fallback |
Secrets configurados: SITE_URL, SHOPEE_AFFILIATE_APP_ID, SHOPEE_AFFILIATE_SECRET, WORKFLOW_SECRET, HEYGEN_API_KEY.
F. Analytics
| Recurso | Status |
|---|---|
| Google Analytics 4 | ❌ NÃO IMPLEMENTADO |
| Google Tag Manager | ❌ NÃO IMPLEMENTADO |
| Meta Pixel | ❌ NÃO IMPLEMENTADO |
| Eventos personalizados | ⚠️ PARCIAL — Click.create + analytics.track |
| Tracking interno | ⚠️ PARCIAL — entidade Click sem session/visitor |
| Cookies | ❌ NÃO IMPLEMENTADO |
| Session ID | ❌ NÃO IMPLEMENTADO |
| Visitor ID | ❌ NÃO IMPLEMENTADO |
| UTM | ❌ NÃO IMPLEMENTADO — não parseados |
| Logs de clique | ⚠️ PARCIAL — sem contexto de sessão |
G. Tracking — Capacidade atual
| Nível | Status | Observação |
|---|---|---|
| Origem | ⚠️ Parcial | Click.origem é hardcoded |
| Visitante | ❌ Não existe | Sem visitor_id |
| Sessão | ❌ Não existe | Sem session_id |
| Campanha | ❌ Não existe | Sem campaign_id, UTM não parseado |
| Produto | ✅ Existe | Click.offer_id |
| Clique | ✅ Existe | Entidade Click + Offer.click_count |
| Redirecionamento | ❌ Direto | Sem redirecionamento interno |
Resumo: O sistema registra que produto foi clicado, mas não quem clicou, de onde veio, nem em qual sessão/campanha.
H. Dados de Marketplace para Tendências
| Campo | Marketplace | API/Origem | Possibilidade |
|---|---|---|---|
| Qtd vendida (sales) | Shopee | productOfferV2.sales | ⚠️ Disponível — não armazenado |
| Comissão (commissionRate) | Shopee | productOfferV2.commissionRate | ⚠️ Disponível — não armazenado |
| Avaliação (ratingStar) | Shopee | productOfferV2.ratingStar | ✅ Já armazenado em rating |
| Desconto % | Shopee | priceDiscountRate | ✅ Já armazenado |
| Preço atual | Shopee | priceMin | ✅ Já armazenado |
| Ranking/popularidade | Shopee | sortType (2=Sales) | ✅ Via ordenação |
| Hot Products | AliExpress | API (futuro) | 🔜 Disponível se integrar |
| Amazon sales/ranking | Amazon | Não via scraping | ❌ Não disponível |
Oportunidade: A API Shopee fornece sales e commissionRate que poderiam ser armazenados mas não estão sendo salvos. Adicionar esses campos permitiria análise de tendência no PRD 08.
I. Segurança
| Item | Status |
|---|---|
| API Keys no front-end | ✅ Nenhuma — todas em secrets |
| Tokens expostos | ✅ Nenhum token no front-end |
| Secrets no front-end | ✅ Nenhum — via secrets.get() |
| Endpoints administrativos | ✅ Protegidos — verificam admin |
| Acesso público a dados admin | ✅ ProtectedRoute |
| Credenciais hardcoded | ⚠️ Amazon tag fishnet0f-20 hardcoded |
| RLS (Row-Level Security) | ⚠️ Não configurado nas entidades |
J. Performance
| Item | Status | Observação |
|---|---|---|
| Consultas desnecessárias | ⚠️ | Home: 100 ofertas + 3 posts (2 chamadas) |
| Carregamento do catálogo | ✅ | Lista 100 ofertas — razoável |
| Imagens | ⚠️ | Usa img nativo, não Image otimizado |
| Busca | ⚠️ | Client-side em memória — não escala |
| Sitemap | ✅ | Gerado dinamicamente via getSitemap |
K. Alterações Realizadas
Nenhuma alteração foi feita no código. Este PRD é exclusivamente de auditoria e levantamento. A aplicação permanece exatamente como estava.
L. Testes de Regressão
Como nenhuma alteração foi feita, não há risco de regressão. A arquitetura foi apenas lida, não modificada. Funcionalidades intactas:
✅ Home (catálogo, busca, filtros, marquee, blog)
✅ OfferDetail (SEO, JSON-LD, cliques, similares)
✅ Dashboard (3 abas)
✅ Sincronização Shopee API
✅ Sincronização via IA
✅ Importação manual por URL
✅ Instagram posting
✅ Blog (listagem, detalhe, admin)
✅ Atendimento via WhatsApp
✅ SEO (sitemap, meta tags, JSON-LD)
✅ Login/Admin (ProtectedRoute)
M. Recomendação para PRD 02
Estruturas existentes que o PRD 02 deverá reutilizar:
- Entidade Click — já existe. Expandir (não recriar) adicionando: session_id, visitor_id, utm_source, utm_medium, utm_campaign, utm_content, utm_term, referrer, landing_page.
- Entidade Lead — já captura origem. Manter como está.
- Componente Layout — ponto ideal para injetar tracking de sessão/visitante.
- OfferModal.handleBuy e OfferDetail.handleBuy — pontos onde o clique já é registrado. Expandir para incluir session_id/visitor_id/UTM.
- index.html — local para adicionar Meta Pixel e GA4 no PRD 06.
Novas estruturas que o PRD 02 precisará criar:
- Entidade Session — nova, não existe equivalente.
- Entidade Visitor — nova, não existe equivalente.
- Entidade Campaign — nova, não existe equivalente.
- Entidade Event — nova, estrutura genérica para eventos.
- Hook useTracking ou módulo src/lib/tracking.js — para inicializar visitor_id (localStorage) + session_id (sessionStorage) + parse de UTM.
Recomendação técnica:
O PRD 02 deve seguir a prioridade REUTILIZAR → EXPANDIR → CRIAR: reutilizar entidade Click e handlers de clique existentes; expandir Click com novos campos; criar entidades Session, Visitor, Campaign, Event (não existem equivalentes).
Status do PRD 01: ✅ Concluído · Aguardando aprovação para iniciar o PRD 02
