Pular para o conteúdo principal

21 publicações com a etiqueta "pagamentos"

Ver todas as etiquetas

Changelog - 09/08/2026

Perfil único de resolução para a arte de jogo

  • Janela desta entrada — cobre 03/08 a 09/08 (25 commits em main-7k). É a entrada mais recente do changelog; 10/08 ainda estava em curso quando ela foi escrita, e os dois commits daquele dia que fecham a poda de environments estão anotados no fim, em ## Infra / CI/CD.
  • O Cloudflare Images codifica o transform no PATH, então cada combinação de largura, altura e recorte é um RECURSO distinto (PR #1876) — 1b6b8e904 parte dessa constatação: cache-key de browser própria, entrada de cache CF própria e download próprio pra cada variação. O app tinha 12 superfícies pintando game.image com 4 recortes e 10 ladders diferentes, nenhuma compartilhando nada. Medido no 7k mobile (iPhone 14 Pro Max, DPR 3, 3G): o card do carrossel pedia width=240,height=300 (10,0 KB) e a página de jogo pedia width=320,height=400 (13,5 KB) — 23,5 KB pra mostrar a MESMA arte duas vezes, com o segundo request entrando frio no 3G do usuário e a arte piscando ao abrir o jogo.
  • Pior: os degraus grandes eram upscale. O master da arte de jogo no CF é 300x350 (amostrado sobre 12 assets reais da biblioteca), então 320, 447 e 480 inventavam pixel — width=480,height=600 devolvia 21,5 KB de nada, o dobro do degrau que a listagem já tinha em cache. O teto útil é ~300px de largura.
  • O que passa a valer~/utils/game-artwork centraliza ladder e fallback num perfil único e cada superfície declara só o seu sizes, que é o slot de layout real. Não há mais recorte no servidor: o enquadramento vai pro CSS (object-cover numa caixa de aspect fixa), então card 4/5, poster 59/79 e thumb de proporção natural passam a compartilhar o MESMO arquivo. O ladder default vai de [144,216,288] pra [128,192,288] — o degrau do meio serve DPR 1 e precisa ficar logo acima do maior slot (186px, a thumb do preview da página de jogo) sem nenhum degrau entre ele e o menor slot de card de desktop (140px); com 216 o card pegava um degrau e o hero era empurrado pro seguinte, baixando a mesma arte duas vezes no desktop. As 5 brands size: "compact" passam a [128,192,240], cortando ~25% dos bytes e da memória de bitmap decodado. Fundos borrados e reflexos reusam as props EXATAS da thumb em vez de baixar uma segunda variante recortada só pra ficar sob um blur().
  • Guarda-chuva contra regressão — 11 testes de perfil mais uma auditoria de TODAS as brands (56 casos) que falha se alguém reintroduzir um degrau entre o card e o hero, inclusive em brand nova. THUMB_ASPECT_VALUE foi removido porque existia só pra alimentar o recorte no servidor e mantê-lo era convite pra refragmentar.
  • A convergência que faltava (PR #1877) — a97d91545: o perfil único convergia em DPR maior ou igual a 2 (todo celular real) e em DPR 1 no desktop, mas não em DPR 1 com viewport estreito, onde os slots divergem de verdade (o card declara 115px e a thumb do preview ~152px, com o degrau 128 exatamente no meio). O fix faz as superfícies da página de jogo declararem o slot do CARD no mobile: GAME_PREVIEW_ARTWORK_SIZES passa a espelhar os breakpoints do card e o GamePageHero da donald vai de 131px pra 128px. É uma sub-declaração deliberada de ~19% — em DPR 1 estreito a arte vem 128px numa caixa de ~152px, imperceptível.

Changelog - 28/06/2026

Semana de 22/06 a 28/06, na branch main-7k do front-web-base.

  • O baseline de boot do Google Consent Mode v2 foi invertido pra granted (16bf59fee). Isto reverte o comportamento descrito no changelog de 23/04/2026. A política antiga emitia gtag('consent','default', { ...tudo denied, wait_for_update: 500 }) e só depois, se houvesse cookie salvo, aplicava um update. A nova emite gtag('consent','default', { ...tudo granted }) sempre, sem wait_for_update. O único caminho que ainda rebaixa sinais é cookieConsentCosmeticOnly === false e cookie salvo indicando rejeição total, caso em que o initGTM dispara um update imediato pra denied. Matriz implementada: cosmético truegranted (qualquer cookie ignorado); cosmético false sem cookie ou com aceite → granted; cosmético false com rejeição total → default granted + update imediato pra denied. Arquivos: app/utils/metrics/consent.ts (injectConsentDefaults com opts.applyDenied) e app/utils/metrics/gtm.ts (decide applyDenied = !cosmetic && userRejectedAll), com 4 casos de teste. A justificativa registrada no commit é paridade com o app Nuxt legado, que nunca gateava tracking, e a eliminação da janela cega de 500ms do wait_for_update, apontada como causa suspeita da queda de performance em Google Ads e Meta Ads após a migração.
  • cookieConsentCosmeticOnly passa a ter default true no base (be0518d91). Antes o default global era false, então brand que não declarasse a flag honrava a rejeição do usuário. As 7 brands que já declaravam true seguem idênticas; as 8 que herdavam false (casateste-com, donald-bet-br, pb-bet, ph-state77-com, pt-state77-com, rj-bet, state77-com, x2b-bet) passaram a declarar false explicitamente no próprio override — comportamento preservado bit a bit, com o ganho de que cada override é agora a fonte autoritativa da política de consent daquela brand, sem depender do default do base.
  • Nota de revisão pendente: as duas mudanças acima descrevem o que o código faz hoje. A política resultante — consent concedido por padrão, tratamento cosmético como default e ausência de botão de rejeição total no banner — ainda depende de confirmação do responsável por LGPD antes de ser publicada como política oficial. Registrado aqui como fato técnico, não como posição de conformidade.
  • Eco do gtag duplicando eventos do dataLayer corrigido em ea9b09a68.

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.

Changelog - 31/05/2026

Semana 25–31/05 — Governança: CODEOWNERS em todo repo + gate de autorização de deploy

  • CODEOWNERS chega a todos os repositórios de front045206ec2 no front-web-base, e93a938 no front-cactus-core, 296deb8 no front-ops, 333c4f3 no front-tests-e2e, da59ea2 no front-service-api e dfd3af6 no front-service-api-dev-proxy. A regra default é * apontando pro time de codeowners de front — qualquer arquivo do repositório passa a exigir review de quem está no time, e adicionar codeowner virou uma mudança de membro de team no GitHub em vez de edição de arquivo.
  • .github/ endurecido com owners explícitos848c853a6. A ownership default segue no time, mas .github/ (workflows e o próprio CODEOWNERS) passa a exigir aprovação nominal de dois owners específicos. A justificativa está no commit: arquivos de governança não deveriam ser mergeáveis só porque qualquer membro do time aprovou — uma aprovação futura maliciosa ou distraída bastaria pra neutralizar a proteção. A sintaxe é gitignore-like com last-match-wins: a regra mais específica abaixo substitui a default acima, não faz união.
  • Gate de autorização para workflow_dispatch de deploy — front-ops 5dbdcb5 adiciona o campo opcional deploy_protection.required_team no deploy.yml de cada ambiente. Quando presente, deploys manuais via workflow_dispatch naquele ambiente ficam restritos a membros do time nomeado; push (auto-deploy) nunca é gateado por esse campo e continua disparando exatamente como antes. A implementação consulta GET /orgs/.../teams/.../memberships/<actor> com um token que passou a carregar read:org, e falha rápido com erro linkando o time. Aplicado aos 13 ambientes de produção do web-base — todos sem prefixo stage-/dev-/performance-, menos os dois ambientes internos.
  • Gate movido pro job check3d645e8 (mais o gêmeo ee5751e) reposiciona a verificação: o gate é uma pré-condição, como a checagem de elegibilidade de auto-deploy que já existia, então pertence ao job que valida inputs e resolve config. O ganho concreto é a forma da falha na UI — vira check ❌ → deploy skipped em vez de check ✅ → deploy ❌, que sugeria falsamente que o deploy tinha sido tentado. Sem mudança de comportamento: mesmo schema de campo, mesmas checagens, mesmas mensagens de erro.

Changelog - 06/05/2026

Pós-registro & Auth — fluxo regulatório e dedup de bursts

  • Novo hook useAfterRegisterFlow (app/hooks/useAfterRegisterFlow.ts) orquestra o pós-registro: abre o modal de depósito uma vez, logo após o cadastro, bypassando o throttle de 12h do useAutoDepositModal. Replica o handleOpenRegisterStrategy → openModal('deposit') do handleSuccessRegister legado em Vue. Suporta o ramo regulatório (espera o LimitsStep do ValidationBlockerOverlay resolver antes de abrir o depósito) e suprime quando há ?deposit=<campaign> na URL, conta restrita ou featuresConfig.autoDepositAfterRegister === false.
  • Store app/store/onboarding.ts (Zustand, não persistida) carrega o sinal justRegistered + lastPrudentialLimitActive entre o sucesso do RegisterModal e o próximo render do DefaultLayout. Reset automático no logout.
  • Forward de user_prudential_limit_active no payload de signup (/bff/register-simplified, /auth/register): sinaliza ao BFF qual botão regulatório o usuário clicou ("Quero definir meus limites agora" vs "Continuar sem limites"). Nova feature flag autoDepositAfterRegister propagada nos 13 overrides de brand.
  • Dedup cross-request de /auth/user-profile em app/services/auth.server.ts: cache token-scoped com TTL de 10s + cap de 100 entradas (chave = SHA-256 hex do token, evita expor token cru em dumps de memória). Resolve o burst pós-login onde POST /api/auth/login, useAuthProfileSync → GET /api/auth/profile e revalidator.revalidate() → _layout loader pegavam três Requests distintos com o mesmo token — o WeakMap<Request> antigo não conseguia deduplicar.
  • /api/auth/profile agora consome getAuthForRequest em vez de chamar createAuthFromClient direto, herdando automaticamente o cache acima. PRs touch-up em 20+ componentes (UserSummaryHeader, ValidationContextGate, GameIframe, payments, protection, validation steps) que liam useProfile() ad-hoc.

Changelog - 01/05/2026

FTD Onboarding — três fluxos novos consolidados (stage-ftd)

Maior entregável do dia. A branch stage-ftd aterrissou três fluxos completos de retenção/conversão D0, todos brand-configuráveis e cobertos por testes:

  • FTD Offer ("Oferta Relâmpago") — modal + floating widget + story thumb com Quick Deposit embutido. Componentes em app/components/ftd-offer/ (Provider, Modal, FloatingWidget, StoryThumb), storage isolado por marca em ftd-offer-storage.ts e analytics em ftd-offer-analytics.ts.
  • FTD Cashback — fluxo D0 com modal de oferta inicial (FtdCashbackFirstModal), modal de prêmio (FtdCashbackPrizeModal), Provider, dev panel, scaffolding de tiers (ftd-cashback-tiers.ts) e persistência local (ftd-cashback-storage.ts). Testes cobrem storage e cálculo de tiers.
  • FTD Check-in — daily check-in com mock fixture, logs diagnósticos, special offers, label "done today" e kill switch via feature flag remota da brand 7k (feat/ftd-checkin-7k-feature-flags). Componentes Checkin, CheckinTrigger, CheckinStoreOffers.
  • Loop de reabertura corrigidouseFtdCashbackFlow ganha guard pra não reabrir o first-modal logo depois do close (PR #485, fix/ftd-cashback-first-modal-loop).

Changelog - 29/04/2026

Dia pesado: 25 PRs no front-web-base cobrindo um empurrão grande de performance (CSS, ícones, modal), refatoração do header secundário com gating de rota, novas features de cassino e pagamentos, e ajustes finos de SEO/mobile/auth. Plus 4 mudanças de CI/CD em front-ops pra suportar o novo modelo de cache por device/country/buildId.

Performance — empurrão grande

  • Drop important: true do Tailwind (tailwind.config.js). Removido globalmente — precedência CSS volta ao normal (inline style vence class). Resultado: CSS −23,5KB raw (−14,4%). Componentes que usavam o pattern condicional bgStyle ? "" : "bg-..." (omitir classe quando havia inline style) foram simplificados — agora basta sempre emitir a classe que o style inline sobrescreve quando presente. Atualizados: GameCardStacked, GameStats, GameWinners, MainLeaguesSquare, SidebarButtonsGradient, SidebarButtonsGrid.
  • Migração react-modal-sheetvaul (app/components/base/Modal.tsx). Modal chunk caiu de ~158KB pra ~65KB raw — −93KB (−59%). Mesma API externa, drop-in pelos consumers. (PR #405 fez ajustes finos depois pra resolver bugs de input-focus em mobile e espaço fantasma no footer.)
  • Remoção do @tailwindcss/typography. Plugin não justificava o custo — uso restrito a 4 lugares (FaqSingleContent, WpPostContent, page.$slug, vip/levels) substituído por classes utilitárias inline. package.json enxuga uma dep + 22 linhas de pnpm-lock.yaml.
  • Ícones direct-imports + lazy MainLeagues (app/widgets/home-leagues/). Drop do registry intermediário — agora cada componente faz import Icon from "~icons/<set>/<name>" direto. MainLeaguesSquare virou lazy chunk separado. 25 arquivos tocados, −564 linhas vs +454. Atualiza configs de home-leagues em 7 brands (7k-bet-br, cassino-bet-br, fi-7k-bet, ng-7k-bet, pb-bet, vera-bet-br, state77-com, x2b-bet).
  • CI Lighthouse manual (.github/workflows/lighthouse.yml). Workflow caller dispatchável via workflow_dispatch pra rodar Lighthouse on-demand contra preview/prod sem precisar de schedule fixo. Útil pra validar PRs pesados de UI antes de mergear.

Changelog - 24/04/2026

Topbar de Notificações

  • Redesign completo da TopbarNotification (PR #333): novo layout com botão de fechar (X) à esquerda, ícone em chip arredondado com tokens dedicados (topbar.icon-bg / topbar.icon-text), pilha de título + subtítulo no centro e CTA pill à direita, com altura de 72 px alinhada às barras modernas de instalação de app. Os ícones emoji foram substituídos por componentes do lucide-react (Smartphone, Bell, Gift, Send, Trophy, ShieldAlert) e o tipo TopbarDefinition.icon virou LucideIcon. Os modos default e restricted foram unificados num TopbarShell compartilhado, e a topbar deixou de ser sticky — agora rola junto com a página enquanto o header permanece fixo no topo do viewport. Tooltip de instalação iOS foi reancorado para o rodapé do viewport com safe-area-inset-bottom para que a seta inferior alinhe com a barra de endereços do Safari.
  • Centralização do conteúdo no desktop (PR #334): o TopbarNotification recebeu um container interno max-w-[460px] mx-auto envolvendo close/ícone/texto/CTA. O fundo continua preenchendo edge-to-edge, mas em viewports largos o X e o CTA não escorregam mais para os cantos deixando um espaço vazio gigante no meio. Em mobile (< 460px) o comportamento é idêntico ao anterior — o container preenche naturalmente toda a largura.
  • Refresh de tokens de tema da topbar em todos os overrides (PR #347): sincronizou o override 7k-bet-br (que estava sem icon-bg e icon-text), padronizou a paleta com fundo mais suave (lifted bg-primary), chip do ícone tingido com primary e CTA combinando com o botão primário da brand. Ajustes manuais aplicados nas variantes 7k, state77, vera-bet-br, betpontobet-bet-br e cassino-bet-br. Altura interna da linha do TopbarNotification reduzida de 68 px para 62 px para compactar o footprint vertical.

Changelog - 21/04/2026

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 452450e apaga 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.

Changelog - 12/04/2026

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).