Pular para o conteúdo principal
← Voltar ao changelog

Changelog - 19/07/2026

Refino de UX da família 7k — ondas 4 a 7 e paridade cl/ng/fi

  • Janela desta entrada — cobre 13/07 a 19/07 (151 commits em main-7k, a branch de entrega viva do front-web-base; a main está parada desde 25/06 e não representa o que está em produção). Entradas semanais, não diárias.
  • Ondas 4, 5 e 7 fecham a série de refino visual do 7k-bet-br2de6e2187 (onda 4: modais de depósito, PIX compacto, "já paguei", valores sugeridos), 927f6b2e6 (onda 5: sidebar/nav, gamificação, home cassino, busca mobile) e 352b5beeb (onda 7: corrige hydration mismatch dos links de share, que piscava no F5). As ondas 1 a 3 caíram na semana anterior.
  • Paridade da família imediatamente depois32245acd0 replica as ondas 1 a 4 em cl-bet7k-com, ng-7k-bet e fi-7k-bet; fd3e7ad1c replica a onda 5 (sidebar/nav). O padrão do trimestre: o 7k-bet-br é a brand de referência e as três irmãs recebem o mesmo pacote em commit separado.
  • Barra mobile redesenhada com FAB central da marca (PR #1597) — b5a8d4f99 cria a variante mobile-nav-fab-logo: o item "Menu" vira um FAB circular com a logo da brand e o menu mobile passa a subir como bottom sheet em vez de drawer lateral, degradando pra tiles planos quando o special fab-center está ausente. af7e9bd23 (PR #1594) reordena os tiles pra Menu · Cassino · Buscar · Torneios · Esportes, com a busca no centro pelo alcance do polegar.
  • Tom global dos textos escurecido um pontoe45e597c4 troca #e6e6e6 por #e0e0e0 nos theme/colors.ts das 4 brands da família, cobrindo texts, links, titles e todos os sub-tokens; 4fb6b3eb5 já havia escurecido o fundo dos títulos de seção.

Motor de modais reescrito

  • react-modal-sheet e toda a cadeia framer-motion saem do bundle (PR #1569) — 306fe2063 reescreve app/components/base/Modal.tsx como CSS-only (useModalTransition mais keyframes do tailwind.css): desktop vira diálogo centrado com scale-in, mobile vira bottom-sheet com slide-up. Seis pacotes transitivos removidos. As props sheet-only saíram (disableSheetDrag, onSwipeDismiss, expandable, forceExpand, showCloseButtonOnMobile), maxHeightFraction foi reimplementado em CSS e um novo fullScreen atende o KYC.
  • Modais de auth de-lazyficados e abrindo antes da hidratação — com o Modal base em ~3 KB, LazyAuthModals virou AuthModals eager: abre no clique sem Suspense, spinner ou fetch de chunk (~15 ms medido em Slow 3G). 1781e87e3 (PR #1584) leva isso ao extremo — login/cadastro abrem ANTES da hidratação.
  • Modo below-header (flag authModalBelowHeader, ligada na 7k) — painel colado abaixo do header no mobile, sem overlay (o header segue clicável), título e descrição no lugar da logo, X à direita. e1fe087a0 (PR #1604) estende às demais brands da família.
  • Polimento em sequênciadc0ec3a74 mata o pisca na abertura e no fechamento, 3ecc95f77 transforma o X em overlay quando o modal não tem título, 983365ecd (PR #1701) estabelece o contrato de respiro, a405f8ce1 aumenta o botão de fechar. 75e414dda (PR #1632) impede a página de rolar por baixo de menu, painel, sheets e modais.

Header do usuário logado pinta no SSR

  • Cluster real no primeiro paint (PR #1584) — e588583b8 remove o lazy() e o gate hydrated && isAuthenticated do HeaderUserArea: Depositar, caixa de saldo, avatar e QuickAccessMenu renderizam no primeiro paint e só os DADOS mostram loading (o saldo pulsa até a primeira busca da wallet e, em erro, mostra traço com refresh em vez de um R$ 0,00 enganoso). Nenhum byte user-specific entra no HTML, então a variante logada segue compartilhável no cache de borda.
  • Fim do "deslogou sozinho" no F5 (PR #1586) — e59a37b08 resolve o caso em que o usuário logado recebe a variante anônima compartilhada do edge cache: um script inline no head lê o cookie non-HttpOnly is_authenticated=1 e marca data-auth-flag na raiz antes do primeiro paint, e o CSS esconde os CTAs de convidado. O DefaultLayout reconcilia pós-hidratação — cookie stale (sessão expirada, 401, clearAuth) remove o atributo e os CTAs voltam, integrado ao AUTH_FLAG_CLEARED_EVENT existente, então ninguém fica preso no skeleton.

Ganhos e estatísticas saem do payload SSR

  • useClientWins com foto por sessão1eb0c6d79 (branch feat/stage-spa-7d-shell-cache) introduz o hook com snapshot por sessão e hydrateWins; hydrateHome passa a aceitar wins opcionais. 9ff06f3fa cria o wrapper WithClientWins e converte os widgets de ganhos pra busca client-side, fora do payload SSR.
  • Rollout por superfície73b82f0b4 (home), f49fb4426 (hub, ao vivo, categoria, provedores, incluindo o grid "Pagou hoje"), 2eaa25b61 (showcase da página de jogo, fora do doc cacheado), 2450ccddb ("pagou muito" client-side com skeleton dedicado).
  • Endpoint consolidadoabc7b7fbe faz /api/games/top-wins devolver lastWins junto, servindo o widget combinado numa única request; 3fd1e821c reserva espaço durante o fetch e aplica slice de 30. Cobertura em 49b126c43, 2a7520483 e 14524727e (feed falho degrada pra vazio com 200; resposta não-2xx degrada sem quebrar).
  • Motivo de fundo: com o doc HTML cacheado por dias, qualquer dado volátil embutido nele nasce velho. Tirar wins do loader é pré-requisito da casca compartilhada — não é otimização de payload.

Cache de borda: serve-stale, TTLs por env e gate de build

  • SWR manual no Worker (PR #1625) — bf7347805 contorna um comportamento real da Cache API do Workers: ela honra s-maxage mas IGNORA stale-while-revalidate e não faz request-collapsing, então expirado o s-maxage o path popular dispara N re-renders de origem simultâneos. Atrás da flag SSR_SWR_ENABLED, a cópia é gravada com s-maxage longo (3600 s) mais o header interno X-Fresh-Until; no HIT fora da janela lógica o body stale é servido na hora (X-Cache: HIT-STALE) e UMA revalidação roda em ctx.waitUntil, com dedupe por isolate e cap defensivo de 200. X-Fresh-Until nunca vaza pro cliente e a flag OFF é byte-a-byte o comportamento anterior. Cobertura em b58057099.
  • TTLs viram env993b3bdca torna KV_SSR_TTL configurável via SSR_CACHE_KV_TTL; 088ee21a5 adiciona max-age de browser opcional no .data público via SSR_CACHE_DATA_BROWSER_TTL (default 0 = omitido).
  • Build-currency gate (PR #1595) — 99b9ca541 nasce do postmortem do stage-7k de 14/07: uma versão antiga do Worker continuou servindo tráfego com o warmer cron dela re-aquecendo o snapshot KV velho, imortalizando HTML de build antigo na entrada direta enquanto a navegação SPA vinha fresca. O gate usa um ponteiro global no KV (meta:currentBuild), checado 1×/min por isolate: o build mais novo assume o ponteiro e dispara self-purge one-shot do prefixo ssr:; o build órfão opera sem cache SSR, responde X-Cache: BYPASS-STALE-BUILD com no-store e o warmer dele vira no-op. Fail-open por design. O mesmo commit remove a perna caches.delete(name) do purgeSsrHtml — o runtime Workers não a implementa (jsg::WontImplement), então ela lançava em toda chamada e nunca deletou nada em produção.
  • Entrypoints unificados (PR #1637) — a27a8845e extrai workers/entry.ts e os três entrypoints (app.ts dev, app.deploy.ts prod, preview.ts) viram wrappers finos. Dois fixes passam a valer nos três por construção: o fallback self-recovering em 503 quando o pipeline SSR lança (antes só dev tinha o try/catch, prod estourava 1101 no edge) e o await do handleMiddlewareRoute, cujo retorno misto fazia um branch async que resolve null ser tratado como truthy — o Worker respondia null.

Streaming per-user e paralelização de loaders

  • Piloto na carteira (PR #1629) — c5b017fda dá loader à wallet montando a promise no servidor com o token do request e devolvendo-a DEFERIDA; o componente hidrata a store via efeito com guard anti-clobber e o fetch client-side segue como fonte de frescor. Seguro porque /user/* é never-public-cache.
  • Replicado em income-report e rewards (PR #1638) — 02b7248b7 aplica o mesmo padrão, matando o waterfall TTFB → JS → hidratação → fetch → BFF; ambas ganham clientLoader.hydrate=false pra navegação SPA não re-pagar o server. e17336ff0 e 91746a6a4 deferem o bootstrap do álbum e o loader de /perfis.
  • Loaders sequenciais viram paralelos (PR #1609) — 039603927 (help), 310ed3114 (blog), c4595a23a e 8b6e0ca27 (promoções, lista e detalhe), 5c9d77cd7 (colapsa a cadeia tripla do loader do post), 274103869 (catálogo em paralelo com slugs per-user nos favoritos), 498086231 (defere o getBase do catálogo de chips no hub e no ao vivo).

Conteúdo WordPress: cards podados e platform-cache

  • Fim dos documentos de 2,6 a 3,8 MB (PR #1624) — a204b68ec identifica a raiz: o WpPost cru carrega content.rendered integral, yoast_head_json e _embedded completo, e nas listas 100% disso é desperdício (o card usa título, excerpt, data e imagem). pruneToCardPost poda no fetcher CACHEADO, então a poda roda por revalidação e não por request. Medido em dev: /promocoes de 3.803 KB pra 212 KB, /blog de 2.604 KB pra 216 KB, detalhe de 3.652 KB pra 359 KB. A área faq mantém content.rendered porque o JSON-LD FAQPage usa excerpt ?? content.
  • Conteúdo WP ligado ao platform-cache (PR #1612) — 90d58aa92 conserta um BYPASS silencioso: o nome do resource incluía a URL dinâmica do WP e nunca casava com a policy, então o engine caía em bypassFetch e batia no WordPress em TODO request. Agora usa fetchWithKey com resources fixos e a URL, área e filtros viram sufixo de chave. Todos os fetches ao WP ganham AbortSignal.timeout(8s) — WP lento degrada pra stale ou vazio em vez de segurar o doc request.
  • Binding estourou o limite73dd212d1 (PR #1617) consolida os resources de conteúdo em 2 porque o binding de policy passou de 5,1 KB. b1a8efefd e 305e3d391 corrigem o CSS embutido de posts WP no mobile.

Modo perf-lite e corte de trabalho de GPU

  • perf-lite desliga animações de UI em dispositivo fraco80aaf44cf monta duas camadas com padrão cv-off: script inline pré-paint no head (cookie perf_lite, deviceMemory <= 2, deviceMemory <= 4 com effectiveType 2g/3g, ou saveData) mais um micro-benchmark de CPU pós-hidratação em idle, FATIADO em 10 chunks de ~1,6 ms com yield entre eles pra nunca virar long task (score = soma dos 8 melhores, threshold 64 ms, skip em aba oculta). O veredito persiste em cookie, então a próxima visita nasce lite pré-paint. O CSS de html.perf-lite zera animation e transition em 0.001 ms — nunca 0 nem none, preservando animationend pras state machines — com allowlist pro .animate-spin, porque spinner congelado passa a impressão de site travado. Canal SEPARADO do prefers-reduced-motion, que segue sempre honrado.
  • Decorações infinitas removidasaadbb621c (PR #1613) mata promo-pulse e gift-wiggle do header, f2a86e6d9 (PR #1610) remove o shine sweep das thumbs de jogo, ca688df6b (PR #1611) coloca gates de CPU no marquee horizontal (low-end, reduced-motion, off-screen).
  • Fundação (PR #1671) — 5793177de cria um cache em memória por sessão com API síncrona (getSessionSnapshot, putSessionSnapshot, clearSessionSnapshotsForTests). O módulo é deliberadamente "burro": os guards (nunca per-user, nunca Promise, nunca vazio) vivem no call-site.
  • Rollout964482698 (volta pra home instantânea no clientLoader), cd817b8dd (hub e ao vivo), 0e54a1963 (categoria, provedor e jogo por slug). 6c9e11c8d endurece os guards (userVote sob Fase 2, catálogo na home, isArray no ao vivo) e 91122af08 elimina a race de escrita do voteState entre efeitos de hidratação. 2cecf2fe5 faz favoritos re-hidratarem pós-login e recentes atravessarem dispositivos via seed remontado.

Listagens de cassino mais enxutas

  • Header fora, chips sempre visíveis (PR #1592) — bf3e45018 simplifica as 5 rotas de listagem (/cassino, /cassino/ao-vivo, categoria, provedor, /cassino/provedores) no branch "rows", valendo pra todas as brands exceto donald: saem InternalNavBar, título visível, botão de funil e busca local; as rows de chips renderizam direto e sempre abertas no topo. Objetivo declarado: jogos aparecem mais cedo na tela.
  • Follow-ups8fab28b2b (PR #1606), 7aebd0037 (chips uniformes), a6db92f40 (PR #1655: rows sem margem própria) e e4b7e4034 (skeleton do top-games segue a variante via config). b8d185efb (PR #1608) corrige o toque que não abria o jogo após rolar, removendo o scroll snap no mobile dos game rows.

Identidade Chile — primeira aparição

  • UI de RUT e data de nascimento no cadastroffe24094b adiciona RutValidationField (máscara mais módulo 11 via validateRut do core) e BirthDateValidationField (máscara DD/MM/AAAA), exibidos apenas quando country === "CHL", seguindo o padrão do ValidatedCpfField. Nesta semana é UI e mock apenas, sem integração de API — os textos ficam marcados como pendentes de i18n no core e o nome retornado é mockado. 0c6098d9e abre o stub de overview da feature em docs/superpowers, que vira a base das especificações das duas semanas seguintes.

SEO, versão e limpeza

  • Três vazamentos reais de indexação fechados (PR #1693) — 2629968fc parte de um reporte de páginas de conta e políticas indexadas; a auditoria com curl no HTML real mostrou que a maioria das rotas JÁ servia noindex,nofollow. Sobraram /usuario/notificacoes (registrada fora do user/_layout, não herdava o robots — ganhou meta próprio via mergeParentMeta), /usuario/validar/:type/:token (meta de leaf substitui tudo, então ficou sem robots) e o sitemap-legal.xml, que anunciava páginas noindex — sinal contraditório que ATRASA a desindexação, e a rota foi deletada.
  • Atualização silenciosa de versão (PR #1695) — 430e71061 remove o toast "nova versão disponível": fora da página de jogo, versão nova detectada dispara reload() direto; dentro de casino.play nunca recarrega no meio da sessão, deixando o reload pra próxima navegação. Guard anti-loop com uma única tentativa quando o CDN ainda serve HTML antigo.
  • meta() resolvia i18n pela instância errada (PR #1665) — 74d95ae64: 12 rotas importavam getI18n do react-i18next, mas o initI18n do core nunca registra initReactI18next, então esse getI18n retornava undefined SEMPRE e todo label traduzido de meta() caía no fallback em pt (o título da brand es-CL saía como "Promociones — Promoções - Bet7k"). Passa a importar getI18n de @cactus-agents/i18n.
  • Limpeza5cfc59d23 (PR #1616) apaga ~750 linhas de módulos órfãos da era pré-streaming com prova de zero referências (workers/spa-shell-sanitize.ts, app/services/faq-wp.server.ts, LazyGameSections, LazyHomeGamification); 8bea22d22 remove exports órfãos e símbolos mortos; 09eb0971d (PR #1639) zera os errors do Biome no baseline. afe4e602f devolve o título SEO completo à aba em navegação SPA.

Analytics e consentimento

  • Pendo desligado em todas as brands que o tinham (PR #1652) — 205ff80c6 é decisão de produto: enabled: false nas 4 brands que o habilitavam, com tokens e accountId PRESERVADOS nos overrides, então religar é voltar a flag. O mesmo commit registra que o Clarity já estava desligado por config em todas as brands (clarityId: null) e que qualquer Clarity observado em produção vem de container GTM, não do repo. O Pendo volta em cl-bet7k-com e ng-7k-bet na semana seguinte — é vai-e-vem, não estado final.
  • Banner de consentimento centralizado, depois corrigido066d5124c atende pedido de produto e move o banner do rodapé pra card flutuante centralizado, com apenas dois botões de largura igual (Personalizar, que abre os toggles, e Aceitar tudo). O wrapper usa pointer-events-none, então NÃO é backdrop: a página atrás segue clicável e rolável. "Recusar todos" e o botão-ícone de settings saem do banner por pedido explícito de produto, e a gestão granular passa a viver apenas no painel Personalizar. 8cb9f039d corrige a rota no dia seguinte: o pedido era centralizar só na horizontal, então o card volta ancorado no rodapé. O comportamento acima é o que o código faz; a adequação dele à política de consentimento precisa da confirmação do responsável por LGPD antes de virar posição publicada.

Core / SDK

  • @cactus-agents/brand 0.8.0 — breaking — core 116c234 (perf(brand)!: slim do BrandConfig) remove 26 campos sem consumidor depois de um grep app-wide no base e no core, incluindo destructuring: cssCode, themeColors, terms (~39 KB), footerExtraCode, texts, spaLimits e 20 flags de features viajavam no turbo-stream de toda página e em todos os tiers de cache. Removidos do shape e dos transforms na raiz, substituindo a poda manual que o base fazia no _layout. Os raw types (input do BFF) ficam intactos e core a6e73ef deixa os campos removidos comentados no fonte pra história ficar visível. Base consome via ce8ee8910 (types@0.7.0 + brand@0.8.0, com a poda manual do _layout removida).
  • @cactus-agents/i18n em três releases — core 91202f2 (copy curto das regras de senha mais status sr-only), ee81b30 (novo copy do flutuante de install-app) e 526adc7 (labels expandir/recolher do footer compacto). O base acompanha em a1595c059 (^0.97.0), c28e7feb2 e 0a5c0b3ed (^0.98.0) e 6e3084b6f (0.98.1); a release do footer compacto só é consumida em 20/07.
  • Cobertura de localização do Chile completada — core 613d134. No lado do base, 3d13e5ab9 conserta um furo relacionado: a família de blocos das páginas de conteúdo (footer, promotions, news, responsibleGaming, help_center, help) vive nos overrides de locale do base e havia sido adicionada só pra pt-br/pt/es/en — es-cl, en-ng e fi-fi renderizavam CHAVE CRUA em todas as páginas de conteúdo (bet7k.cl mostrava promotions.title no título e no breadcrumb).
  • @cactus-agents/sweepstakes2893b63 alinha o wire model de redemption e adiciona o endpoint de detalhe getRedemption; 9e2d4ad aceita page opcional em listRedemptions. É a linha de produto 7wins (sweepstakes dual-currency) evoluindo no core sem consumidor no base ainda.
  • @cactus-agents/sports-rogue 0.26.0 → 0.26.1 nesta semana (c567a438d, 0a5c0b3ed). O pacote é uma dependência real do base que não vive em front-cactus-core — é publicado de outro lugar, então os bumps aparecem só como chore no base.

Brand Overrides

  • 7k-bet-br: 89594836e limpa o topo da home (sem stories nem slide, label "pagou hoje", pills nas ligas); 8f2023521 abre cassino e esportes já no SSR da sidebar; 10ff733ec compacta o footer stacked; 345050f27 escurece a decoração dos cards ranqueados; d3736f003 põe o identificador do deploy no rodapé.
  • família 7k (br/cl/ng/fi): além dos itens já descritos nas seções acima (tom dos textos, bottom nav com FAB, modais below-header e full-height), e8c353f49 (PR #1661) troca o flutuante inferior pelo template 7games — ícone, título/subtítulo e X à direita, com o card inteiro disparando a ação — e liga o master, que estava false nas 4.
  • cl-bet7k-com: 2c5b53bc3 troca o wordmark BET7K do backoffice pela logo local "7K" via brandAppearanceOverride, mesmo padrão da donald-bet-br. Em todas as brands, 1f2efb01d remove a flag userPanelCompact e entrega o visual novo do painel de usuário.

Pagamentos

  • Modaisc5f8304a5 compacta o modal PIX "aguardando pagamento"; 921f9bc3f leva o depósito pra full-height no mobile na 7k e remove os valores sugeridos estáticos; 1a4398e0d faz o saque usar painel full-height sob a mesma flag; a9fe240fc (PR #1636) alinha o resultado do depósito com o X flutuante.
  • Formulários e senha192b9008c (PR #1622) tira o ,00 de mínimo/máximo e torna o saldo disponível clicável no saque; 8a3a59f98 corrige o sufixo de moeda do CurrencyInput estourando em telas estreitas; af3f51196 (PR #1623) remove o scale trick anti-zoom do iOS que desalinhava inputs. 19880bab0 (PR #1635), f7187824a e 4e4813e00 entregam o checklist de senha compacto em chips, com o popover de regras abrindo pra cima pra não cobrir o CTA.

Infra / CI/CD

  • BUILD_TS e guards contra versão órfã — ops 089d21d injeta BUILD_TS via vars do deploy (par do gate 99b9ca541 no base) e ops 2e6385a adiciona um probe de build servido com janela de propagação de ~3 min.
  • Canais de rollout por env — ops a2b743c cria a flag shared_public_doc_for_auth e liga no stage-7k; ops 4dc4897 cria o canal ssr_swr_enabled no mesmo env; ops 80ab174 declara as flags nos outputs do job check; ops ed43b61 transforma ssr_cache.* por env em SSR_CACHE_*_TTL sempre-com-default; ops 11792e9 mapeia data_browser_ttl pra SSR_CACHE_DATA_BROWSER_TTL; ops 81f22eb documenta a exclusão mútua entre SSR_SWR_ENABLED e data_browser_ttl.
  • Casca de 7 dias sai do experimento — ops 49c8d56 a estende pros envs bet7k-cl e cl-bet7k-com, ops b89b761 ativa a Fase 2 (doc público compartilhado pro logado) nesses mais o stage-spa, ops 1e895ee põe conteúdo e catálogo em 7d nos três, e ops 4d90e0c, 50beb31 e b5792fa normalizam o padrão em prod-7k-bet-br, stage-cl-bet7k-com, stage-7k e nos envs NG/FI.
  • Cache — ops 7d1ff12 adiciona 5 resources de WordPress à policy e ops 3ecc962 consolida pra 2 porque o binding estourou 5,1 KB (par do 73dd212d1 no base). Dois bumps de geração: ops 312f1c1 (apcsrasj-v14v15) e ops aa3e6e0 (v15v16). O valor operacional vive em config/cache/generation.yml no front-ops, rotacionado pelo workflow bump-cache-generation; o token em platform-cache/src/generation.ts é só fallback in-source quando nenhuma env é injetada.
  • Environments — ops c77038a cria sports-cl-bet7k-com-cactusgaming-tech (base espelha o dropdown em 00013f47e); ops 40f821f e bc478b1 ajustam default_branch dos envs CL; ops 6cb013f e 418a4c4 sincronizam os dropdowns de purge manual com config/.
  • Primeiro sinal do fork externo — ops e01a693 aponta default_branch dos envs cassino-bet-br e vera-bet-br pra main-external, e ops e8b0855 reativa auto_deploy no cassino-bet-br. A remoção das duas brands do front-web-base só acontece em 28/07 — aqui é a infra se preparando.
  • Sem entregas em front-tests-e2e, front-service-api, front-service-api-dev-proxy e fecadm nesta semana.