QABot

Revisão técnica assistida por IA

Históricoc32b7b79-e3d7-425d-a065-7ad5407378cc
ANÁLISE SALVA

cellarvinhostechteam/novo-app-cellar

feat/tab-pop-to-top · 22 de setembro de 2026 às 12:53 · gpt-5.6-sol

52/ 100

A alteração apresenta riscos relevantes de segurança e publicação. O principal problema é o envio de credencial de autenticação na query string de uma WebView, agravado pela liberação global de HTTP sem TLS. A configuração de produção também mantém OneSignal/APNs em modo de desenvolvimento, e atualizações OTA para o canal production podem ser disparadas por uma mensagem de commit na branch development. Há ainda caminhos que podem bloquear indefinidamente a inicialização, numeração fixa de builds, scripts de migração defeituosos e ausência de testes automatizados para o comportamento tab-pop-to-top. Score: 52/100.

Achados 12

24 arquivos analisados

Alto

Token de autenticação é inserido diretamente na URL da WebView

security
src/components/home/ClubeWelcome.tsx

A navegação para GeneralWebview monta `https://socio.cellarvinhos.com/loginWebview?email=${userEmail}&tokenVtex=${authCookie?.Value}`. O token e o e-mail passam a fazer parte da URL, podendo aparecer em histórico, logs, telemetria, relatórios de erro e redirecionamentos. Além disso, os valores não usam `encodeURIComponent`, então caracteres como `&`, `+`, `#` ou `=` podem corromper os parâmetros.

RecomendaçãoTrocar a autenticação por POST, header de autorização ou código temporário de uso único. Não transportar o cookie VTEX completo na URL. Se parâmetros não sensíveis continuarem na query string, aplicar `encodeURIComponent` e validar valores ausentes antes de navegar.
Alto

Transporte inseguro está habilitado globalmente em iOS e Android

security
app.config.js

No iOS, `NSAppTransportSecurity.NSAllowsArbitraryLoads` está definido como `true` em `infoPlist` e também repetido na configuração de `ios`. No Android, `usesCleartextTraffic: true` permite tráfego HTTP sem criptografia para todo o aplicativo.

RecomendaçãoDesabilitar `NSAllowsArbitraryLoads` e `usesCleartextTraffic` em produção. Se algum domínio legado exigir HTTP, criar exceções restritas por domínio usando ATS e Network Security Config, acompanhadas de plano de remoção.
Alto

Build de produção mantém configuração de push em modo de desenvolvimento

reliability
app.config.js

A configuração fixa `entitlements['aps-environment']` como `development` e o `onesignal-expo-plugin` usa `mode: 'development'`. O perfil production de `eas.json` não fornece configuração alternativa, portanto o mesmo app.config é usado no build de produção.

RecomendaçãoSelecionar `aps-environment` e `mode` conforme o profile/ambiente do EAS, usando `production` no build de loja. Validar em um artefato assinado que o entitlement final usa APNs production e executar teste real de push em TestFlight/produção.
Alto

Push na branch development pode publicar OTA diretamente no canal production

reliability
.eas/workflows/publish-development-updates.yml:14

O job `dev_update_production` é executado em pushes para `development` quando a mensagem do último commit contém simultaneamente `update` e `production`; o destino configurado é `channel: production`. Não há aprovação, tag, branch protegida ou outro gate mostrado no workflow.

RecomendaçãoRemover publicação em production a partir de development. Exigir tag ou branch de release protegida, aprovação manual e checagens obrigatórias. Preferir seleção explícita de ambiente em vez de palavras livres na mensagem de commit.
Alto

Verificação de atualização pode manter o aplicativo em tela vazia indefinidamente

reliability
App.tsx

Enquanto `isCheckingUpdates` é verdadeiro, o componente retorna `null`. Esse estado só é liberado após os awaits sequenciais de `VersionCheck.needUpdate()`, `Updates.checkForUpdateAsync()` e, quando aplicável, `Updates.fetchUpdateAsync()`. O código não impõe timeout ou fallback caso uma dessas Promises permaneça pendente.

RecomendaçãoAplicar timeout global curto à verificação de startup e liberar a interface no fallback. Executar download OTA após a aplicação estar utilizável, quando possível, e registrar falhas/timeout para diagnóstico. Adicionar teste com Promises que nunca resolvem.
Alto

Builds de produção reutilizam números fixos de versão nativa

reliability
eas.json

O EAS usa `appVersionSource: 'local'` e o profile production define `autoIncrement: false`. Em `app.config.js`, `ios.buildNumber` e `android.versionCode` estão ambos fixos em `70`. Builds subsequentes preservam esses números e não podem ser submetidos como novas versões depois que o número for usado nas lojas.

RecomendaçãoAtivar `autoIncrement` para production ou incrementar obrigatoriamente `buildNumber` e `versionCode` no processo de release. Adicionar validação de CI que rejeite artefatos com número já publicado.
Médio

Falha no carregamento das fontes impede a aplicação de sair do splash

reliability
App.tsx

Somente o primeiro retorno de `useFonts` é capturado: `const [fontsLoaded] = useFonts(...)`. A renderização continua retornando `AnimatedSplash` enquanto `!fontsLoaded`, sem tratar o erro retornado pelo hook. Assim, uma falha definitiva de fonte não possui caminho de fallback.

RecomendaçãoCapturar também o erro de `useFonts`, registrar a falha e permitir inicialização com uma fonte fallback. Cobrir com teste em que o carregamento da fonte rejeita ou retorna erro.
Médio

Script de substituição nunca adiciona o import de AppScrollView após transformar o arquivo

maintainability
replace_scrollviews.js

O script primeiro substitui `<ScrollView` por `<AppScrollView` e depois verifica `if (!content.includes('AppScrollView'))` antes de adicionar o import. Após qualquer substituição, essa condição é necessariamente falsa, mesmo quando não existe import, deixando o arquivo transformado com identificador não definido.

RecomendaçãoVerificar a presença do import antes da substituição ou procurar especificamente uma declaração de import válida. Executar parser AST em vez de substituições textuais e adicionar um teste de fixture que transforme um componente com ScrollView e valide o resultado compilável.
Médio

Falha no AsyncStorage pode impedir o fechamento do modal

reliability
src/components/home/SelecaoCupons/HowToUseCouponsModal.tsx

`handleClose` aguarda `AsyncStorage.setItem` ou `removeItem` antes de chamar `onClose`, sem `try/finally`. Se a persistência rejeitar, `onClose()` não é executado. O `loadPref` também faz leitura sem tratamento de erro, podendo gerar rejeição não tratada.

RecomendaçãoEnvolver leitura e gravação em `try/catch`; no fechamento, chamar `onClose` em `finally`. Registrar a falha sem bloquear a interação. Adicionar testes simulando rejeições de getItem, setItem e removeItem.
Médio

Consulta da vitrine é criada mesmo para usuários que não podem visualizar o componente

performance
src/components/home/MinhaVitrine.tsx

`useAdegaProductsQuery(skus)` é chamado antes do retorno que verifica `user?.clube !== true` e outros critérios. Quando o usuário não possui SKUs, ainda é fornecida a lista padrão `869214074, 869214847, 869214391`, embora o componente possa retornar `null` logo depois.

RecomendaçãoPassar uma opção `enabled` baseada nos mesmos critérios de visibilidade para a query. Manter a chamada do hook incondicional, mas impedir fetch/cache desnecessário quando o usuário não for elegível.
Médio

Não há infraestrutura ou scripts de testes para validar o comportamento da branch

testing
package.json

Os scripts disponíveis incluem start, builds, submits e upload de sourcemaps, mas não existe script de teste, lint ou typecheck. As dependências também não mostram runner de testes. Entre os arquivos enviados não há teste para tab-pop-to-top, deep links, atualização OTA, push ou persistência do modal.

RecomendaçãoAdicionar scripts de `typecheck`, lint e testes automatizados. Para o escopo da branch, cobrir ao menos: toque na aba ativa levando a lista ao topo, preservação ao trocar de aba, listas aninhadas, aba sem ref, múltiplos toques e comportamento em iOS/Android. Incluir esses checks como obrigatórios antes de publicar OTA.
Baixo

Cálculo de offset para PDP no BolaoButton é inalcançável

maintainability
src/components/home/Bolao/BolaoButton.tsx

O código calcula `isPDP`, `pdpOffset` e adiciona esse valor a `dynamicBottom`, mas posteriormente retorna `null` sempre que `currentRouteName !== 'Home'`. Portanto, quando a rota é `Produto`, o botão não é renderizado e o offset específico de PDP nunca é usado.

RecomendaçãoRemover o ramo de PDP se o botão deve existir apenas na Home, ou ajustar a condição de renderização se ele também deve aparecer em Produto. Adicionar teste por rota para documentar o comportamento esperado.