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.
Novo subpath @cactus-agents/utils/forms (core e020bd1): error-codes.ts com FormErrorCode (40 códigos cobrindo registro, login e fallbacks genéricos) e o type guard isFormErrorCode; error-resolver.ts com resolveErrorMessageKey(code) mapeando cada código para sua chave i18n em auth:register.errors.*, auth:login.errors.* ou common:error.*; e bff-error-normalizer.ts com mapBffValidateDocumentError, mapBffRegisterError, mapBffLoginError e mapBffFieldErrors. Substitui o padrão de inspecionar string crua do BFF em cada consumidor.
A taxonomia é propagada ponta a ponta no base (aaddf81d1): rota SSR → client de auth → estado do componente → chave i18n → string renderizada, no RegisterModal e no LoginModal. Bugs concretos que isso fechou: invalid_email exibia "Este e-mail já está cadastrado" (mensagem errada), invalid_document exibia "Este documento já está cadastrado" (errada), invalid_phone e required_document renderizavam só o label do campo ("Telefone", "Documento"), e envelopes crus do BFF chegavam à tela do usuário.
AuthError ganha code normalizado (core 8ea6c5b): o callAuth() lê envelope.code quando presente e o anexa ao erro lançado, mantendo envelope.error como fallback para chamadores ainda não migrados. O campo é string de propósito, para não puxar @cactus-agents/utils como peer dep de accounts. As chaves register.errors.* e login.errors.* entram no i18n com fallbacks genéricos (79bbf45).
@cactus-agents/api-client passa a extrair a mensagem estruturada do BFF em vez de despejar o blob JSON (05fe53d) — a outra metade do mesmo problema.
Área do usuário — 2FA, senha, contratos e informe de rendimentos
Autenticação de dois fatores fecha o ciclo (cf834fabe). Em /user/config, o TwoFactorSection passa a ler brand.features.authConfig.twoFactorAuthActive do @cactus-agents/brand (vem do BFF, sem override hardcoded por marca); o toggle dispara runValidationFlow({ context: "updateData" }) para que as exigências de password_check e kyc_id do backoffice gateiem a mudança, replicando o $containment.handle('update_data') do legado; a persistência vai por POST /api/user/two-factor, com o UserService.toggleTwoFactor do core como fonte única do endpoint e do payload; e refreshAuthProfile() roda antes do toast para o toggle não piscar. No login, o novo TwoFactorStep aparece dentro do LoginModal quando o BFF responde two_factor_code, reusando o OTPInput de 5 dígitos. Core: 0cd55d5 estende o TwoFactorPayload e alinha a cópia de 2FA no login.
Troca de senha ganha rota de API própria e mensagens de verdade (8c31b4ae3), com o extrator de erro refatorado para o novo shape de resposta; 1b115a308 pluga o fluxo de validação antes da troca e atualiza o payload. No core, 958585a renomeia os campos do payload de troca de senha no user-service.
Novo informe de rendimentos (c202bee7d): página app/routes/user/income-report.tsx mais as rotas de API income-report/available-years, income-report/generate e income-report/status.$id (o relatório é assíncrono — pede, recebe id, consulta status), aba nova em UserTabNavigation e feature flag para gatear. 316fa5af0 registra a rota nos paths de usuário de todos os overrides e e0c7701ea adiciona o ícone e esconde a aba quando a flag está desligada. Traduções no core em 2d45657.
Contratos e preferências:4fc547e24 re-busca o perfil depois de alternar um contrato e dá feedback visual da operação; ca762aa62 adiciona os links de navegação da seção de contratos.
6cc80a795 revalida o loader do _layout depois de login, registro ou logout feitos por modal — sem isso, o que foi pintado a partir do loader continuava mostrando o estado anterior até a próxima navegação.
Extrato mais legível:47b2cf470 melhora a categorização e o tratamento de status no TransactionCard e 51733e968 traz metadado de jogo e imagem responsiva para o card e o FullStatement. O core forneceu os helpers de exibição e a inferência de categoria com o tipo CategoryHint (960eba8, 19ea353, 34364c0, f9567cb).
Fundação do sistema em c4bf3a236:app/layouts/layout.defaults.ts (com defaultLayoutConfig e o helper defineLayoutConfig), app/layouts/layout-registry.ts como catálogo central que mapeia chave de string para componente de variante (header, sidebar, footer, painel direito, banner), app/config/layout.config.ts como ponto de entrada que a marca sombreia, e app/context/component-variants.tsx para micro-variantes (card de jogo, slide de banner). d1b41bbf1 faz o DefaultLayout consumir tudo isso e 1b249c110 formaliza o tipo LayoutConfig.
Reorganização estrutural que veio junto:8466da163 move os tipos de config para app/types/ (navigation.ts, deposit.ts, licenses.ts, topbar.ts) mantendo re-exports temporários, 44ed8961c remove esses re-exports e passa a importar de ~/types/ direto, 613806b4f move routes.config.ts para app/router/routes.ts, e 0cb19f4d7 move Header, Sidebar e Footer para app/layouts/variants/. ccbae60b0 tira o export de LayoutComponent do layout.config.ts para quebrar um import circular e 73e83a242 separa a lógica de notificação do topbar da config de marca.
Ganchos de variação sem fork de componente:53a875e8d dá ao header as props opcionais containerClassName, navAppearance e HamburgerIcon, adff72e48 passa className pelos componentes de sidebar, e 0228070e8 adiciona deepMerge com DeepPartial — usado por defineLayoutConfig para que a marca declare apenas os slots que quer mudar. Vale ser preciso aqui: o plugin de brand override continua substituindo o layout.config.ts inteiro; o merge acontece dentro desse arquivo, entre o objeto que a marca passa e o defaultLayoutConfig. 863754323 garante que as variantes da vera-bet-br componham os defaults em vez de substituí-los, para não perder funcionalidade.
Spec de design em e1f34a2aa, com a doc correspondente publicada em docs-internal/template/layout.md (docs d531e7e).
Nova variável CASSINO_MODE com três modos (1a5892021): legacy (default — BFF /casino-games/filter + home-rows.legacy.ts), api_new (BFF /casino-games/home + home-rows.new.ts) e front_custom, em que um provider base — escolhido por CASSINO_FRONT_CUSTOM_BASE — alimenta getAllGames() e as categorias vêm de app/config/categories.custom.config.ts, sobrescrevível por marca. O modo front_custom é estrito: slug que não está na config devolve vazio, sem fallback para o BFF.
As configs de linha triplicaram por página:home-rows, casino-rows e casino-live-rows passam a existir em .legacy.ts, .new.ts e .custom.ts, e o games.cache.server escolhe qual carregar conforme o modo. 0ffad3de0 adiciona ordenação personalizada na recuperação dos jogos.
e5e1aa376 fecha a armadilha do modelo de override: como o plugin de brand override substitui o arquivo inteiro, marca que sobrescreve X.legacy.ts e não sobrescreve X.new.ts / X.custom.ts cai silenciosamente no default genérico do base ao trocar de modo, perdendo stories, favoritos, banners e linhas próprias. O commit propaga os três arquivos em 10 marcas: .new.ts é cópia literal do .legacy.ts (só muda o nome do export) e .custom.ts converte as linhas type: "games-api" em type: "custom-category" por uma tabela de mapeamento (roleta → roletas-em-destaque, jogos-crash → crash-games, e assim por diante).
Core:@cactus-agents/games ganha categorias customizadas e ordenação por estatística para CASSINO_MODE=front_custom (5a95f81), implementadas como service factory que delega tudo a um baseProvider e sobrescreve apenas a resolução de categoria. c944f6959 semeia as categorias customizadas e a config de personalização da betpontobet-bet-br.
Jogos favoritos entram no base (b6c05edc9), com a FavoritesRow resolvida no servidor (a67697571, 0ef9355bb, 9f7265f09), botão de favorito na barra de detalhes do jogo (0c69aeec4, 3ddf7b9f3), checagem de autenticação para exibição (c349be745), rota própria (021cebbae) e ícone trocado de estrela para coração (0f9073f72).
Duas correções de reatividade que valem registrar:55b4e483d faz a linha de favoritos da home reagir a login/logout feitos por modal e 753541e89 hidrata os slugs logo após o login em vez de esperar um F5 — o padrão de ler auth de snapshot de loader não sobrevive a modal.
42aa819a6 remove a variável FAV_GAMES_BRAND e passa a derivar a marca de ORIGIN_DOMAIN, eliminando uma variável de ambiente por marca que existia só para isso.
Novo widget top-games alimentado pela API de sports-metrics (294584c2f): nova opção SPORTS_METRICS_API_URL, serviço app/services/topgames.server.ts, GamesCacheService.fetchTopGamesEntries(), componentes TopGameCard e TopGamesWidget, hidratação no store de jogos e o payout aparecendo no GameCard. 991f0dd00 liga o widget em todas as marcas e no default.
O visual do widget foi refeito várias vezes na mesma semana. O estado final: variante inline-badge substituída por um layout de showcase (e0b86c4a1) com variantes de estilo de rank configuráveis (80dd1b35d) — caixa de rank retangular recuada, cards com auto-size, borda colorida. Os cerca de oito commits intermediários de padding, thumb e margem não são leitura útil. Uma correção real no meio: 99554ac97 faz o widget pintar a partir dos dados do loader em vez do store Zustand, que chegava vazio no primeiro paint.
A política de cache do segmento faltava (ops faf37cc): sem entrada de policy para topGames, o engine caía em BYPASS e toda requisição de home batia direto na API externa. O segmento passou a espelhar o shape de topWins — ttlSeconds: 300, staleWhileRevalidateSeconds: 120, sem snapshot em KV.
2f227d261 sincroniza todos os overrides com os campos do config default. Como não há deep merge, campo ausente no override vira undefined para aquela marca — várias tinham derivado com o tempo. O commit auditou e preencheu topGamesRankStyle: 'outline-sideways' nas 10 marcas (com betpontobet-bet-br ficando em 'inline-badge', que estava testando a V2 do widget) e keepTrackingParamsInUrl: true em casateste, ph-state77, pt-state77 e state77.
Votos de jogo unificados (f38046fa5), com clientes separados para requisição pública e autenticada (7b2b16ede) e a resposta da rota reconstruída a partir do payload enviado (0646348be). Core: 5386b9d e 50ca212.
Missões, torneios e minigames passam a ter estado explícito (fbdef15a8, 833db0eac): filtragem, ordenação e visibilidade por estado, com 518fc5130 cobrindo bônus e filtros nas rotas de /vip/*. Core: 996dc77 adiciona os helpers de missão e o enum de status de disponibilidade, a58305b acrescenta o estado "em breve" e a lógica de exibição, 6715075 traz os utilitários de mini-game e 3f09b72 amplia as definições de evento e tipo.
Gate de autenticação onde faltava:40926469c na sidebar, 65e61a584 no MissionDetailModal e no MissionCard, b727910b7 no layout de VIP para visitante deslogado, e cf0c40301 bloqueando ações do Smartico para quem não está autenticado.
0be5bb8ed esconde minigames inativos quando showInactive é false (core 973a246 adiciona a opção ao GamificationModuleConfig) e 68c45917d inclui o estado de cooldown na filtragem — minigame em cooldown deixa de aparecer como jogável.
Skeletons próprios por seção (855a788ad, com a8b6ac20b ajustando as dimensões na MissionsSection), e 61bc83ce0 corrige o nome da variável de pontos de buy-in no MiniGameCard. Traduções de unidade de tempo e de missão futura/expirada no core (87faf15, e59f05e, 3d784fd).
ea9a47385 adiciona os scripts de service worker do Smartico messaging v2.
CHL_ACCOUNT_TYPES passa a ser fonte única de verdade no core (16fa23b), com os dados dos bancos chilenos e a UX de seleção (8cbbaae), as chaves i18n dos 7 tipos de conta (9209221) e o aviso de titularidade do RUT (92dee3d); c6a95b0 remove as chaves obsoletas, c807794 aperta a tipagem e ccd007b exporta a constante pelo barrel.
Compatibilidade com o backend legado:22db0ac normaliza na leitura os valores CUENTA_* antigos de bank_type, 4d532c8 roteia conta bancária genérica para /generic-bank-accounts/* e 766df14 + 9393516 alinham o GenericBankAccountRaw aos nomes de campo que o BFF realmente usa.
No base:d4aa9b3f1 implementa o dropdown de banco com busca e a ChlBanksSection, 8b50cbeeb faz o WithdrawForm consumir os 7 tipos compartilhados mais o aviso de RUT, e 38ace5941 casa os valores enviados com os do backend legado.
Depósito:8914b81ff corrige a altura do iframe de cartão de crédito, 95878f3a6 adiciona fallback robusto de cópia para clipboard em CopyableField e DepositResultPix (core f87c475 traz as traduções do botão de copiar), cab363979 instrumenta o valor depositado e 6ecd521e6 cadastra os valores de depósito em PHP.
Quatro marcas entram na semana:ph-state77-com (07e7c0277), pt-state77-com (12db5e58e), pb-bet (73a87ed3a) e rj-bet (f2b9fbd60) — cada uma com árvore de override, entrada no ci-deploy.yml e exceção no .gitignore; b7bc3e6a2 completa os ambientes de pt-state77-com e ph-state77-com.
Core:@cactus-agents/country-config ganha Portugal (packages/country-config/src/countries/prt.ts + registro, 7e6aa03) e Filipinas (phl.ts, f6e02a4) — pré-requisito para o registro validar documento e telefone nesses países.
vera-bet-br recebe bootstrap completo em 16/04, portado do legado: tema e cores (33e3408ac, 58ed62b96), HeaderVera com hambúrguer de 3 barras e navegação em abas (52fb999d7), painel direito de maiores ganhadores ao vivo com a nova rota GET /api/games/top-wins (da49adce9, escondido abaixo de lg em a6f3d8f04), licenças com o textLicense real do legado (73b4413b7), configs de cassino/sidebar/rotas/thumbs e de analytics/SEO/LP copiadas da betpontobet-bet-br (568d48272, 377e63be7), First como sportsbook principal (3f0978e65), notificações de topbar sem torneio nem push porque o legado da marca não tinha programa de gamificação (72e429f63), CDN de imagem (1457e2207), ícones PWA (9b7998390) e o helper /twa.js do Telegram (f87be872d). O layout final ficou em coluna única com sidebar estreita (f96a9057d).
e8107bad2 faz o roteamento suportar landing page específica por marca mais os redirects legados, e 51951d34e manda as URLs legadas de autenticação para a home.
Varredura de strings do fornecedor que chegavam ao browser (70984c492), em três frentes. Primeira: os loaders de home, detalhe de jogo e favoritos devolviam _debug com as respostas cruas do BFF em todo request, serializando baseRaw/gameRaw/winnersRaw — inclusive URLs de thumbnail do CDN do fornecedor — dentro de window.__reactRouterContext; o novo app/utils/debug.server.ts passa a gatear isso por ?EnableDebug=1. Segunda: as 11 marcas apontavam gamificationConfig.smartico.libraryUrl para o CDN do fornecedor e passaram a usar /proxy/smartico.js, o que exigiu o vite-plugins/dev-proxy-mirror.ts porque o cloudflareDevProxy() não executa workers/app.ts e a rota 404aria em dev. Terceira: o prefixo de localStorage do useFavorites saiu de cactus:favorites:<uid> para brand:favorites:<uid>.
Core, breaking:2205b4b renomeia o parâmetro e a chave de debug para nomes neutros — ?CactusEnableDebug → ?EnableDebug e sessionStorage["cactus_debug"] → sessionStorage["debug_enabled"]. Abas abertas com a chave antiga perdem o estado de debug e precisam reativar via ?EnableDebug=1.
9a687fb75 renomeia o chunk de vendor de vendor-cactus-lazy para vendor-cts-lazy, e 08c8021c8 (com 4bdb1245e) troca o preconnect, o dns-prefetch e o <script> de inicialização de statics.cactusgaming.net para statics.ct-bt.com.
Zoom involuntário do Safari iOS ao focar input resolvido (c9722e1f3): maximum-scale e user-scalable na meta viewport, ajuste por user agent e touch-action no CSS; cba614802 refina os limites e f70960423 remove o !important do font-size que a primeira versão tinha usado.
Detecção de dispositivo centralizada (3491378c6): novos app/constants/breakpoints.ts e app/context/device.tsx substituem checagens duplicadas em GameIframe, Marquee, VerticalMarquee, DepositResultPix, DepositResultWallet e AuthBannerLayout. Junto, e12b4d82d troca useClientEnv por useIsBot nos componentes que só queriam saber se era crawler.
Pull-to-refresh no mobile (7f615c566), habilitado por configuração nas marcas (97435aa19).
CSS do Tailwind deixa de bloquear a renderização para crawlers (5849ff0f6): um script inline de ~150 bytes no <head> detecta o user agent de bot (Lighthouse, PSI, Googlebot, GTmetrix, bingbot) e converte a folha de estilo para carregamento assíncrono (media="print" + swap no onload). Usuário real continua com CSS blocking. 11d1d1e4b acrescenta fetchpriority e restaura o atributo rel.
Acertos visuais menores: be2c946a3 no padding do header do Modal, 325a9d880 e be72f96f1 no overflow e no scroll do carrossel após reordenação por estatística, d6cc0ce65 e 53009a4c0 no contentMaxWidth do tema.
O dia 21/04 tem uma corrida de cerca de 25 commits de assunto genérico (feat: test1, feat: test with fake lcp, feat: limit assets, feat: try with min chunk size, fix: chunks, feat: caches, feat: change preload only for mobile, feat: disable analytics, entre outros) mexendo em vite.config.ts, app/entry.server.tsx e workers/middleware.ts. É uma sessão de tentativa e erro medindo LCP, tamanho de chunk e camadas de cache — descrita aqui pelo que é, não commit a commit: nenhum deles carrega intenção documentada e vários se anulam. O que sobreviveu está no estado final desses três arquivos.
Ferramental que saiu com conclusão clara na mesma semana:ad93748f5 faz o dev server, os testes e o typecheck lerem @cactus-agents/* direto de ../front-cactus-core/packages/*/src/ quando o core está clonado ao lado — novo helper buildCoreAliases com regex ancorada, para @cactus-agents/accounts não colidir com o subpath @cactus-agents/accounts/react, e dedupe expandido para react, zustand, i18next e use-sync-external-store evitando "Invalid hook call". e2ab3cc0a faz o mesmo para os JSON de locale e 3ccbee47b apaga o tsconfig.dev.json, fundindo seus paths no tsconfig.json com dois alvos por pacote (source no core, node_modules como fallback), de modo que editor, dev local e CI usem o mesmo arquivo.
79f2694b1 conserta um furo perigoso do push gate: com o core clonado ao lado, o pnpm typecheck do pre-push resolvia @cactus-agents/* para o working copy local, incluindo tipos ainda não publicados. Isso quebrava o push de quem não tinha o core sujo e, pior, deixava passar commit que quebrava CI, produção e a máquina de todos os outros. O gate passou a validar contra a árvore do registry.
42b237515 regenera o lockfile sem pnpmfile; 27d353641 adiciona .worktrees/ ao gitignore para workspaces paralelos; 1a170bc9b dá método de refetch e suporte a body ao DevApiDebug.
pb-bet: texto de licença e selo primário (1db903e03), informações do operador (9e6a23a38), rótulo "Casino" corrigido para "Cassino" no menu (da691116c) e sidebar de esportes com labels em pt-BR (9418cc3ef). 9f2090c69 traduz os nomes de liga na sidebar e nas configs de home.
vera-bet-br: bootstrap completo em 16/04 (detalhado acima). A decisão sobre gamificação virou no meio da semana: o bootstrap seguiu o legado e não expôs notificações de torneio/push (72e429f63), e em 20/04 o programa Smartico foi ligado na gamification.config.ts (74eeeac4e, c59ef1257). Também ganhou flag de jogos favoritos (9f538b00b) e novas notificações e configurações (e7daaad40).
betpontobet-bet-br: categorias customizadas e config de personalização semeadas (c944f6959), favoritos ligados (f7a9bb91c) e topGamesRankStyle: 'inline-badge' mantido como teste da V2 do widget (2f227d261).
state77-com: jogos favoritos ligados e linha correspondente na home (9671c178a). Junto com casateste-com, ph-state77-com e pt-state77-com, recebeu keepTrackingParamsInUrl: true no alinhamento com o default (2f227d261).
Todas as marcas: widget top-games nas linhas de home (991f0dd00), paridade de .new.ts / .custom.ts (e5e1aa376), rota de informe de rendimentos nos paths de usuário (316fa5af0), rota de favoritos (021cebbae), configuração de First por marca para visibilidade de rodapé e bottom nav (92b57a7e2, ed3cbf40f, com o suporte no core em 974f241) e variantes extras de apple-touch-icon em 8 overrides (4df2976d1).
Pacote @cactus-agents/accounts nasce unificando auth, user e wallet, com o subpath /react cobrindo saldo, wallet, transações, perfil, auth e recuperação (bumps 0.2.0 → 0.14.1 na semana).
Pacote @cactus-agents/utils ganha o subpath /forms com FormErrorCode e os normalizadores de erro do BFF, e renomeia o parâmetro de debug para nomes neutros (breaking, 2205b4b).
Pacote @cactus-agents/games ganha categorias customizadas e ordenação por estatística para CASSINO_MODE=front_custom (bumps 0.19.0, 0.19.1, 0.20.0).
Pacote @cactus-agents/gamification ganha showInactive no GamificationModuleConfig e os utilitários de missão e mini-game (bump 0.10.0).
Pacote @cactus-agents/payments ganha CHL_ACCOUNT_TYPES, os dados de banco chileno e o roteamento de conta genérica (bump 0.12.1).
Pacote @cactus-agents/api-client extrai a mensagem estruturada do erro do BFF (05fe53d) e adiciona sanitizeHeaderValue para limpar caracteres não-ASCII de header (bfec991).
Pacote @cactus-agents/platform-cache respeita o modo cache-only sob BYPASS (2cff12a).
Pacote @cactus-agents/brand normaliza link social vazio para null (bacf270) — o base passa a esconder o ícone quando o href é vazio ou só espaço (ba687c484).
Pacote @cactus-agents/i18n recebe register.errors.* / login.errors.*, rótulos de estatística do balão de cassino (53cb484), as chaves de informe de rendimentos, os tipos de conta chilenos e os labels "Em breve" (153831c); bumps 0.51.0 a 0.57.0.
Pacote @cactus-agents/sports ganha as opções de visibilidade de bottom nav e rodapé nas páginas do First (974f241).
Proxy do Cactus Sportbook (c245b13b7) para as requisições de iframe, com repasse de header e log de erro melhorados em 5a9fc7db6.
Observabilidade:bf430e8f9 e ff7d40677 reorganizam o log de erro e as configurações de observabilidade do worker.
e1edef551 executa o plano de limpeza de violações:text-yellow-500 → token text-warning em SportsBetby, SportsAltenar e SportsIframeFirst, e String(err) → extractApiError(err).message nos mesmos arquivos mais o useAuthProfileSync — String(err) sobre objeto de erro produz [object Object] na tela.
16fac9903 sobe a qualidade de imagem de 20 para 50, e 01c76557e centraliza a resolução de URL de imagem das promoções.
e9a63a225 inclui arquivos CSS no lint do pre-push e troca o comando para biome check; 7206e88ef dá rótulo de navegação opcional às páginas 404; 06e1874a5 preserva a capitalização de siglas nos links do menu de regras; 4b9a1f005 troca caracteres Unicode soltos por emoji e texto.
Ambientes: ops 5eb1fad (pb-bet), b8e0a61 (pt-state77 e ph-state77), e3bfc5a (rj-bet) e 1d44584 (stage-vera-bet-br, espelhado no base em 18baf5198 / 58c595024).
docs-internal/template/layout.md reescrita para o sistema de composição (docs d531e7e), junto com atualizações em overview.md, routing.md e no guia de fork refletindo app/router/routes.ts e app/types/.
Fluxo de desenvolvimento local reescrito para o modelo source-direct (docs ac3e967): sai o pnpm link / file: com pnpm build e tsup --watch, entra o alias que lê src/*.ts do core clonado ao lado. Complementos: 47d0675 documenta o split dev:base / dev:docs, 678468c, ab2098e e 680c16b cobrem exemplos de marca no feca dev mais feca update, feca kill, feca install e sync --install; 562b771 registra a unificação dos tsconfigs.
docs-internal/architecture/auth-flow.md ganha a regra de reatividade de UI (docs 0fa98ae): componente deve ler auth de useAccountsStore (reativo), não de useRouteLoaderData("routes/_layout") (snapshot de SSR), porque login e logout por modal só mutam a store — não navegam nem revalidam loader. É a regra que os dois bugs de favoritos desta semana produziram na prática.
Docs de cassino reescritas para os três modos (docs 4c5caec): LEGACY_CASINO_ENABLED sai, CASSINO_MODE e CASSINO_FRONT_CUSTOM_BASE entram nas tabelas de env e na doc de deploy, e a doc externa de jogos ganha a tabela de modos com o triplicar de linhas e um exemplo de seed de categoria com orderBy e displayPriority.
Rot de caminho corrigido (docs 3a1946c): várias páginas ainda citavam app/config/overrides/<brand>/ como local do override; o caminho real, e o que o plugin do Vite resolve, é overrides/<brand>/app/config/. 6559bff alinha a doc de utils ao rename do parâmetro de debug e a9bb08f remove o GAMES_CACHE_TTL já extinto.
Specs e plans passam a viver centralizados no workspace: cada repo ganha um symlink local para front-dev/docs/superpowers/ e o adiciona ao .gitignore para não versionar o alvo duas vezes (base ee37afe86, core da33175, ops 4e99013, docs d130c70). 15751757c e fb393fa16 removem do base os documentos que migraram, incluindo o CLAUDE.md local, hoje consolidado no hub do workspace.