[{"data":1,"prerenderedAt":923},["ShallowReactive",2],{"blog-pt-move-a-secret-to-an-edge-function":3,"blog-index-pt":571},{"id":4,"title":5,"body":6,"category":526,"cover":527,"coverAlt":528,"description":529,"draft":530,"extension":531,"faq":532,"image":549,"keywords":550,"meta":559,"navigation":560,"ogTitle":561,"path":562,"published":563,"seo":564,"stem":565,"tldr":566,"updated":563,"__hash__":570},"blog_pt\u002Fblog\u002Fmove-a-secret-to-an-edge-function.md","Esconder uma chave de API: mova para uma Edge Function do Supabase",{"type":7,"value":8,"toc":512},"minimark",[9,13,29,32,37,40,53,56,62,66,69,72,80,84,87,162,171,201,221,225,228,244,247,257,263,268,272,275,282,292,313,316,320,323,346,349,353,356,359,377,380,387,391,394,407,410,418,427,431,434,452,458,471,475,504],[10,11,12],"p",{},"Todo guia sobre uma chave de API vazada termina no mesmo lugar: mova para um\nservidor. Aí ele para. Você fica com um app que construiu no Lovable, no Bolt ou\nno Cursor, nenhum servidor à vista, e uma frase que presume que você já sabe o\nque fazer em seguida.",[10,14,15,16,20,21,28],{},"Esta é a parte que guia após guia deixa de fora. ",[17,18,19],"strong",{},"Mover a chave para uma Edge\nFunction do Supabase tira ela da sua página, e sozinho isso não impede um\ndesconhecido de usar."," A própria documentação do Supabase diz por quê: a\nchecagem que uma function publicada faz por padrão\n",[22,23,27],"a",{"href":24,"rel":25},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fauth-headers",[26],"nofollow","também aceita sua chave pública",",\ne sua chave pública está no seu frontend, ao alcance de quem quiser copiar.\nEsconder a chave é a metade fácil. Sobre a outra metade ninguém escreve: decidir\npara quem a sua nova function responde.",[10,30,31],{},"Pense na chave como a chave-mestra de um estoque. Agora ela está colada por\ndentro da vitrine, onde qualquer um que parar consegue ler. Uma Edge Function é\num quartinho dos fundos com um guichê: a chave vai para lá, e os visitantes pedem\nno guichê em vez de entrar e se servir. Se isso é uma melhora depende de para\nquem o guichê abre.",[33,34,36],"h2",{"id":35},"onde-coloco-minha-chave-de-api-se-não-é-no-frontend","Onde coloco minha chave de API, se não é no frontend?",[10,38,39],{},"Em qualquer lugar que não seja o navegador. Uma Edge Function é a versão menor\ndisso.",[10,41,42,43,47,48,52],{},"Um navegador não sabe guardar segredo. Tudo que sua página precisa para funcionar\né baixado por cada visitante, e um visitante consegue ler tudo: o código, as\nimagens, os valores compilados dentro do código. Isso não é um defeito da sua\nferramenta. É o que uma página web é.\n",[22,44,46],{"href":45},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Quais chaves de API são seguras no frontend","\né a versão longa; a curta é que uma chave ",[49,50,51],"code",{},"sk_",", uma chave da OpenAI ou uma chave\nsecreta do Supabase nunca ia sobreviver a uma viagem até o navegador.",[10,54,55],{},"Uma Edge Function do Supabase é um pedacinho de código que roda nas máquinas do\nSupabase. Ela consegue ler os segredos que você definiu no projeto, responde num\nendereço web próprio, e seu app chama ela pelo nome. Você escreve um arquivo, o\nSupabase executa, e não há servidor nenhum para alugar, atualizar ou manter\nacordado.",[57,58],"diagram",{"alt":59,"caption":60,"src":61},"Dois arranjos. Em cima, a chave está dentro do bundle que cada visitante baixa e o navegador chama o fornecedor direto. Embaixo, o bundle não leva chave, o navegador chama a Edge Function, e a function guarda a chave e chama o fornecedor.","Em cima: a chave está no arquivo que cada visitante baixa, então cada visitante tem ela. Embaixo: o navegador pergunta para a function, e a chave nunca sai do Supabase.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fwhere-the-key-lives-1600x800.png",[33,63,65],{"id":64},"troque-a-chave-que-você-já-publicou-antes-de-mover-qualquer-coisa","Troque a chave que você já publicou, antes de mover qualquer coisa",[10,67,68],{},"A chave que está hoje no seu frontend já é pública, e continua pública depois que\nvocê tira ela do código.",[10,70,71],{},"Cada visitante que carregou seu site baixou ela. Cada robô também, e existem\nrobôs automáticos percorrendo a web inteira atrás exatamente dessas sequências.\nSeu bundle antigo ainda está, além disso, no seu histórico de versões e em\nqualquer cache com uma cópia da sua página. Apagar uma linha de um arquivo que é\nseu não muda nada sobre um valor que já foi distribuído.",[10,73,74,75,79],{},"Então a ordem é: criar uma chave nova no fornecedor, segurar ela um instante, e\nrevogar a antiga assim que a function abaixo estiver no ar. Depois leia sua\npágina de cobrança e seus registros de uso de todo o período em que a chave\nantiga esteve solta. Trocar barra o que vem a seguir; sobre o que já aconteceu\nnão tem efeito nenhum. Se a chave era uma chave secreta do Supabase, ",[22,76,78],{"href":77},"\u002Fblog\u002Frotate-supabase-service-role-key","a ordem em\nque trabalhar"," tem um detalhe que vale\nler antes.",[33,81,83],{"id":82},"os-quatro-passos","Os quatro passos",[10,85,86],{},"Guardar o segredo, escrever a function, publicar, e mudar seu app para chamar a\nfunction em vez do fornecedor.",[88,89,90,106],"table",{},[91,92,93],"thead",{},[94,95,96,100,103],"tr",{},[97,98,99],"th",{},"Passo",[97,101,102],{},"Na linha de comando",[97,104,105],{},"No painel",[107,108,109,123,136,149],"tbody",{},[94,110,111,115,120],{},[112,113,114],"td",{},"1. Guardar o segredo",[112,116,117],{},[49,118,119],{},"supabase secrets set MY_API_KEY=…",[112,121,122],{},"Edge Functions → Secrets, depois Key e Value",[94,124,125,128,133],{},[112,126,127],{},"2. Escrever a function",[112,129,130],{},[49,131,132],{},"supabase functions new forward-request",[112,134,135],{},"Edge Functions → Deploy a new function → Via Editor",[94,137,138,141,146],{},[112,139,140],{},"3. Publicar",[112,142,143],{},[49,144,145],{},"supabase functions deploy",[112,147,148],{},"O botão Deploy embaixo do editor",[94,150,151,154,159],{},[112,152,153],{},"4. Chamar do seu app",[112,155,156],{},[49,157,158],{},"supabase.functions.invoke('…')",[112,160,161],{},"Igual, no código do seu app",[10,163,164,165,170],{},"Dentro da function o segredo chega como variável de ambiente, ou seja, um valor\ncom nome que o código consegue ler e ninguém de fora. A documentação do Supabase\nsobre\n",[22,166,169],{"href":167,"rel":168},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fsecrets",[26],"segredos de Edge Functions","\ntem a referência completa, e três detalhes de lá poupam uma hora de confusão:",[172,173,174,185,191],"ul",{},[175,176,177,184],"li",{},[17,178,179,180,183],{},"O nome de um segredo não pode começar com ",[49,181,182],{},"SUPABASE_","."," Esse prefixo é\nreservado para os valores que o Supabase define por você, e tanto o painel\nquanto a API recusam.",[175,186,187,190],{},[17,188,189],{},"Um segredo novo já pode ser lido na hora."," Você não precisa publicar a\nfunction de novo depois de trocar um.",[175,192,193,196,197,200],{},[17,194,195],{},"Local e produção são separados."," A pilha local lê\n",[49,198,199],{},"supabase\u002Ffunctions\u002F.env",", que é um lugar diferente dos segredos do seu projeto\nno ar, então defina o valor nos dois, ou a function funciona na sua máquina e\nfalha depois de publicada.",[10,202,203,204,207,208,211,212,215,216,220],{},"Depois apague a variável antiga do seu frontend. Se ela se chamava ",[49,205,206],{},"VITE_",",\n",[49,209,210],{},"NEXT_PUBLIC_"," ou ",[49,213,214],{},"EXPO_PUBLIC_",", esse prefixo era a instrução de compilar o\nvalor dentro do bundle, e ",[22,217,219],{"href":218},"\u002Fblog\u002Fvite-and-next-public-env-vars","o prefixo é a história\ninteira"," de como ele foi parar lá.",[33,222,224],{"id":223},"exigir-um-token-quer-dizer-que-só-meus-usuários-conseguem-chamar","Exigir um token quer dizer que só meus usuários conseguem chamar?",[10,226,227],{},"Não, e este é o ponto deste artigo que vale ler duas vezes.",[10,229,230,231,234,235,238,239,243],{},"O Supabase liga por padrão uma checagem chamada ",[49,232,233],{},"verify_jwt",". Ela olha o\ncabeçalho ",[49,236,237],{},"Authorization"," antes do seu código rodar e recusa a requisição se não\nhouver nada válido ali. Parece uma porta que só seus usuários abrem. Não é,\nporque o Supabase documenta também que a mesma checagem\n",[22,240,242],{"href":24,"rel":241},[26],"aceita uma chave pública ou secreta","\nem qualquer um dos dois cabeçalhos, por compatibilidade com projetos mais\nantigos, e acrescenta com todas as letras que a checagem sozinha não autentica\nquem chama mandando só uma chave de API.",[10,245,246],{},"Sua chave pública está no seu frontend. Isso está certo e é para ser assim.\nTambém quer dizer que quem abrir seu site, ler a chave e mandar ela para a sua\nfunction nova passa pela checagem da plataforma e entra no seu código.",[248,249,251],"callout",{"type":250},"warn",[10,252,253,256],{},[17,254,255],{},"É assim que uma chave movida vira um proxy aberto."," A chave não está mais na\nsua página, então um scanner que procura sequências em formato de chave não acha\nnada, e a fatura da OpenAI ou da Stripe segue crescendo. O que mudou é que agora\nas requisições passam por você. Antes um desconhecido tinha sua chave; agora um\ndesconhecido tem um endereço web seu que usa sua chave em nome dele, quantas\nvezes quiser.",[10,258,259,260,262],{},"No estoque, ",[49,261,233],{}," é um porteiro que confere se você está com um crachá de\nvisitante. Todo visitante tem um, porque é você quem distribui na entrada. Quem\nestá no guichê faz outro serviço, e é essa pessoa que pergunta qual visitante\nvocê é.",[57,264],{"alt":265,"caption":266,"src":267},"Dois chamadores chegam à mesma Edge Function. Um desconhecido que manda só a chave pública passa pela checagem de plataforma verify_jwt e depois é recusado pela checagem de dentro da function. Um usuário logado que manda um token de sessão passa pelas duas e chega à API do fornecedor.","Os dois passam pela checagem da plataforma. Só o segundo passa por uma checagem de quem está chamando, e essa segunda é a que você precisa acrescentar.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Ftwo-checks-1600x860.png",[33,269,271],{"id":270},"trancar-a-function-para-não-ter-construído-um-proxy-aberto","Trancar a function, para não ter construído um proxy aberto",[10,273,274],{},"Decida quais chamadores sua function aceita, e escreva essa decisão dentro da\nfunction.",[10,276,277,278,281],{},"O Supabase entrega um invólucro para isso, então é uma linha e não um projeto.\nColoque ",[49,279,280],{},"auth: 'user'"," e a function aceita o token de um usuário logado e entrega\nao seu código um cliente de banco já limitado às regras de Row Level Security\ndesse usuário:",[283,284,290],"pre",{"className":285,"code":287,"language":288,"meta":289},[286],"language-ts","import { withSupabase } from 'npm:@supabase\u002Fserver@1'\n\nexport default {\n  fetch: withSupabase({ auth: 'user' }, async (_req, ctx) => {\n    \u002F\u002F ctx.userClaims diz quem está chamando. Recuse aqui o que você não quer,\n    \u002F\u002F e então chame o fornecedor com o segredo vindo do ambiente.\n    return Response.json({ ok: true })\n  }),\n}\n","ts","",[49,291,287],{"__ignoreMap":289},[10,293,294,295,300,301,304,305,308,309,312],{},"A página ",[22,296,299],{"href":297,"rel":298},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fauth",[26],"Securing Edge\nFunctions"," lista os outros\nmodos, e dois deles importam num app comum. Uma function chamada por outra\nmáquina e não por um navegador usa ",[49,302,303],{},"auth: 'secret'",", com a chave secreta mandada\nno cabeçalho ",[49,306,307],{},"apikey",". Uma function que recebe webhooks da Stripe ou do GitHub\nnão pode usar nenhum dos dois, porque esses fornecedores não têm token nenhum\nseu; ela coloca ",[49,310,311],{},"verify_jwt = false"," e confere a assinatura do fornecedor dentro\ndo handler.",[10,314,315],{},"Seja qual for a escolha, decida com cuidado o que acontece quando aparece um\nchamador que você não esperava. O exemplo que o Supabase dá de uma function que\npode aceitar qualquer um é uma verificação de saúde, e uma verificação de saúde\nnão custa nada quando um desconhecido chama. Uma function que repassa uma chamada\nde API paga cobra de você cada uma delas.",[33,317,319],{"id":318},"posso-usar-service_role-numa-edge-function","Posso usar service_role numa Edge Function?",[10,321,322],{},"Pode. Uma function é o único lugar em que uma chave secreta do Supabase cabe.",[10,324,325,326,329,330,333,334,329,337,340,341,345],{},"E você nem precisa colar ela. O Supabase coloca as chaves do projeto no ambiente\nda function, então o código lê de lá e não de um segredo definido por você.\nProjetos novos recebem ",[49,327,328],{},"SUPABASE_SECRET_KEYS"," e ",[49,331,332],{},"SUPABASE_PUBLISHABLE_KEYS",", cada\num um pequeno dicionário de chaves com nome; projetos mais antigos recebem\n",[49,335,336],{},"SUPABASE_SERVICE_ROLE_KEY",[49,338,339],{},"SUPABASE_ANON_KEY"," com os nomes de sempre. ",[22,342,344],{"href":343},"\u002Fblog\u002Fsupabase-new-api-keys","O que\nmudou quando o Supabase renomeou as chaves"," diz qual\npar você tem.",[10,347,348],{},"Use a chave secreta para o trabalho que realmente precisa ver cada linha, como\ngravar um registro de auditoria que o usuário não possa editar. Para tudo que um\nusuário lê sobre si mesmo, use o token dele e deixe suas regras de Row Level\nSecurity filtrarem, que é para isso que elas existem.",[33,350,352],{"id":351},"conferir-pelo-navegador-a-única-prova-que-vale","Conferir pelo navegador, a única prova que vale",[10,354,355],{},"Carregue seu site no ar, abra a aba de rede, e veja o que seu navegador manda de\nverdade.",[10,357,358],{},"As duas coisas para conferir:",[172,360,361,371],{},[175,362,363,366,367,370],{},[17,364,365],{},"Nenhuma requisição leva a chave."," Passe pela parte do seu app que antes\nchamava o fornecedor. A requisição de saída tem que ir para\n",[49,368,369],{},"…supabase.co\u002Ffunctions\u002Fv1\u002Fsua-function",", e a única credencial lá dentro tem\nque ser sua chave pública ou o token do seu usuário.",[175,372,373,376],{},[17,374,375],{},"A chave não está no código baixado."," Use a busca do navegador em todos os\narquivos carregados e cole a primeira dúzia de caracteres da chave antiga.\nNenhum resultado é a resposta que você quer.",[10,378,379],{},"Só uma nova compilação e uma nova publicação tiram um valor do bundle. Uma chave\nque ainda aparece na busca costuma querer dizer que o frontend saiu antes de a\nvariável sair dele.",[10,381,382,383,183],{},"Nosso scan gratuito faz a segunda conferência de fora e diz o que consegue ler no\nseu bundle no ar, inclusive qual chave do Supabase você publicou. Leva uns 20\nsegundos e não precisa de conta: ",[22,384,386],{"href":385},"\u002Fsecurity-scanner","escaneie seu app",[33,388,390],{"id":389},"como-fazer-isso-a-partir-do-lovable-bolt-ou-replit","Como fazer isso a partir do Lovable, Bolt ou Replit",[10,392,393],{},"Use o painel do Supabase. Não tem nenhum passo de terminal ali.",[10,395,396,397,400,401,406],{},"Abra seu projeto, escolha Edge Functions na barra lateral e depois ",[17,398,399],{},"Deploy a new\nfunction → Via Editor",". O ",[22,402,405],{"href":403,"rel":404},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fquickstart-dashboard",[26],"guia rápido do\npainel"," do\nSupabase percorre tudo com capturas de tela, e entre os modelos oferecidos há um\npara repassar a um fornecedor de IA, que é exatamente o formato deste trabalho. A\npublicação leva entre dez e trinta segundos, e a function fica no ar num endereço\npróprio. Seu segredo vai na página Edge Function Secrets, na mesma seção.",[10,408,409],{},"Uma ressalva que vale conhecer antes de confiar nisso: o Supabase escreve que o\neditor do painel não tem controle de versão, nem versões, nem volta atrás, e\nrecomenda ele para trabalho rápido e não para código que vai ficar. Apertar\nDeploy sobrescreve o que estava lá. Se a function acabar fazendo algo que importa\npara você, baixe ela por essa página e guarde o arquivo.",[10,411,412,413,417],{},"Existe também uma versão desta pergunta no formato Replit, porque o Replit tem um\narmazém de segredos próprio e seu app roda um servidor próprio lá. ",[22,414,416],{"href":415},"\u002Fblog\u002Freplit-secrets-explained","O que os\nReplit Secrets fazem de verdade"," é essa versão.",[248,419,421],{"type":420},"note",[10,422,423,426],{},[17,424,425],{},"Se a chamada sai de um navegador, a function precisa de cabeçalhos CORS."," Um\nnavegador não deixa sua página ler uma resposta de outro endereço a menos que\nesse endereço permita. Os modelos do painel do Supabase já trazem os cabeçalhos;\numa function escrita do zero não, e o sintoma é uma requisição que parece certa\nnos registros da function e falha no seu app.",[33,428,430],{"id":429},"quando-uma-edge-function-é-a-resposta-errada","Quando uma Edge Function é a resposta errada",[10,432,433],{},"Dois casos, e nos dois a mudança custa trabalho e não traz nada.",[10,435,436,439,440,443,444,447,448,451],{},[17,437,438],{},"A chave era pública de propósito."," Uma chave ",[49,441,442],{},"pk_live_"," da Stripe, uma chave\npública do Supabase ou uma chave ",[49,445,446],{},"anon",", um token público do Mapbox: essas são\nfeitas para ficar num navegador, e a proteção está em outro lugar. Colocar uma\ndelas atrás de uma function acrescenta um desvio e não tira risco nenhum. ",[22,449,450],{"href":45},"Quais\nchaves são essas"," é a lista.",[10,453,454,457],{},[17,455,456],{},"A chave pode ser restrita ao seu próprio site."," As chaves de navegador do\nGoogle são o exemplo mais comum: no console do Google você limita uma delas aos\nseus domínios, e é justamente essa a solução que o Google prevê para esse caso. A\nchave continua legível e deixa de servir para quem a copiar.",[10,459,460,461,465,466,470],{},"Todo o resto fica num servidor. Uma chave da OpenAI ou da Anthropic não tem\nvariante pública, e é por isso que ",[22,462,464],{"href":463},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","uma chave de fornecedor de IA no seu\nfrontend"," não tem ajuste nenhum que a\nsalve, e nenhuma minificação esconde uma ",[22,467,469],{"href":468},"\u002Fblog\u002Fstripe-secret-key-in-frontend","chave secreta da\nStripe"," de quem ler sua página.",[33,472,474],{"id":473},"o-que-fazer-agora","O que fazer agora",[476,477,478],"key-takeaways",{},[172,479,480,483,489,492,498,501],{},[175,481,482],{},"Troque a chave primeiro. Crie uma nova no fornecedor, coloque no segredo da function, e revogue a antiga assim que a function estiver no ar.",[175,484,485,486,488],{},"Guarde o segredo no seu projeto do Supabase, não no seu repositório e não numa variável ",[49,487,206],{},". Defina separadamente para desenvolvimento local e para produção.",[175,490,491],{},"Publique uma function que usa o segredo, e mude seu app para chamar a function pelo nome em vez do fornecedor.",[175,493,494,495,497],{},"Acrescente uma checagem de quem está chamando. ",[49,496,233],{}," sozinho aceita a chave pública do seu próprio frontend, então não barra um desconhecido.",[175,499,500],{},"Apague a variável antiga, compile de novo, e confirme na aba de rede do navegador que nada que sai leva a chave.",[175,502,503],{},"Leia cobrança e uso de todo o período em que a chave antiga ficou pública. Trocar barra a próxima cobrança e não a última.",[10,505,506,507,511],{},"Se você prefere revisar o app inteiro em vez de uma chave só, a\n",[22,508,510],{"href":509},"\u002Fchecklist","checklist de segurança em 10 minutos"," cobre isso junto com as outras\ncoisas que vale fechar num app recém-lançado.",{"title":289,"searchDepth":513,"depth":513,"links":514},3,[515,517,518,519,520,521,522,523,524,525],{"id":35,"depth":516,"text":36},2,{"id":64,"depth":516,"text":65},{"id":82,"depth":516,"text":83},{"id":223,"depth":516,"text":224},{"id":270,"depth":516,"text":271},{"id":318,"depth":516,"text":319},{"id":351,"depth":516,"text":352},{"id":389,"depth":516,"text":390},{"id":429,"depth":516,"text":430},{"id":473,"depth":516,"text":474},"Noções de segurança","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcover-1200x630.png","Uma folha com um furo em formato de chave, e atrás dela uma caixa lacrada com cadeado fechado e a chave visível por uma janelinha.","Esconder uma chave de API é tirá-la do navegador, e uma Edge Function do Supabase é o menor lugar para guardá-la. Dois passos em volta pesam mais.",false,"md",[533,535,538,541,544,546],{"q":36,"a":534},"Em qualquer lugar que não seja o navegador. Uma Edge Function do Supabase é a opção menor: você guarda a chave como segredo no seu projeto, escreve um arquivo pequeno que usa ela, e seu app chama essa function pelo nome em vez de chamar o fornecedor direto. Uma rota serverless na sua hospedagem ou um servidor seu funcionam igual. O que elas têm em comum é que a chave é lida onde seu visitante não vê.",{"q":536,"a":537},"O que é uma Edge Function do Supabase?","Um pedacinho de código que roda nas máquinas do Supabase e não no navegador do seu visitante. Ela responde num endereço web próprio, consegue ler os segredos que você definiu no projeto, e seu app chama ela com supabase.functions.invoke. Você escreve um arquivo, o Supabase executa, e não há servidor nenhum para alugar ou manter.",{"q":539,"a":540},"Preciso trocar a chave depois de mover?","Precisa, e antes de tudo. A chave que estava no seu frontend foi baixada por cada visitante e por cada robô que leu seu site, e tirar ela do código não muda nada sobre essas cópias. Crie uma chave nova no fornecedor, coloque no segredo da sua Edge Function e revogue a antiga. Depois confira cobrança e uso em todo o período em que a chave antiga esteve valendo.",{"q":542,"a":543},"Qualquer pessoa pode chamar minha Edge Function?","Por padrão uma function recusa uma requisição sem token nenhum, mas essa checagem é mais fraca do que parece. O Supabase documenta que a checagem da plataforma aceita também sua chave pública ou secreta, e sua chave pública está no seu frontend, onde qualquer um consegue ler. Então a checagem barra uma requisição vazia e não uma decidida. Para aceitar só seus usuários logados, verifique quem chamou dentro da function.",{"q":319,"a":545},"Pode. Uma Edge Function é o único lugar em que uma chave secreta do Supabase cabe, e o Supabase coloca as chaves do projeto no ambiente da function para você, então você nunca cola nenhuma. Use para o trabalho que precisa ver cada linha, e use o token de quem chamou para tudo que deve respeitar suas regras de Row Level Security.",{"q":547,"a":548},"Dá para fazer isso sem terminal?","Dá. O painel do Supabase tem uma seção Edge Functions onde você escreve uma function no navegador, aperta Deploy e define seu segredo na página Edge Function Secrets. O Supabase avisa que o editor do painel não guarda histórico de versões, então recomenda ele para trabalho rápido e deixa a linha de comando para o que você pretende manter.","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",[551,552,553,554,555,556,557,558],"esconder chave de api edge function supabase","supabase edge function secrets","supabase secrets set","mover chave de api para o backend","chamar openai de uma edge function","manter a chave de api fora do frontend","variáveis de ambiente edge function supabase","onde colocar uma chave secreta",{},true,"Esconder uma chave de API numa Edge Function do Supabase","\u002Fblog\u002Fmove-a-secret-to-an-edge-function","2026-10-05",{"title":5,"description":529},"blog\u002Fmove-a-secret-to-an-edge-function",[567,568,569],"Nada no navegador sabe guardar segredo, então esconder uma chave de API é movê-la para algo que saiba. Uma Edge Function do Supabase é o menor servidor que você consegue ter.","A mudança são quatro passos. Troque antes a chave que você já publicou, porque a cópia no seu bundle antigo continua legível depois que você a tira de lá.","Uma function publicada exige um token por padrão, e a chave pública do seu próprio frontend atende essa exigência. Conferir quem está chamando é um passo à parte, e é ele que impede um desconhecido de gastar a sua cota.","FzHS1gNN2QGcRAx1B18eSh6zBgasC_pQZK32AVXs254",[572,578,584,590,596,602,608,609,615,621,627,633,639,645,652,658,664,669,675,681,687,693,699,705,710,715,721,727,733,739,745,751,757,763,769,774,780,786,792,798,803,809,815,820,826,832,838,844,850,856,862,868,874,880,886,891,896,902,908,913,919],{"path":573,"title":574,"description":575,"published":576,"category":526,"image":577,"draft":530},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" ao enviar","\"New row violates row-level security policy for table objects\" quer dizer que o seu envio não tem regra insert. Deixar o bucket público não cria nenhuma.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":579,"title":580,"description":581,"published":582,"category":526,"image":583,"draft":530},"\u002Fblog\u002Fbase44-security-scan","Scan de segurança do Base44: o que só ele enxerga","O scan de segurança do Base44 verifica sete tipos de problema por dentro. Esta é a metade que ele lê e mais ninguém, e a metade que ele nunca olha.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":585,"title":586,"description":587,"published":588,"category":526,"image":589,"draft":530},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Sua chave de API vazou. A ordem em que agir","Uma chave de API vazou e você não sabe o que fazer primeiro. Nem toda chave no seu frontend é um vazamento, e a ordem importa mais que a pressa.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":591,"title":592,"description":593,"published":594,"category":526,"image":595,"draft":530},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" sem desligar o RLS","\"Infinite recursion detected in policy for relation\" significa que a sua policy perguntou à tabela que ela protege. Veja como quebrar o círculo.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":597,"title":598,"description":599,"published":600,"category":526,"image":601,"draft":530},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" no Supabase, e a correção errada","\"No API key found in request\" significa que sua requisição chegou ao Supabase sem chave. Quase toda resposta aponta para as regras do seu banco.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":603,"title":604,"description":605,"published":606,"category":526,"image":607,"draft":530},"\u002Fblog\u002Fis-base44-safe","O Base44 é seguro? O que vimos em 5.442 apps Base44","O Base44 é seguro? Rodamos nove verificações em 5.442 apps Base44 no ar. Quase todas tiraram B por motivos que o dono nunca escolheu.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":562,"title":5,"description":529,"published":563,"category":526,"image":549,"draft":530},{"path":610,"title":611,"description":612,"published":613,"category":526,"image":614,"draft":530},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Seu arquivo .env está exposto? Os doze caminhos para testar","Seu arquivo .env está exposto no seu próprio servidor web? Doze endereços dizem isso em um minuto, e um acerto significa que tudo nele já é público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":616,"title":617,"description":618,"published":619,"category":526,"image":620,"draft":530},"\u002Fblog\u002Fis-v0-safe","Segurança do v0: os 1.790 aplicativos v0 escaneados tiraram A","A segurança do v0 medida em 1.790 aplicativos v0 no ar: todos tiraram A. Só 17 citavam um banco de dados, e é sobretudo isso que esse A mede.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":622,"title":623,"description":624,"published":625,"category":526,"image":626,"draft":530},"\u002Fblog\u002Fis-bolt-safe","O Bolt é seguro? O que vimos em 1.123 aplicativos Bolt","O Bolt é seguro? Passamos 1.123 aplicativos Bolt no ar por nove verificações. A hospedagem saiu limpa. Os achados: chaves e tabelas abertas nos aplicativos.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":628,"title":629,"description":630,"published":631,"category":526,"image":632,"draft":530},"\u002Fblog\u002Fis-supabase-down-or-your-app","O Supabase caiu ou o problema é o seu app? Como saber","O Supabase caiu ou o problema é o seu app? Um projeto pausado, um banco cheio e um erro seu parecem iguais. Quatro verificações separam os casos.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":634,"title":635,"description":636,"published":637,"category":526,"image":638,"draft":530},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","O Supabase criptografa meus dados? Sim. Veja o que isso impede","O Supabase criptografa os dados? Sim: AES-256 em repouso, TLS em trânsito, SOC 2 e ISO 27001. O que cada um cobre, e o vazamento que nenhum deles impede.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":640,"title":641,"description":642,"published":643,"category":526,"image":644,"draft":530},"\u002Fblog\u002Fsupabase-free-plan-limits","Quanto custa o Supabase? Os limites do plano gratuito","Quanto custa o Supabase: o plano gratuito tem 500 MB de banco, 5 GB de egress e nenhum backup. O que acontece em cada limite e o que o Pro de $25 muda.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":646,"title":647,"description":648,"published":649,"category":650,"image":651,"draft":530},"\u002Fblog\u002Ftest-your-supabase-backup","Teste o backup do seu Supabase antes do dia em que precisar","Como testar o backup do seu Supabase: restaurar num projeto de teste, contar as linhas, entrar e procurar a linha que falta num arquivo cortado.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":653,"title":654,"description":655,"published":656,"category":650,"image":657,"draft":530},"\u002Fblog\u002Fsupabase-backup-github-action","Backup grátis do Supabase com uma GitHub Action, e a pegadinha","Um backup do Supabase com GitHub Action é grátis e serve para muitos apps. O workflow, a connection string certa e o egress de cada execução.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":659,"title":660,"description":661,"published":662,"category":650,"image":663,"draft":530},"\u002Fblog\u002Fdownload-your-supabase-backup","Por que você não consegue baixar seu backup do Supabase","Você não consegue baixar seu backup do Supabase num projeto atual, porque a cópia diária é um snapshot físico. Como conferir e como ter uma cópia só sua.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":665,"title":666,"description":667,"published":662,"category":526,"image":668,"draft":530},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": o grant que falta","A partir de 30 de outubro, uma tabela nova no Supabase responde \"permission denied for table\" até receber um grant. O e-mail mostra só metade.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":670,"title":671,"description":672,"published":673,"category":526,"image":674,"draft":530},"\u002Fblog\u002Fopen-api-endpoint-exposed","Um endpoint de API aberto é um problema? Leia o JSON","Seu scan apontou um endpoint de API aberto. Se isso importa depende do que voltou, e a maioria dos que encontramos era da própria plataforma.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":676,"title":677,"description":678,"published":679,"category":526,"image":680,"draft":530},"\u002Fblog\u002Flovable-security-scan","Escaneamento de segurança do Lovable: o que ele não prova","Escaneamento de segurança do Lovable: o que o Quick scan e o Deep scan checam, quando cada um roda, e a única coisa que nenhum escaneamento por dentro prova.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":682,"title":683,"description":684,"published":685,"category":650,"image":686,"draft":530},"\u002Fblog\u002Fsupabase-backup-auth-users","Por que seu dump do Supabase não tem usuários dentro","Rode supabase db dump sozinho e você recebe a forma do seu banco e nenhuma das linhas dele, sem o schema auth onde seus usuários moram.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":688,"title":689,"description":690,"published":691,"category":526,"image":692,"draft":530},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domínio expirado, site fora do ar: o que acontece agora","Seu domínio expirou e seu site está fora do ar. O relógio que começa a correr, por que o certificado é o problema menor, e como conferir os dois.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":694,"title":695,"description":696,"published":697,"category":526,"image":698,"draft":530},"\u002Fblog\u002Fis-lovable-safe","O Lovable é seguro? O que vimos em 18.554 aplicativos Lovable","O Lovable é seguro? Passamos 18.554 aplicativos Lovable no ar por nove verificações. A plataforma foi a mais limpa de cinco. Os achados estavam nos aplicativos.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":700,"title":701,"description":702,"published":703,"category":526,"image":704,"draft":530},"\u002Fblog\u002Fvibe-coded-app-security-checklist","O checklist de segurança do vibe coding, em nove verificações","Um checklist de segurança do vibe coding com nove itens, cada um verificável no seu app de fora por qualquer pessoa, e cada um com um teste de uma linha.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":468,"title":706,"description":707,"published":708,"category":526,"image":709,"draft":530},"Uma chave secreta da Stripe no frontend pode mover dinheiro","Uma chave secreta da Stripe exposta no seu frontend pode reembolsar, cobrar e ler cada ficha de cliente que você tem. Sua chave pk_live_ é que deve estar aí.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":218,"title":711,"description":712,"published":713,"category":526,"image":714,"draft":530},"Variáveis de ambiente do Vite expostas: o prefixo diz publique isto","Variáveis de ambiente do Vite expostas no seu app: fizeram o que o prefixo pediu. VITE_ e NEXT_PUBLIC_ significam publique isto, e a IA nunca soube o custo.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":716,"title":717,"description":718,"published":719,"category":526,"image":720,"draft":530},"\u002Fblog\u002Fbase44-source-maps","Segurança no Base44: o que um scan aponta e o que é seu para corrigir","Segurança no Base44 em 5.438 apps escaneados: três achados em quase todos são da plataforma, o source map é o selo do Base44, e a sua parte é uma lista curta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":722,"title":723,"description":724,"published":725,"category":526,"image":726,"draft":530},"\u002Fblog\u002Fis-cursor-ai-safe","O Cursor AI é seguro? O editor, o código e o app que você publicou","O Cursor AI é seguro? Três perguntas em uma busca: o que o Cursor guarda, o que o código que ele escreve erra, e se o app que você publicou está aberto.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":728,"title":729,"description":730,"published":731,"category":526,"image":732,"draft":530},"\u002Fblog\u002Fis-replit-safe","O Replit é seguro? O que vimos em 3.042 aplicativos Replit no ar","O Replit é seguro? Passamos 3.042 aplicativos Replit no ar por nove verificações externas. Os achados estavam no aplicativo publicado, não no host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":734,"title":735,"description":736,"published":737,"category":650,"image":738,"draft":530},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: sua cópia do banco não tem nenhum arquivo","Um Supabase storage backup é uma tarefa à parte. Os backups do banco guardam a lista dos seus arquivos e nenhum deles, então cada upload fica quebrado.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":740,"title":741,"description":742,"published":743,"category":650,"image":744,"draft":530},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery do Supabase: preço e limites","O point-in-time recovery do Supabase rebobina seu banco para qualquer segundo da última semana. Custa $100 por mês além do Pro e cobre só o banco.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":746,"title":747,"description":748,"published":749,"category":650,"image":750,"draft":530},"\u002Fblog\u002Fsupabase-project-paused-recover","Projeto Supabase pausado? Seus dados continuam lá","O Supabase pausou seu projeto depois de uma semana sem atividade. Nada foi apagado, Restaurar fica ao lado do nome e você tem um ano antes disso mudar.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":752,"title":753,"description":754,"published":755,"category":526,"image":756,"draft":530},"\u002Fblog\u002Fsafest-ai-app-builder","Qual builder de apps com IA é mais seguro? 30.998 apps testados","Qual builder de apps com IA é mais seguro? Escaneamos 30.998 apps no ar do Lovable, Base44, Replit, v0 e Bolt. O builder não é o que decide sua nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":758,"title":759,"description":760,"published":761,"category":526,"image":762,"draft":530},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Ative Row Level Security em toda tabela do Supabase e comprove","Ativar Row Level Security no Supabase sem política fecha a tabela por completo. Uma política sem a chave ligada não faz nada. Aqui está o SQL, e o teste.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":764,"title":765,"description":766,"published":767,"category":526,"image":768,"draft":530},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": o que o aviso não vê","O Supabase marca \"RLS disabled in public\" como erro. Ele não diz nada sobre a política de leitura que deixa a sua tabela igualmente aberta.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":77,"title":770,"description":771,"published":772,"category":526,"image":773,"draft":530},"Como rotacionar uma chave service_role do Supabase vazada","O Supabase manda fechar o vazamento primeiro. Outros guias mandam rotacionar agora. O que vale depende de para onde a sua chave service_role vazou.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":775,"title":776,"description":777,"published":778,"category":526,"image":779,"draft":530},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de segurança para vibe coding comparados, o nosso incluído","O melhor scanner de segurança para vibe coding depende de três perguntas que nenhuma lista de recursos responde. Dez ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":781,"title":782,"description":783,"published":784,"category":526,"image":785,"draft":530},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: faça você mesmo as cinco verificações","Um Supabase security checker lê o seu app publicado em vez das configurações do projeto. Aqui estão as cinco verificações e como fazer cada uma sozinho.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":787,"title":788,"description":789,"published":790,"category":526,"image":791,"draft":530},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de segurança para vibe coding: o que ele não vê","Um scanner de segurança para vibe coding lê seu app no ar, de fora. O que isso cobre, as quatro coisas que ele não consegue ver e como ler o resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":793,"title":794,"description":795,"published":796,"category":526,"image":797,"draft":530},"\u002Fblog\u002Fmissing-security-headers","Cabeçalhos de segurança faltando: quando isso importa","Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":463,"title":799,"description":800,"published":801,"category":526,"image":802,"draft":530},"Sua chave de API da OpenAI está exposta no frontend. Troque-a.","Uma chave de API da OpenAI exposta no frontend não pode ser presa a um domínio. Troque-a hoje, mova a chamada para o seu servidor e limite o gasto.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":804,"title":805,"description":806,"published":807,"category":526,"image":808,"draft":530},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chave de API exposta no frontend: o que 30.998 apps entregam","Uma chave de API exposta no seu frontend costuma ser uma chave do Google Maps. Escaneamos 30.998 apps vibe-coded e contamos quais segredos vazam de verdade.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":810,"title":811,"description":812,"published":813,"category":650,"image":814,"draft":530},"\u002Fblog\u002Fsupabase-backup-tools-compared","Ferramentas de backup do Supabase comparadas, a nossa incluída","Quatro tipos de ferramenta de backup do Supabase, o que cada uma copia de verdade e quando uma GitHub Action gratuita ganha de pagar, nós inclusive.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":415,"title":816,"description":817,"published":818,"category":526,"image":819,"draft":530},"Como usar secrets no Replit, e o que ainda assim é publicado","Como usar secrets no Replit: adicionar um, ler de volta e resolver as duas causas do undefined. E as chaves que a ferramenta Secrets não consegue proteger.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":821,"title":822,"description":823,"published":824,"category":650,"image":825,"draft":530},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups do plano gratuito do Supabase: como fazer sem terminal","No plano gratuito do Supabase não existe backup nenhum: a cópia é você que faz. Como fazer uma pelo painel e o que a rota do CSV deixa para trás.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":827,"title":828,"description":829,"published":830,"category":526,"image":831,"draft":530},"\u002Fblog\u002Fis-supabase-secure","O Supabase é seguro? É. Seu projeto é outra pergunta","O Supabase é seguro? A plataforma é auditada, criptografada e passa por pentests. A documentação deles diz onde isso termina e começam suas configurações.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":833,"title":834,"description":835,"published":836,"category":526,"image":837,"draft":530},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Onde ficam as chaves de API do Supabase: anon, service_role e URL","A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":839,"title":840,"description":841,"published":842,"category":526,"image":843,"draft":530},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":845,"title":846,"description":847,"published":848,"category":526,"image":849,"draft":530},"\u002Fblog\u002Fcors-wildcard-security-risk","Um curinga CORS é um risco de segurança? Quase nunca.","Um curinga CORS é um risco de segurança? Em geral é o padrão do seu builder e não entrega nada que o seu servidor já não desse a qualquer um que pedisse.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":851,"title":852,"description":853,"published":854,"category":650,"image":855,"draft":530},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching do Supabase não é backup. Ele só anda para a frente.","Por que o branching do Supabase não é backup: um branch começa sem os seus dados e um merge só leva o esquema. Para que ele serve e o que usar no lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":857,"title":858,"description":859,"published":860,"category":650,"image":861,"draft":530},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Como restaurar um backup do Supabase, e o que quebra depois","Como restaurar um backup do Supabase pelo painel ou por um arquivo de dump, o que a restauração substitui e por que o seu app pode continuar quebrado no fim.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":863,"title":864,"description":865,"published":866,"category":526,"image":867,"draft":530},"\u002Fblog\u002Fsupabase-storage-bucket-public","Seu bucket do Supabase Storage é público. Isso é um problema?","Um bucket público do Supabase Storage significa que quem tem a URL de um arquivo pode abri-lo. Não significa que alguém possa listar o que está lá dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":869,"title":870,"description":871,"published":872,"category":526,"image":873,"draft":530},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Uma chave de API do Google no frontend é um problema?","Uma chave de API do Google exposta no seu frontend é a chave que nosso scanner mais encontra, e quase sempre está tudo bem. Um ajuste gratuito decide isso.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":875,"title":876,"description":877,"published":878,"category":650,"image":879,"draft":530},"\u002Fblog\u002Fai-agent-deleted-my-database","Um agente de IA apagou meus dados do Supabase. O que eu recupero?","Um agente de IA apagou dados do seu banco. O que você recupera já estava decidido antes de ele rodar, e os próximos minutos decidem o resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":881,"title":882,"description":883,"published":884,"category":526,"image":885,"draft":530},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Qualquer um consegue ler seu banco Supabase? Testamos 3.680 apps","Qualquer um consegue ler seu banco de dados Supabase sem fazer login? Escaneamos 30.998 apps no ar criadas com builders de IA e medimos quantas dizem que sim.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":887,"title":888,"description":889,"published":884,"category":526,"image":890,"draft":530},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expostos: seu app está publicando o código original","Um source map exposto deixa qualquer um ler o código original do seu app, comentários incluídos. A verificação de 30 segundos e o que importa de verdade.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":343,"title":892,"description":893,"published":894,"category":526,"image":895,"draft":530},"As novas chaves de API do Supabase: qual vai no seu app?","O Supabase trocou anon e service_role por chaves publicáveis e secretas. Qual delas pertence ao seu app e qual nunca deve estar lá?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":897,"title":898,"description":899,"published":900,"category":650,"image":901,"draft":530},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","O Supabase faz backup do meu banco de dados? Depende do plano.","O Supabase faz backup do seu banco de dados? Todo dia nos planos pagos, e nada no gratuito. Como descobrir o que você tem e o que essa cópia não cobre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":903,"title":904,"description":905,"published":906,"category":526,"image":907,"draft":530},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","O Supabase Row Level Security está ligado. A tabela continua pública.","Ligar o Supabase Row Level Security não protege uma tabela. Quem protege são as políticas, e a que consertou o seu app pode deixar qualquer um entrar.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":909,"title":910,"description":911,"published":906,"category":650,"image":912,"draft":530},"\u002Fblog\u002Fversion-history-is-not-a-backup","O histórico de versões não é backup. Ele não desfaz um delete.","Lovable e Bolt guardam um histórico de versões do seu código. Seu banco de dados é um serviço à parte, e voltar atrás não traz os seus dados de volta.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":914,"title":915,"description":916,"published":917,"category":650,"image":918,"draft":530},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Três formas de fazer backup de um banco Supabase, e o que falta","O painel, o pg_dump e um serviço gerenciado. O que cada um salva de verdade, o que deixa de fora sem avisar e qual sobrevive a perder a conta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":45,"title":920,"description":921,"published":917,"category":526,"image":922,"draft":530},"Quais chaves de API são seguras no navegador e quais não são","Sua chave anon do Supabase foi feita para ser pública. Sua chave service_role não, e ela ignora todas as regras que você criar. Como diferenciar as duas.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1791705963237]