Pular para o conteúdo principal
← Voltar ao changelog

Changelog - 21/06/2026

Semana de 15/06 a 21/06. Daqui pra frente o changelog é semanal (arquivos YYYY-MM-DD-weekly.md, datados no último dia coberto). A fonte de verdade do front-web-base é a branch main-7k — a main está defasada e não reflete o que foi pra produção.

Semana 15–21/06 — cache overhaul: CACHE_GENERATION como token único de rotação

  • front-ops/config/cache/generation.yml vira a fonte operacional de verdade (ops f00c642): o arquivo carrega current: apcsrasj-v3, é lido no deploy e injetado como --var CACHE_GENERATION no wrangler deploy. Bumpar pelo workflow novo bump-cache-generation flipa de uma vez a namespace do Cache API do platform-cache, o cacheKeyPrefix do api-client e o GLOBAL_VERSION do front-service-api; sem o arquivo, o deploy cai no default in-source (fail-open). É separado do BUILD_ID, que já rotaciona a cada deploy — o CACHE_GENERATION é o "nuke from orbit" que o padrão legado de pasta-nova-por-deploy fornecia. cache-status.yml complementa como leitura read-only.
  • Base conectado à máquina nova (b445a6b5a): binding declarado no worker-configuration.d.ts; app/services/platform-cache.server.ts mantém um storesByGeneration chaveado pelo token, então o cache de isolate rotaciona atomicamente; app/services/api.server.ts deriva cacheKeyPrefix como api-cache-<gen> e liga delegateCaching: true nas rotas já cacheadas na camada platform-cache, eliminando o drift de TTL duplo que causou o postmortem de /payment-providers em 05/2026. app/routes/api/cache/purge.ts passa a delegar ao createPurgeHandler do core (mesmo contrato de tag/glob/scope/dry_run, com extractApiError no lugar de [object Object]) e nasce app/routes/api/cache/inspect.ts, endpoint GET que lista recursos, tags e namespace corrente e, com ?include=state, sonda o Cache API.
  • TTLs apertados e falhas de fallback visíveis (239651ff4): KV_SSR_TTL cai de 12h pra 1h (o valor antigo era resquício da premissa "rebuild a cada 12h"), entra MAX_API_CACHE_TTL = 3600 com clamp em getApiCacheRule, e erros de fallback de asset em KV e R2 passam a ser logados — antes eram engolidos em silêncio, deixando problema de permissão ou bucket invisível no Logpush. public/_headers reduz /icons/* de 1 ano pra 30 dias.
  • Defaults e purge seletivo no front-ops (b36e445): brandConfig sai de 3600s e homeRows de 7200s, ambos pra 60s + SWR 300s, então mudança de backoffice reflete em menos de 60s; toda resource ganha tags pra o purge mirar fatias em vez de derrubar tudo; staleIfErrorSeconds capado em 6h. manual-cache-purge.yml sobe pra v3 com tags (CSV), glob, scope e dry_run. 8645ac2 cria config/cache/service-api-defaults.yml com 19 regras consumidas no deploy do service-api — base e service-api passam a compartilhar a mesma taxonomia de tags.
  • skip_post_deploy_purge por environment (ops 2d83a4c, aplicado em 0d4437e e 64f130f): workers atrás de Cloudflare Access devolvem 404 no purge pós-deploy porque o curl segue o redirect de login sem service token. Até os service tokens entrarem no workflow, o environment pode sair do purge por segmento — a rotação do CACHE_GENERATION já torna as entradas anteriores inalcançáveis — e um step de notice registra o skip no run summary.
  • front-service-api com política externalizada (f80791d): DEFAULT_GLOBAL_VERSION = apcsrasj-v3, getGlobalVersion(env) lendo CACHE_GENERATIONBUILD_KEY → default, política vinda de env.SERVICE_API_CACHE_POLICY_JSON (era hardcoded) e /v2/cache/purge com o mesmo contrato do base. scripts/build-cache-policy.mjs resolve o YAML por --file, FRONT_OPS_PATH ou irmão ../front-ops. 27 testes novos, com 8d9fe4f documentando o fluxo no README.

PSI honesto — todo branch específico de bot foi removido

  • Bots passam a receber exatamente a mesma página que usuário real (08fd669a0). Isto reverte o padrão de otimização por bot documentado em abril: o root.tsx tinha um elemento decorativo de LCP falso (gateado por isBot || true, ou seja, renderizava pra todo mundo), o entry.server.tsx removia o script de boot da hidratação e reescrevia o viewport pra crawler, e useIsBot() gateava Slideshow, Marquee, VerticalMarquee, StepCarousel, CookieConsentBanner, os dois widgets de banner da home e useCustomThumb. Tudo isso saiu: bots hidratam como usuários, então o Lighthouse mede TBT/INP reais em vez de uma página sem JS, e a auditoria de acessibilidade passa a refletir o viewport de verdade. Mantido de propósito: o skip de isBotRequest na geração de remarketing-ID no loader do root — higiene de dado, invisível, não afeta o que o PSI mede.
  • Worker de edge sem discriminador de bot (5dad940a7): o isBot sai da chave de cache do workers/middleware.ts (o HTML é idêntico pra qualquer UA agora) e o guard !isBot no caminho de SPA-shell autenticado sai como defesa morta. Comentários obsoletos que ainda afirmavam mascaramento de bot foram corrigidos em oito arquivos.
  • Hack anti-FOUC removido (73c032fa4): o par <body style="visibility:hidden"> + visibility: visible !important escondia a página até o CSS chegar, mas o stylesheet principal já sobe render-blocking — o browser sozinho retém o primeiro paint. O hack era redundante em produção e arriscava tela branca se o CSS demorasse ou falhasse.
  • Scripts de terceiros voltam a carregar eager (74259e8a2): o third-party-scheduler tinha um encadeamento de gates (LCP + primeira interação + 7s + idle) e descartava tudo em auditoria sintética; evento disparado antes do GTM inicializar era silenciosamente perdido, sem fila de replay, então quem convertia sem interagir nunca era rastreado. scheduleThirdParty(fn) roda imediatamente e só o kill-switch thirdPartyScriptsDisabled sobrevive. O useAnalytics perde o gate !isBot e o atraso de 7s do pageviewReady, e sai o Meta Pixel duplicado e hardcoded do AnalyticsInitializer, que dupla-inicializava o pixel e vazava entre todas as brands.
  • Regra que fica valendo: o que for deferido por performance tem que ser deferido pra todo visitante, nunca só pra bot, pra o score continuar honesto.

Analytics — um page_view por navegação

  • page_view disparava ~59 vezes na home (c72d9eb4b). O useAnalytics() é chamado por cerca de 27 componentes só pra ler os métodos track*, mas os efeitos de init de tracker e de page_view viviam dentro do hook — então cada consumer disparava o seu, um por card de jogo montado. O antigo atraso de 7s mascarava o problema e ainda piorava: aquele gate era um ref virado por setTimeout, que nunca re-executava o efeito, então o page_view inicial na prática nunca era despachado (a queixa de "eventos desaparecendo"). Os efeitos foram extraídos pra um useAnalyticsBootstrap() de mount único, chamado uma vez pelo AnalyticsInitializer; useAnalytics() fica sem side effect.
  • Container GTM secundário no 7k, atrás de autorização5eb1fff32 adiciona, 222a93c1f gateia por autorização explícita e 12ab06e7d autoriza pra stage. Canal Floodlight DV360 opt-in em cl-bet7k-com e ng-7k-bet (0f14c99f4); Pendo na betpontobet-bet-br (59c60a10f); af2e11f6f empurra select_content pro anaLayer no clique do card de torneio.

Game assistant e drawer de pré-jogo

  • game-assistant: menu flutuante estilo AssistiveTouch dentro do jogo (252cd26b0) — botão mobile-only visível só em jogo fullscreen, arrastável com edge-snap, posição persistida por usuário e clamp inferior region-aware pra nunca sobrepor outros widgets flutuantes. Abre um card com saldo real ao vivo, stepper de depósito rápido reusando o CtaButton da casa, toggle de favorito e opções config-driven que abrem bottom sheets de carteira (com paridade de bônus/cashback), notificações, recompensas, missões, torneios e info do jogo. 7519bb64a sobe os labels como override de i18n no base (temporário, aguardando core) e 79cdfbd33 gateia a feature só na 7k-bet-br.
  • Missões e torneios filtrados por relevância do jogo (c4ea27e12): o util filterByGameRelevance(gameKey, providerName, items) aplica cascata estrita jogo-específico → provedor → todos, com tiers mutuamente exclusivos. Aplicado só nos sheets do assistant — MissionsSection, TournamentsSection, rows da home e páginas /vip ficam intocados.
  • Saga do cap de altura dos sheets, com causa-raiz encontradacf1c3fc8e, c80410889, 81af6a9e2 e finalmente 3cd78fe66: o SheetContainer do react-modal-sheet 5.6.0 sobrescreve containerStyle.height por detent depois do style do caller, e no detent content sobrescreve também o maxHeight — então nem CSS max-height nem altura fixa com snapPoints capavam. Só o detent default preserva o maxHeight, e é o que o modo capado passa a usar. e3ec07b27 fecha com back-to-preview e refresh de carteira.
  • Drawer de pré-jogo config-driven (ab7846ada): bottom sheet mobile intersticial que abre no toque no card, com hero, métrica de RTP/payout, CTA "Jogar agora" e rows "Confira também". O clique passa por useGameActivation, que mantém o <Link> como fonte de verdade da navegação e só intercepta em mobile + flag. Gateado por featuresConfig.preGameDrawer, ligado só na donald-bet-br. Iterações em dc965d465, 5c6978219, 386b3b352, a3f17dbc4; 8a21db3bd liga o widget "Pagou hoje"; c08362ccb faz o CTA já pedir o launch em tela cheia, eliminando o segundo toque.

Recuperação de chunk e tela de versão obsoleta

  • "Aba velha, deploy novo" deixa de virar erro cru (87cd10e94). Quando os nomes hasheados de chunk desaparecem do CDN após redeploy, qualquer import lazy num client defasado lança TypeError('Failed to fetch'). Entram app/utils/version.client.ts, fonte única de comparação de build-id (envolvendo o fetch de /api/version, rota do próprio Worker, confiável até com o BFF fora) que trata null como "não sei dizer" e não classifica como obsoleto, e app/utils/chunk-reload.client.ts, com isChunkLoadError(err) e auto-reload guardado por marcador em sessionStorage numa janela de 10s pra impedir loop, falhando fechado quando sessionStorage não existe. O entry.client.tsx liga listeners de error e unhandledrejection, e o ErrorPage ganha o estado chunkKind (pending, stale-version, generic) — enquanto o /api/version está em voo aparece spinner neutro em vez de piscar um 500 que vai virar a tela amigável. Suportado pelo core fd10a1d.

Esportes — First v4 e geometria do iframe

  • Token de launch da First deduplicado e navegação interna v4 corrigida (f9aa638f0): o endpoint de launch passa a ser escolhido pelo cookie is_authenticated e deduplicado por identidade de auth, então F5 de usuário logado emite um token em vez de dois; a URL de launch é cacheada por sessão (auth-keyed, TTL curto). eventlistTab e o chip da home passam a reload do iframe, porque o iframe v4 dropa deep-link de tab via postMessage; a URL do browser é sincronizada pelo LOCATION_CHANGE do v4, agora path-only.
  • Altura do iframe endurecida, com causa-raiz estrutural (8ee6dc32e): --mobile-nav-h era estática em tailwind.css (56px) com override imperativo em useEffect pra 64px só na família 7k — mutando a geometria depois do paint e criando race na montagem do sportsbook; as variantes illustrated, illustrated-tabs e grid-tiles renderizam alturas diferentes e nunca atualizavam a var. Agora o BottomNavShell publica --mobile-nav-h a partir do offsetHeight real do <nav> via ResizeObserver, no padrão de --header-h, com o valor estático virando fallback de SSR. Em paralelo, useSportsAvailableHeight ganha trailing-rAF, recompute pós resize/orientationchange e limpeza de --sports-h no unmount. Complementos: 41fd5fb44, b3fa7bc24 e 031159fc0.
  • @cactus-agents/sports-rogue avança de ^0.9.0 pra ^0.10.1 na semana (f03de4e16, ec4ba2555, d737034eb).

Auth, cadastro e validação

  • Cadastro BR não deixa mais submeter com CPF não validado (9da4ea87a): no fluxo de CPF não existe campo de data de nascimento — birthDate vem do lookup do documento. Quando o CPF já está cadastrado, o lookup falha com DOCUMENT_TAKEN e nunca preenche birthDate, mas o form deixava submeter; o validateRegisterInput então reportava REQUIRED_BIRTH_DATE → "Informe sua data de nascimento", mensagem sem sentido porque o campo não existe. Agora o submit é bloqueado e o erro real do documento aparece. Só dispara quando requestDocument && country === "BRA".
  • Saque não repete passos de validação já cumpridos (52a23e170): o perfil é atualizado antes de avaliar o gate, então módulos já validados do firstWithdraw deixam de aparecer como pendentes por snapshot defasado, e EmailStep/PhoneStep auto-avançam quando o campo já está validado em vez de travar no retorno "já validado" do BFF. O liveness por saque forçado por withdraw.frequent fica intacto. 50a536ccd sobe o ValidationStepsModal acima dos modais de pagamento prioritários.

Core / SDK

  • @cactus-agents/platform-cache (5334086): exporta DEFAULT_CACHE_GENERATION (apcsrasj-v3) como fonte única; CacheApiStore aceita cacheGeneration e logger opcionais, tornando visíveis erros transitórios de KV/Cache API; expõe findResourcesByTag, findResourcesByTagGlob e listAllTags; e ganha o createPurgeHandler({ engine, secret, originDomain }) compartilhado entre base e service-api. Mais de 80 testes novos.
  • @cactus-agents/api-client (0a897c2): ServerCacheConfig.delegateCaching permite pular por completo o cache próprio do api-client pra quem já envolve as chamadas com platform-cache; DEFAULT_CACHE_KEY_PREFIX passa a api-cache-apcsrasj-v3.
  • @cactus-agents/payments + i18n (665a089): contrato de Pagamentos v3 aditivo — roteamento por hub_payment_methods, client_request_id e provider_code no payload, PaymentStatusV3, normalizeDepositStatus e transformWithdrawResponse. Contrato legado inalterado quando os campos novos não vêm. No i18n, chaves de sucesso de saque nos 7 locales.
  • @cactus-agents/i18n (fd10a1d): stale_version_title, stale_version_message, stale_version_cta e show_details em layout.error, nos 7 locales.

Brand Overrides

  • donald-bet-br concentra o volume da semana. Destaques: depósito e saque em etapas (d563b9478), modais de auth com floating-label (67d067426), drawer mobile do sidebar flutuante com abas contextuais (9686ecdcd), menu do usuário em painel flutuante (95bc60355), home BFF-driven em modo misto (c96c25567), card de torneio showcase com filtros estilo cassino (55063e9e9) e detalhe redesenhado (64defee69, b81b021cb), home legada curada em 8 rows (827e76c79), grade in-place com banners 2-up (0920a10b2), menu de navegação rápida fixo no topo (603cbb055), filtro de provedor in-place (cf774c0e5) e o botão "Já paguei" do Pix verificando status antes de confirmar (f2ecc1c6d) e depois oculto (e8c17770d).
  • Redesign de torneio isolado atrás de config (df01e51ee): o redesign e os GamificationFilters restilizados tinham sido aplicados em componentes compartilhados, vazando o visual da donald pra todas as brands. Entra GamificationUiConfig com tournamentDetailLayout e filtersStyle (default clássico no base, donald flipando pra showcase/chip), mais headerStyle.authCtaUsesHeaderButtons (default false).
  • 7k-bet-br: "Copa dos Palpites" ganha acesso no menu lateral (2cba186bc), deep-link #copa-dos-palpites (5242e905d), pill alinhada em 40px (e33159645) e item no bottom nav (08962957c), e é renomeada pra "Bolão 7K" (206f77f7f). Bottom nav alinhada ao Figma (c2da25746), menus Cassino e Esportes iniciando recolhidos (c41c3b454), borda em gradiente na Copa do Mundo (248d7d45a), carrossel "Jogos do Álbum de Figurinha" no cassino (74ac10af3) e row da home renomeada pra "Top 10 - Álbum" (cf38b1f3f). 98703321e remove perfil e roletas do Xand Avião; 996e6697e adiciona a campanha "Roleta Premium Neto V2".
  • betpontobet-bet-br: Política de Privacidade Open Gaming v2.0 publicada (ecc42a8e0). Família 7k: 849f9d7a8 adiciona o export footerFollow que faltava nos overrides — sem ele a brand recebia undefined, o sintoma clássico de campo novo não propagado.

Pagamentos

  • Contrato Pagamentos v3 consumido atrás da flag paymentsV3 (8642d7475): flag nova com default false e casateste-com em true no dia zero, propagada pra todos os overrides. No depósito, client_request_id por tentativa (reusado no retry, renovado em "novo QR"), provider_code e payment_method encaminhados a partir do hub_payment_methods do provedor selecionado, resultado Pix usando expires_in, copy_paste e charge_id, e status normalizado por normalizeDepositStatus. No saque, client_request_id + provider_code e tela de sucesso distinguindo aprovado automático de pendente de aprovação. As rotas internas passam a expor o reason do BFF no envelope. Brand com a flag desligada mantém o fluxo legado byte a byte.
  • Polling de status por transaction_id, não charge_id (b6b561301): o endpoint /wallet/charge/{id} espera o transaction_id (ex. casatestecom_19502), não o charge_id numérico — o polling v3 mandava o charge_id e todo deposit-status falhava. Volta a usar sempre result.transactionId, no legado e no v3. b94c28b8a habilita a flag na cl-bet7k-com pra teste em stage.

Infra / CI/CD

  • fecadm ganha um uplift grande (5ca4a85): dark mode com tokens de tema substituindo zinc-*/white hardcoded, primitivos novos em components/ui/ (Table, Tabs, DropdownMenu, Avatar, Breadcrumb, Pagination, ToggleGroup, UserMenu) todos Radix-based e tematizados por token, CommandPalette global, botão de cache, husky e CI. Os ajustes de CI que fecham esse uplift caem na semana seguinte.
  • front-service-api-dev-proxy ganha deploy própriode4bd2e adiciona o workflow (wrangler deploy no push pra main), f2ff6ea documenta PROXY_FROM, o padrão de lookup de secret e o fluxo de deploy no README, e d4d57a5 resolve 3 erros de typecheck que travavam build estrito.
  • CODEOWNERS repontado pro grupo de ruleset novo em todos os repos: base 631d22020, core 19aea0a, ops 4f631f3, service-api 360c1f8, e2e def626b, dev-proxy 2af7019. Ops dd53d6b atualiza também as referências de team de deploy protection em vários environments.
  • Environment 7wins-cc criado (ops 8020ff6) e adicionado ao dropdown de dispatch do base (f00dc6b42, com 9856f63dd sincronizando com ops/main); ops daa9800 e base 63dafb4e2 adicionam o environment de esportes da betpontobet. c65a7564d remove as env vars mortas FAV_GAMES_API_URL e FAV_GAMES_API_KEY.

Documentação

  • Runbooks de cache no front-cactus-docs129618e publica arquitetura, estratégia e operação de cache, e 5dd9530 atualiza os guias de SDK e template pro platform-cache 0.14 e pro overhaul. É o último conteúdo substantivo que o repo de docs recebeu antes da lacuna que este lote de entradas semanais fecha.
  • 97aa0ee adiciona o guia de deploy/environments e corrige docs de CI/CD defasados; 67dcdd5 atualiza o required_team de deploy protection; a03ce81 adiciona template/favorites ao sidebar interno.