Depurar como um profissional & proteger a tua app
Objetivos deste capítulo
- Proteger os teus segredos e reagir corretamente a uma fuga
- Validar as entradas dos utilizadores e pôr limites em todo o lado
- Diagnosticar metodicamente um bug em produção
A noite em que tudo quase descarrilou
Numa terça-feira à noite, duas mensagens caem uma a seguir à outra. A primeira vem do Karim, um aluno de humor duvidoso: «Stôr, pus uma coisa esquisita no nome de um hábito e agora a página mostra tudo ao contrário 😂». A segunda vem da colega de português: «A app estava muito lenta ontem por volta das 19h, é normal?». O Tom percebe uma coisa que todo o criador de apps descobre um dia: com utilizadores verdadeiros vêm os bugs verdadeiros… e as asneiras verdadeiras. A app dele já não é um projeto pessoal, é um serviço público em miniatura — e um serviço protege-se.
Descansa: a segurança «nível iniciante profissional» assenta em três frentes, e já tens bases em cada uma. Os segredos (as tuas chaves e palavras-passe de infraestrutura), as entradas (tudo o que os utilizadores escrevem), e os limites (o que se tem o direito de fazer, quantas vezes). Este capítulo dá a volta às três, e depois arma-te para a depuração em condições reais — aquela em que o bug está num utilizador, num aparelho que não tens, a uma hora em que não estavas lá.
Frente 1 — Os segredos
Já sabes que as chaves vivem num ficheiro .env do lado do servidor. Falta verificar duas coisas. Primeiro, que esse ficheiro é mesmo ignorado pelo Git: se for incluído num commit, parte para o GitHub com o resto — e um repositório, mesmo privado hoje, pode tornar-se público amanhã. Depois, que sabes reagir a uma fuga: nunca se «esconde» uma chave comprometida, revoga-se (desativa-se no painel de controlo do serviço) e gera-se uma nova. Sempre, sem exceção, mesmo na dúvida.
# .gitignore — na raiz do projeto .env .env.local # Verificar que o .env NÃO é seguido pelo Git: git status # O .env não deve aparecer em lado nenhum da saída. # Se uma chave fugiu: não se esconde, REVOGA-SE # no painel de controlo do serviço, e gera-se uma nova.
Frente 2 — Nunca confiar nas entradas
Voltemos à brincadeira do Karim. O que fez ele? Escreveu código HTML no campo «nome de hábito» — algo como <h1>OLÁ</h1> — e a app mostrou-o tal e qual, interpretando-o como formatação. Engraçado aqui; grave em geral: se uma app mostra sem precaução o que os utilizadores escrevem, um utilizador malicioso pode lá introduzir código que se executará nos outros. É a família de ataques mais comum da web (os iniciados dizem «XSS»), e a defesa chama-se escape: o texto digitado é sempre mostrado como texto, nunca interpretado como código.
O princípio a gravar: toda a entrada de utilizador é suspeita por defeito. Um nome de hábito deve ser tratado como texto simples, verificado em comprimento, e validado do lado do servidor — não apenas no navegador, porque um utilizador equipado pode contornar tudo o que se passa do lado do cliente. Não tens de implementar isto tu mesmo: tens de o exigir e de o testar. O teste é simples e saboroso: faz como o Karim, tenta partir a tua própria app.
A auditoria de segurança: o teu aliado IA
Boa notícia: a IA é notavelmente boa a auditar o código que ela própria escreveu, desde que lhe dês um mandato preciso. Eis o prompt de auditoria do Tom — guarda-o preciosamente, voltará a servir em cada etapa importante de todos os teus projetos:
Faz uma auditoria de segurança completa à minha app de acompanhamento de hábitos, adaptada ao meu nível de iniciante. Contexto: HTML/JS na Vercel, Supabase com autenticação por link mágico e regras RLS, funções de servidor para os emails e a IA, pagamento via Stripe Payment Links. Verifica em prioridade: 1. chaves ou segredos presentes no código do lado do navegador, no repositório Git ou no seu histórico 2. as entradas de utilizador mostradas sem escape: nomes de hábitos, conteúdos de formulários 3. as regras RLS: um utilizador pode ler ou modificar os dados de outro? 4. as funções de servidor: podem ser chamadas sem estar ligado? sem limite de frequência? 5. as dependências ou bibliotecas com falhas conhecidas Para cada problema encontrado: explica o risco numa frase simples, mostra a correção mínima, e classifica tudo por gravidade de crítico a menor. NÃO corrijas NADA sem o meu acordo explícito, ponto por ponto.
Duas exigências fazem o valor deste prompt. A classificação por gravidade: tratas primeiro o crítico, e decides com conhecimento de causa para o resto — nem todas as falhas se equivalem, e um iniciante que quer corrigir tudo de uma vez não corrige nada bem. E o «não corrijas nada sem o meu acordo»: uma auditoria que modifica o código ao mesmo tempo que o analisa é incontrolável. Primeiro compreender, depois corrigir, uma correção de cada vez — o método do capítulo 4 aplica-se também à segurança.
Frente 3 — Pôr limites em todo o lado
Terceira frente, a mais simples de compreender: tudo o que não tem limite explícito acabará por ser levado ao absurdo — por malícia, por acidente, ou por um robô. No capítulo 8, limitaste os emails e as chamadas de IA; generaliza agora o reflexo a toda a app. Cada campo tem um comprimento máximo, cada lista tem um tamanho máximo, cada ação tem uma frequência máxima. E cada recusa acompanha-se de uma mensagem educada e clara — o limite protege, não pune.
- Nome de hábito: 50 caracteres no máximo, apenas texto simples.
- Número de hábitos por conta: 30 no máximo — ninguém acompanha 200, mas um script pode criar 100 000.
- Resumo por email: 1 envio por utilizador e por dia.
- Mensagem de IA: 1 chamada por utilizador e por dia, teto de despesa mensal no fornecedor.
- Criação de conta: protegida pela verificação de email do link mágico — já está, obrigado capítulo 6.
flowchart TD
E["Entrada ou ação do utilizador"] --> V{"Conteúdo válido?"}
V -->|"Não"| R["Mensagem de erro clara e educada"]
V -->|"Sim"| L{"Dentro dos limites?"}
L -->|"Não"| R2["Recusa explicada: limite atingido"]
L -->|"Sim"| S["Tratamento e armazenamento em segurança"]Depurar em produção: o método
Resta a mensagem da colega: «estava lento ontem por volta das 19h». Bug típico de produção: não o viste, não o podes reproduzir à vontade, e o utilizador quase não dá detalhes. O método profissional cabe em três movimentos: recolher (fazer ao utilizador as perguntas certas: que aparelho, que navegador, que hora, que ação precisa, uma captura de ecrã), consultar (os registos — «logs» — da Vercel e do Supabase, que gravam o que realmente se passou no servidor àquela hora), e conjeturar (formular hipóteses ordenadas, e depois testá-las uma a uma, da mais simples à mais complexa).
Bug em produção a diagnosticar metodicamente. Contexto: um aluno diz-me que a app «apaga as marcações dele» no telemóvel Android com o Chrome, ontem por volta das 19h. No meu computador, impossível reproduzir. Do que disponho: os logs da Vercel da noite, o acesso ao painel de controlo do Supabase, e a possibilidade de voltar a escrever ao aluno. Guia-me em três tempos: 1. a lista exata das perguntas a fazer ao aluno para delimitar o contexto 2. o que procurar precisamente nos logs da Vercel e nos dados do Supabase por volta das 19h 3. como simular um telemóvel Android e uma rede lenta a partir do meu navegador para tentar reproduzir Propõe depois as tuas 3 hipóteses mais prováveis, ordenadas da mais simples de verificar à mais complexa, com o teste a fazer para cada uma.
Repara na estrutura: este prompt não pede uma solução, pede uma investigação. É o reflexo certo perante um bug não reproduzido — procurar a correção antes de delimitar a causa é corrigir ao acaso. As «3 hipóteses ordenadas» evitam-te a outra armadilha: explorar a pista exótica antes da pista banal. Na vida real, a hipótese banal ganha nove vezes em dez: uma rede que cai no momento errado, uma versão antiga em cache, uma sessão expirada.
A cópia de segurança, o teu seguro de vida
Última peça do dispositivo: a cópia de segurança dos dados. O teu código está seguro no Git, mas os hábitos e as marcações dos teus utilizadores só vivem na base. Uma manobra em falso no painel de controlo — uma tabela esvaziada num clique demasiado rápido — e desaparece tudo. Verifica o que o teu plano Supabase guarda automaticamente, e completa com uma exportação regular (a IA pode criar-te um pequeno script de exportação, ou usa a função de exportação do painel de controlo). E sobretudo, faz uma vez o exercício de restauro: uma cópia de segurança nunca testada é uma promessa, não uma proteção.
Com as três frentes cobertas, o diário de incidentes começado e a primeira cópia de segurança testada, o Tom dorme melhor. O Karim recebeu uma mensagem educada («nome de hábito inválido 😉»), a lentidão das 19h revelou-se uma rede de residência escolar saturada — hipótese banal, como previsto. A app está sólida. É hora de a olhar de outra forma: já não como um projeto, mas como um produto. É o capítulo final.
Contexto
O Tom dedica uma noite completa à revisão de segurança: auditoria pela IA, correções por gravidade, limites em todo o lado, e primeiro teste de restauro de cópia de segurança. De bónus, dá-se ao prazer de fazer de Karim: tentar partir a própria app antes que outra pessoa se encarregue disso. Desenrola o mesmo programa na tua app — é a noite mais rentável do teu percurso.
Instruções
- Verifica os teus segredos: .env no .gitignore, git status limpo, e procura «key» nas fontes do lado do navegador (F12).
- Faz de atacante: escreve HTML nos teus campos, textos de 5000 caracteres, clica freneticamente — anota tudo o que parte.
- Lança o prompt de auditoria de segurança completa e lê o relatório inteiro antes de corrigir o que quer que seja.
- Corrige os problemas por gravidade decrescente, UMA correção de cada vez, com teste e commit depois de cada uma.
- Põe os teus limites (comprimentos, quantidades, frequências) com mensagens de recusa educadas, e testa cada limite.
- Exporta uma cópia de segurança da tua base, e depois faz o exercício de restauro num projeto de teste — e anota o procedimento no teu diário.
Em resumo
- Três frentes: os segredos, as entradas dos utilizadores, os limites — cobre as três e eliminas o essencial do risco.
- Uma chave que tocou no Git está comprometida para sempre: revoga-se e regenera-se, nunca se «esconde».
- Toda a entrada de utilizador é suspeita: com escape na apresentação, validada do lado do servidor, limitada em comprimento.
- A auditoria por IA funciona com um mandato preciso: perímetro, classificação por gravidade, e nenhuma correção sem o teu acordo.
- Cada campo, lista e ação recebe um limite explícito, com uma mensagem de recusa educada.
- Bug em produção: recolher o contexto, consultar os logs, conjeturar hipóteses ordenadas do banal para o exótico.
- Uma cópia de segurança nunca restaurada é uma promessa, não uma proteção: testa o restauro uma vez.
Quiz — verifica a tua compreensão
1. Descobres que uma chave API foi enviada para o GitHub há uma semana. O que fazes?
2. O Karim escreve HTML num campo e a página interpreta-o. Como se chama a defesa?
3. Porquê validar as entradas do lado do servidor e não apenas no navegador?
4. Quais são as duas exigências-chave do prompt de auditoria de segurança?
5. Um utilizador assinala um bug que não consegues reproduzir. Por onde começas?