Banner de consentimento de cookies com Google Consent Mode v2 chega ao base. O CookieConsentBanner (fixado no canto inferior esquerdo, animado, z-60) e o painel CookieConsentDetails (abas Configurações/Sobre, toggles por categoria, tabela de cookies) injetam os defaults do GCM antes do GTM inicializar e gravam a preferência no cookie cactusCookiesConsent. Mapeamento de categorias: performance → analytics_storage, functionality → functionality_storage, demais → ad_storage + ad_user_data + ad_personalization. Bypass para bots via useIsBot(). Feature flag brand.features.cookieConsentPopup controla a exibição por marca, sem build-time config.
Paridade total com o legado Vue (base + 7k + cassino + vera): adicionado o sétimo sinal do GCM v2 (security_storage: granted) para auditorias Lighthouse/CMP enxergarem o contrato completo; COOKIE_TABLE expandida de 6 para 19 entradas cobrindo Cloudflare, GA4, Clarity, Meta Pixel, Kwai, Amplitude, Smartico e cookies de funcionalidade (current_lang, topbar_closed, install_app_popup_closed); migração transparente do formato legado (array JSON de strings) para o novo objeto, sem reprompt de usuários existentes.
UX e visual: o banner se posiciona acima do MobileBottomNav em mobile (h-14), some quando o drawer está aberto, fica print:hidden, e tem split 50/50 entre [Personalizar | Recusar] e [Aceitar todos]. Cores 100% via tokens de tema (bg-secondary, text-texts, bg-primary), eliminando bg-white/* e border-white/* hardcoded. O botão "Salvar" dentro do painel de detalhes se torna "Aceitar todos" quando só a categoria necessária está marcada — replica o saveButton() do legado.
Captura de UTMs agora roda server-side no root loader (app/root.tsx). Antes, a captura era apenas client-side em useEffect — UTMs se perdiam quando um loader fazia redirect(...) antes do hydrate. Ex: landing /?utm_source=X&ref=AFIL1 que dispara redirect para /register agora preserva os parâmetros via Set-Cookie na própria response do redirect. Resolve o report "Rastreamento perde-se após o login/redirecionamento".
Política de atribuição alinhada com legado: last-touch. Cada nova URL com UTM sobrescreve o cookie anterior, igual ao middleware global do Nuxt antigo. A versão anterior (first-touch) divergia silenciosamente da atribuição calibrada nos dashboards de BI.
Captura também re-executa em toda navegação SPA via useLocation() no TrackingCapture — antes corria só 1x no mount.
Semana 13–21/04 — auth, user e wallet viram @cactus-agents/accounts (breaking)
Os três pacotes de conta foram fundidos em um só, no dia 17/04.eac3812 cria packages/accounts movendo para lá o código de packages/auth, packages/user e packages/wallet (serviços de auth, recuperação, usuário e wallet; restrição de conta; histórico de login; jogo responsável; refresh de token; tipos de auth/user/wallet), e 452450eapaga os três pacotes no mesmo dia — 16 arquivos, 2.623 linhas removidas. Não existe mais @cactus-agents/auth, @cactus-agents/user nem @cactus-agents/wallet.
Migração para quem consome: troque os três imports por @cactus-agents/accounts (serviços e tipos) e @cactus-agents/accounts/react (hooks). No base isso foi feito em 88f85f275, com o pacote entrando via fde5ef596 / 4db2b4ed1 e a versão subindo de ^0.2.0 (a3396a973) para ^0.14.1 ao fim da semana. O package.json do base saiu de auth ^0.6.0 + user ^0.6.0 + wallet ^0.4.1 para uma única dependência accounts.
Retratação: as entradas de março que anunciaram @cactus-agents/wallet e @cactus-agents/user como pacotes SDK publicados descrevem um estado que deixou de existir aqui. Leia-as como histórico — os nomes não resolvem mais no registry.
O subpath /react é o que muda o dia a dia do base.212615a expõe store Zustand no nível do módulo e os hooks de saldo já formatados por locale/moeda (useRealBalance, useBonusBalance, useCashbackBalance); 3fad9c8 completa a superfície de wallet (useWallet, useRollover, useWalletFlags, useTransactions, useTransferBonus, useTransferCashback, useRefreshWallet, useFormatMoney, useAccountsInit), tornando removível a fachada useWallet que o base mantinha à mão; dd73c98 adiciona os hooks de auth (useCurrentUser, useLogin, useRegister, useLogout, useRefreshProfile, useValidateDocument, useRecovery); da07b42 adiciona useProfile com updateAddress, updatePhone, updateProfile, storeDocument, updateMarketing e lookupPostalCode; 0afc73a adiciona useWithdrawReceipt.
Os adapters HTTP default vêm embutidos (a492634): como todos os forks do base herdam as rotas de proxy /api/wallet/refresh|transactions|action, /api/auth/*, /api/user/* e /api/address/* com o envelope { ok, data, error }, a lib passou a falar esse protocolo por padrão — o consumidor só chama useAccountsInit({ locale, currency }). 2816079 desacopla initAccounts do client concreto (recebe refetchWallet em vez de walletService), 0a89fe9 alinha os adapters de auth ao envelope do base, e 494c42c documenta por que o /react usa fetch cru em vez do ApiClient.
useTransactions devolve transação pré-formatada (b5ae424): novo FormattedTransaction = Transaction & { amountFormatted: string }, com o amount cru preservado para a lógica de sinal. Consumidor não importa formatador nem recebe um por prop.
Do lado do base, a consequência foi apagar código:551fa1470 remove os fetches manuais, a76c112c1 migra as cinco seções de edição de perfil (AddressSection, PhoneSection, DocumentSection, InfosSection, MarketingSection) para useProfile — adicionando apenas a rota /api/user/update-marketing, porque as demais reaproveitam proxies existentes — e deleta app/store/user.ts. d58617465 conclui a migração de auth, f161de1ab corrige o import de useAccountsStore na PixSection e 886e81f58 fecha os erros de tipo em TransactionCard e BonusWalletCard.
Rollover ficou plano.6c2b9c8 promove os campos de firstTransaction do rollover para o nível de cima e 9ca9cf5 adiciona lookupByPostalCode e maxBonusWithdrawAmount no topo; 10c9d48, 2b5f002 e e0ca444 simplificam a transformação de wallet em cima disso. e2f2f61b6 ajusta o BonusWalletCard para o novo shape.
Semana 06–12/04 — Onboarding de depósito: banner de bônus, auto-abertura e prefill
FirstDepositBonusBanner entra no DepositModal (94fe5c7b7), visível enquanto o formulário de depósito está ativo, para expor a oferta de primeiro depósito no exato momento da decisão. 62ff8e4a1 ajusta a margem e renomeia o maxLabel não consumido para _maxLabel, mantendo o Biome quieto sem apagar o campo.
O modal de depósito volta a abrir sozinho para quem tem saldo baixo (bf390c85e), replicando o useOpenModalAfterTime do front Vue/Nuxt legado: abre após login ou registro quando o saldo é ≤ R$ 0,99, pula contas restritas (autoexclusão, somente-saque), respeita cooldown de 12 h gravado em localStorage, espera 1 s para que modais de validação e bloqueio tenham prioridade, e limpa a chave no logout.
?value= na URL pré-preenche o valor do depósito (c34c93d93), fechando o ciclo de campanhas que mandam o usuário direto para um valor sugerido. O namespace de i18n de pagamentos ganha as mensagens de bônus de primeiro depósito nos três idiomas (core f31c309).
Semana 03–05/04 — Rede 7k chega à Nigéria e à Finlândia
Duas marcas novas nascem no mesmo dia:ng-7k-bet (7c7bcbe0a) e fi-7k-bet (e83078a76) ganham árvore de override completa em overrides/<brand>/app/config/ — tema, features.config.ts, menu.config.ts, sidebar.config.ts, linhas de home/cassino e itens de navegação. O acabamento veio na sequência: 224653ac7 fecha o branding da ng-7k-bet, 750fd7f5c ajusta features e cores da fi-7k-bet, e 0359f4e2e / f6b0ce82c trocam favicon e ícones PWA de cada uma. Como overrides/* é ignorado por padrão no .gitignore, cada marca só passa a ser versionada quando entra na lista de exceções (!overrides/<brand>/) — é esse commit que "cria" a marca aos olhos do git.
Manifest PWA passa a sair do tema (1dff5bffc): theme.config.ts ganha um bloco manifest com theme-color e background-color, e a rota app/routes/manifest[.]json.ts lê dali em vez de ter os valores fixos — o mesmo bloco foi propagado para todos os overrides.
Licenciamento por jurisdição:24d0b6ebf padroniza o texto de licença entre as configs, 7f46e5604 troca o texto da ng-7k-bet para inglês e 9a9a38be0 ajusta o textLicense do licenses.config.ts dessa mesma marca. Marca nova em jurisdição nova não reaproveita o rodapé regulatório brasileiro.
Suporte de país no core:@cactus-agents/country-config ganha suporte ao documento NIN e a localização da Nigéria (8a5d11d) — é dessa config que o registro tira qual documento pedir e como validá-lo.
Novos componentes de Stories implementados — StoriesCircles, StoriesModal, StoriesOnlyButton e StoriesWithModal para exibição interativa de banners
Autoplay adicionado ao HomeBannerCarousel com remoção do skeleton loading
Controle de visibilidade por linha (visibility control) adicionado ao sistema de home rows com classes responsivas
Correções de estabilidade no StoriesModal: safeClose para fechamento seguro com overlay invisível, reset de progresso e timing corretos, ajuste de padding e role de acessibilidade
Widgets configuráveis: HomeBannerCarousel, TournamentsSection e demais widgets agora aceitam title, icon e i18nKey como props para maior flexibilidade
Criado novo pacote platform-cache no monorepo front-cactus-core, com engine de cache governada, policies de TTL/stale, e suporte a múltiplos stores (Cache API, KV snapshot, in-memory)
Publicada versão 0.2.0 do pacote @cactus-agents/platform-cache com changeset automático via CI
Integrado @cactus-agents/platform-cache no front-web-base: novo serviço platform-cache.server.ts substitui lógica de cache dispersa nos serviços de jogos e brand
Refatorado games.cache.server.ts adotando a engine centralizada
Atualizado brand.server.ts para usar a nova camada de cache governada
Rota de dev api/dev/cache-clear atualizada para compatibilidade com a nova engine