Pular para o conteúdo principal
← Voltar ao changelog

Changelog - 04/05/2026

Jornada FTD — Refatoração Completa e Novas Brands

  • D0 e D1 desacoplados — antes, ativar o template vera-legacy do D0 (cashback) ligava implicitamente o modal de anúncio do D1 (check-in). Agora cada brand habilita as três etapas independentemente: ftdCashback.enabled, ftdCheckin.enabled e a flag nova ftdCheckin.announcement.enabled. Quatro combinações possíveis — só D0, só D1, ambos ou nenhum.
  • Copy e assets configuráveis por brand no template vera-legacyFtdCashbackConfig ganhou copy.{firstBonusToastTitle,cashbackModalTitle,cashbackModalDescriptionHtml,cashbackModalCtaText} + templateAssets.{firstBonusToastImage,cashbackModalImage}. FtdCheckinConfig ganhou announcement.copy.{title,descriptionHtml,ctaText} + templateAssets.image. Todos opcionais — fallback é o copy PT-BR + CDN da Vera (zero regressão).
  • 16 tokens de tema novos para o template e o toastftd-offer.template-{shell-bg,title-text,title-shadow,image-bg-from,image-bg-to,highlight-bg,highlight-border,highlight-text,cta-bg,cta-text} e ftd-offer.toast-{bg-from,bg-to,border,icon-bg-from,icon-bg-to,icon-border}. FtdOfferModalTemplate e FtdOfferInGameToast agora leem essas cores via CSS custom properties inline (Tailwind JIT não consegue gerar classes a partir de tokens dinâmicos).
  • 7k-bet-br ativa a jornada completa — D0 cashback, D1 check-in (com modal de anúncio "Garanta sua diversão!") e oferta-relâmpago pré-FTD, todos via template unificado. Quatro assets brand-specific da CDN do 7k substituem os fallbacks da Vera (toast, modal cashback, anúncio D1 e modal de oferta).
  • cassino-bet-br ativa a jornada completa — paleta + assets próprios, brand_id: 2 no Dark Verifier/Freedom (paridade com useFtdCashback.ts:52 do legado), kill-switches feFtdD0Cassino / feFtdD1Cassino, tabela bonusTiers de 35 níveis portada verbatim do legado (R$ 5 → R$ 3000+, cap em R$ 800), autoDepositModal abre o drawer de depósito automaticamente no login quando saldo ≤ R$ 0,10. Inclui lista de jogos elegíveis em cashback/eligible-games.ts.
  • cl-bet7k-com ativa D0 + D1 com identidade chilenabrandId: 4, kill-switch feFtdD07KCl (compartilhado D0/D1), tabela bonusTiers de 11 níveis em CLP (CLP 850 → CLP 510 000, cap CLP 136 000), 6995 IDs elegíveis portados 1:1 do legado, copy em espanhol chileno ("¡Sigue jugando para ganar un cashback!"). Moeda renderiza sem decimais ($50.000) via useFormatMoney() + CountryConfig.displayDecimalDigits. D1 começa desabilitado no primeiro rollout.
  • STT 2 (saldo bônus) com kill-switch remotosaldoBonus.featureFlags?: { legacy?, configcat? } permite desligar a STT 2 instantaneamente via ConfigCat ou FF legado sem deploy. O hook useFtdCashbackFlow computa saldoBonusRemoteKillSwitchPass (closed-by-default enquanto a API está em voo, mesma semântica do D0/D1). Cassino declara feFtdSaldoBonus + feFtdSaldoBonusCassino.
  • Header reescrito — single-row, scroll-aware, cluster com skew. Novos componentes CtaButtonVera e CtaButtonSecondary, HeaderUserAreaVera, hook useScrolledPast. GameCardVera agora usa CtaButton id="game-card-play" visualOnly em vez de <span> hardcoded — herda variant cta-vera da brand e mantém consistência com Cadastrar/Depositar. Overlay de hover ganhou pointer-events-none para preservar o click do <Link> pai.
  • Footer full-width — nova flag structure.footerFullWidth (default false); quando ativa, o footer escapa do contentContainer e renderiza como sibling viewport-wide nos shells header-top e split-shell. Vera ativa a flag para alinhar com o header.
  • Tom de verde alinhado entre header e footerbg-primary da Vera passou de #0e1d21 para #003628 (= header.main-bg), button-bg foi para #026455 (= header.balance-bg) para manter contraste das pílulas mobile.
  • Gradient unificado em sidebar e maiores ganhosSidebarTitledSection e WinsListHeader (Vera) trocaram primary (#06e05b neon) por header-balance-bg (#026455 teal-green), eliminando dissonância visual com os cards do "Pagou Muito". Outras brands não consomem essas surfaces.
  • Footer sem grupo "amigos verabet" — campaign API e widget atualizados para remover o grupo descontinuado; widget campaign-widget continua ativo para os demais grupos.
  • Indique e Ganhe — porta da página /games/indique-ganhe do legado para o LP system: rota canônica /lp/indique-ganhe com redirect 301 da URL antiga (preserva backlinks externos do Telegram, Instagram e WhatsApp). Inclui banner CDN, hero com CTA "Acessar meu código" → /user/refers, seção "Como funciona" com 3 passos, grid de 6 jogos populares (família Fortune do PG Soft + Touro/Macaco Sortudo da Pragmatic) e CTA secundário no fim.
  • Link de download canônico do app — novo override brand.appearance.links aplicado em DefaultLayout antes do BrandProvider montar. Vera força https://play.google.com/store/apps/details?id=br.bet.vera.twa.apk&hl=pt_BR para todos os consumers (FooterBadges, SidebarBottomItems, useAppInstall, InstallAppTooltip) — corrige URLs stale vindas do BFF. Brands sem override têm zero overhead.

Analytics — view_item_list e GTM

  • Tracking GA4 view_item_list no primeiro scroll-into-view — novo hook useOnFirstScrollIntoView instrumenta GameSection, TournamentsSection, WinsCombinedWidget, HomeBannerCarousel, MainLeaguesWidget, RecommendedGamesBento e TopGamesSection. item_list_name segue o título da row (Vera: "Jogos de Cassino Recomendados", fallback "Jogos Recomendados"). Items mapeados pelo banner.action + banner.alt.
  • Helpers de métricas centralizados — novo app/utils/metrics/index.ts + ampliação de app/utils/metrics/gtm.ts para suportar o evento.
  • Nova flag cookieConsentCosmeticOnly — quando true, o banner continua renderizando visualmente (cumprir compliance), mas NÃO gateia tracking: o initGTM injeta acceptAll como Google Consent Mode v2 default (zero janela cega entre carregamento do GTM e clique), e qualquer caminho de clique (Aceitar / Recusar / Salvar personalizado) converge para acceptAll no cookie cookies_consent e no signal de update. Os toggles do painel "Personalizar" continuam visíveis mas sem efeito real. Pré-requisito: brand.features.cookieConsentPopup (BFF) precisa estar true. Ativada em 7k-bet-br, fi-7k-bet, ng-7k-bet, cl-bet7k-com, cassino-bet-br e vera-bet-br por decisão conjunta de marketing + compliance. Demais brands preservam o comportamento legado (consent real respeitado).

Sports — Gate de Validação Real-Time

  • Novo componente ValidationContextGate — gate que bloqueia o iframe de esportes quando o usuário tem KYC pendente, lendo o contexto sports do fetchAllValidations() em real-time.
  • Bottom nav mobile não some mais quando o modal de validação é dispensadosetFullscreenOpen(true) foi movido para dentro de startGameRequest em GameIframe.tsx. Antes, ao clicar em "Jogar" e fechar o modal de KYC sem completar, o estado gameFullscreenOpen ficava preso em true e a bottom nav permanecia escondida até a próxima navegação.

Detail Page de Jogos — Stats Alinhados com a Home

  • high-payers vira fonte autoritativa para valores monetários — o widget "Pagou muito" (home) consome /bff/games/game-high-payers-dl (totalPaid por janela), enquanto o detail page consumia /bff/games/statistics-dl (last24Hours.wins, last1Hour.wins). As duas APIs têm pipelines de cálculo independentes no BI e divergiam sutilmente. Agora o getStats(slug) server-side, depois de buscar stats, consulta getHighPayers() (já cacheado por brand via platform-cache) e sobrescreve last24Hours.wins e last1Hour.wins quando o slug está no top-N. Jogos fora do top-N caem no fallback. Custo zero de chamada extra. Try/catch silencioso garante que o detail page nunca quebra por isso.

Proteção de Conta — Acordeões

  • Botões de "Alternativas à exclusão" agora abrem o acordeão alvo — port do forceOpenAccordion do legado Vera. Antes os 4 botões (Pausar 7d, Pausar 30d, Manter com limite aposta, Manter com limite depósito) só faziam scrollIntoView; o usuário chegava lá e tinha que clicar de novo. Agora um novo store useProtectionStore com forceOpenAccordion(id) é ouvido pelo LimitAccordion, que auto-abre + scrolla quando o id bate. Store reseta em 1s para permitir re-clicar no mesmo botão. Adicionado também o botão "Falar com suporte" quando hasLiveSupport (paridade com legado).

Cassino — Mobile Bottom Nav

  • Variant mobile-nav-fab-center restaurada no cassino-bet-br — após experimento com mobile-nav-illustrated-tabs, o cassino volta para o FAB "Depositar" flutuante no centro. Ordem: Menu · Cassino · [FAB] · Cassino Ao Vivo · Esportes. Ícones herdam INTENT_DEFAULTS (Dices, MonitorPlay, Soccer), paths via routeHref() respeitam overrides da brand.
  • Refinamentos no primitive compartilhadoFabButton sai menos do topo da barra (translate-y-1/4 ancorado em -top-2), label "Depositar" em font-bold, pulse suave (animate-promo-pulse) aplicado só no ícone interno. NavTile ganhou gap-1.5 (de gap-0.5) para mais respiro entre ícone e label. Afeta todos os variants do mobile bottom nav.
  • assetlinks.json restaurado para 7k-bet-br, cassino-bet-br e vera-bet-br — portado dos repos Vue legados para overrides/<brand>/public/.well-known/. Sem esses arquivos os TWAs Android perdem modo url-bar-hidden, Smart Lock (common.get_login_creds) e a permissão common.use_as_origin do Smartico. Placeholders dos 10 repos base-* legados (com package_name vazio) intencionalmente não foram portados — falham na validação DAL do Google e seriam piores que 404. Smoke-tested via pnpm dev --<brand> --port 5185; state77 confirmou 404 como negative control.

Brand Overrides

  • vera-bet-br — campaign API — atualização da configuração do strategy.ts (com testes para Mini Games standalone) e ajuste do trigger de registro do mini-game. Widget campaign-widget permanece ativo após remoção do grupo descontinuado.
  • vera-bet-br — promocode — refactor removendo o estado de feedback e mensagens inline da PromocodePageContent em preparação para integração via SDK.
  • vera-bet-br — UI tweaks — ajustes no badge dos cards de torneio (TournamentCardClassic/Stacked), label dos top-games, hint de quick-access e visual do gift no campaign-widget.

Core / SDK

  • @cactus-agents/validations — cobertura do gate de esportes — três casos novos em evaluate.test.ts validam contexts.sports = { allowed: false, pendingModule: "kyc" } quando a brand declara sports.active=true, modules=["kyc"] e o usuário não tem KYC aprovado. Inclui também: liberado pós-login com KYC aprovado e undefined quando a brand opta out via sports.active=false. Regressão necessária para o novo ValidationContextGate do base.
  • Limpeza de 16 warnings do Biome no core — sem mudança funcional. noNonNullAssertion (13 casos em testes do accounts) silenciado via override de biome.json para **/__tests__/** (! é uso legítimo em tests). noExplicitAny em platform-cache/engine.ts resolvido trocando Map<string, Promise<CacheResult<any>>> por CacheResult<unknown> (call-sites já fazem as Promise<CacheResult<T>>). Suppressions órfãos removidos em api-client/server.ts. Verificado: pnpm lint, pnpm check, pnpm build (20/20) e pnpm test (409+ casos) todos passando.

Ops

  • Branches default padronizadas para main-ana — múltiplos workflows de deploy do front-ops ajustados para consumir main-ana em vários ambientes (paridade da convenção de naming).