[{"data":1,"prerenderedAt":1254},["ShallowReactive",2],{"blog-pt-edge-function-returned-a-non-2xx-status-code":3,"blog-index-pt":728},{"id":4,"title":5,"body":6,"category":686,"cover":687,"coverAlt":688,"description":689,"draft":690,"extension":691,"faq":692,"image":707,"keywords":708,"meta":716,"navigation":717,"ogTitle":718,"path":719,"published":720,"seo":721,"stem":722,"tldr":723,"updated":720,"__hash__":727},"blog_pt\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code.md","\"Edge Function returned a non-2xx status code\": o erro real",{"type":7,"value":8,"toc":673},"minimark",[9,13,24,27,35,40,43,62,65,82,88,92,95,120,133,139,171,175,178,300,315,319,322,338,344,363,380,384,392,409,438,441,462,467,471,474,509,515,519,522,542,557,565,572,576,582,591,605,615,632,636,661],[10,11,12],"p",{},"Você aperta no seu app o botão que chama uma Edge Function e, em vez de um\nresultado, o app mostra isto:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Edge Function returned a non-2xx status code\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"É a mesma frase, seja qual for o problema. Uma chave faltando, uma função que\ncaiu, uma requisição recusada antes de o seu código rodar: todas dizem\n\"Edge Function returned a non-2xx status code\", então a mensagem sozinha quase\nnão diz o que consertar.",[10,28,29,30,34],{},"O que ela não conta é que o motivo já chegou. ",[31,32,33],"strong",{},"O erro voltou na mesma resposta\nque essa frase, e o supabase-js não lê o erro para você."," Pesquisar a frase traz\nos palpites dos outros. Ler a resposta traz a sua.",[36,37,39],"h2",{"id":38},"o-que-significa-edge-function-returned-a-non-2xx-status-code","O que significa \"Edge Function returned a non-2xx status code\"?",[10,41,42],{},"A sua função respondeu, e a resposta foi um erro. É só isso que a frase diz.",[10,44,45,46,49,50,57,58,61],{},"Toda resposta na web carrega um código de status, um número de três dígitos que\ndiz como a requisição foi. Qualquer coisa nos 200 quer dizer que deu certo.\nQuando o seu app chama uma função com ",[21,47,48],{},"supabase.functions.invoke",", o supabase-js\nolha esse número e, se ele estiver fora dos 200, entrega ao seu app uma frase\nfixa no lugar dos dados. A frase está escrita palavra por palavra\n",[51,52,56],"a",{"href":53,"rel":54},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fsupabase-js\u002Fblob\u002Fmaster\u002Fpackages\u002Fcore\u002Ffunctions-js\u002Fsrc\u002Ftypes.ts",[55],"nofollow","no próprio supabase-js",",\ne o erro que a carrega se chama ",[21,59,60],{},"FunctionsHttpError",".",[10,63,64],{},"Pense na chamada como uma carta que você manda para um escritório nos fundos. O\nescritório responde ao que você pediu ou devolve a carta. Quando ela volta, o\nsupabase-js lê o carimbo no envelope e avisa que ela foi devolvida. Ele não abre\no envelope. O bilhete lá dentro diz por quê, e o escritório anotou num livro de\nregistro tudo o que aconteceu enquanto estava com a sua carta.",[10,66,67,68,71,72,76,77,81],{},"Dois parentes próximos parecem iguais e querem dizer outra coisa. ",[21,69,70],{},"Failed to send a request to the Edge Function"," quer dizer que nenhuma resposta legível voltou,\ne no navegador isso costuma ser um cabeçalho CORS faltando, assunto do\n",[51,73,75],{"href":74},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","post sobre essa mensagem",". E\nse várias partes sem relação do seu app quebraram ao mesmo tempo, confira\n",[51,78,80],{"href":79},"\u002Fblog\u002Fis-supabase-down-or-your-app","se o problema é o Supabase ou o seu app","\nantes de abrir qualquer código.",[83,84],"diagram",{"alt":85,"caption":86,"src":87},"Uma requisição sai do navegador para uma Edge Function. A resposta que volta carrega o status 500 e um conteúdo cheio de linhas. O supabase-js reduz tudo a uma única barra cinza para o app, enquanto uma linha tracejada leva da barra de volta à resposta aberta e depois ao log da função.","A resposta carrega o status e o motivo. O supabase-js passa uma frase para o seu app, e o motivo continua preso ao erro e no log da função.","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fthe-reason-rides-back-1600x740.png",[36,89,91],{"id":90},"onde-está-o-erro-real","Onde está o erro real?",[10,93,94],{},"Em dois lugares, e você consegue ler os dois sem mudar uma linha de código.",[10,96,97,100,101,104,105,108,109,112,113,116,117,61],{},[31,98,99],{},"A própria resposta."," Abra o seu app publicado no Chrome, Edge ou Firefox,\naperte F12, escolha a aba ",[31,102,103],{},"Network"," e repita o que falhou. Clique na\nrequisição cujo endereço contém ",[21,106,107],{},"\u002Ffunctions\u002Fv1\u002F"," seguido do nome da sua função.\nA coluna ",[31,110,111],{},"Status"," tem o número, e a aba ",[31,114,115],{},"Response"," tem o que a função mandou\njunto: uma mensagem que o seu próprio código escreveu, um conteúdo JSON curto da\nplataforma do Supabase, ou as palavras ",[21,118,119],{},"Internal Server Error",[10,121,122,123,128,129,132],{},"Se você, ou a ferramenta que escreve o seu código, puder mudar a chamada, o\n",[51,124,127],{"href":125,"rel":126},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Ferror-handling",[55],"guia de tratamento de erros do Supabase","\nmostra como ler essa mesma resposta dentro do app, porque a resposta original\nviaja com o erro como ",[21,130,131],{},"error.context",":",[14,134,137],{"className":135,"code":136,"language":19},[17],"const { data, error } = await supabase.functions.invoke('your-function', { body })\nif (error) console.log(error.context.status, await error.context.text())\n",[21,138,136],{"__ignoreMap":23},[10,140,141,144,145,148,149,152,153,156,157,162,163,166,167,170],{},[31,142,143],{},"O livro de registro da função."," No painel do Supabase, abra ",[31,146,147],{},"Edge\nFunctions",", escolha a função e leia duas abas. ",[31,150,151],{},"Invocations"," lista cada\nrequisição com o código de status e quanto tempo levou. ",[31,154,155],{},"Logs"," guarda o que o\n",[51,158,161],{"href":159,"rel":160},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Flogging",[55],"guia de logs do Supabase","\nchama de eventos da plataforma, exceções não tratadas e mensagens de log\npróprias, ou seja, tudo o que o seu código imprimiu com ",[21,164,165],{},"console.log"," ou\n",[21,168,169],{},"console.error",". Reproduza a falha uma vez, anote o horário e leia as duas abas\nnaquele minuto.",[36,172,174],{"id":173},"leia-primeiro-o-código-de-status","Leia primeiro o código de status",[10,176,177],{},"O número diz até onde a sua requisição chegou antes de ser devolvida, e isso\ndecide onde o motivo está escrito.",[179,180,181,196],"table",{},[182,183,184],"thead",{},[185,186,187,190,193],"tr",{},[188,189,111],"th",{},[188,191,192],{},"O que aconteceu",[188,194,195],{},"Onde está o motivo",[197,198,199,221,237,250,263,276,289],"tbody",{},[185,200,201,207,210],{},[202,203,204],"td",{},[21,205,206],{},"401",[202,208,209],{},"Recusada antes de o seu código rodar, ou o seu código recusou",[202,211,212,213,216,217,220],{},"A resposta. ",[21,214,215],{},"Invalid JWT"," ou ",[21,218,219],{},"Missing authorization header"," é a plataforma",[185,222,223,228,231],{},[202,224,225],{},[21,226,227],{},"404",[202,229,230],{},"Não há função com esse nome publicada neste projeto",[202,232,233,234],{},"A resposta diz ",[21,235,236],{},"Requested function was not found",[185,238,239,244,247],{},[202,240,241],{},[21,242,243],{},"500",[202,245,246],{},"O seu código rodou e lançou um erro, ou devolveu 500 de propósito",[202,248,249],{},"A aba Logs",[185,251,252,257,260],{},[202,253,254],{},[21,255,256],{},"503",[202,258,259],{},"A função nem chegou a iniciar",[202,261,262],{},"A aba Logs: um import, um erro de sintaxe ou a configuração da função",[185,264,265,270,273],{},[202,266,267],{},[21,268,269],{},"504",[202,271,272],{},"Nenhuma resposta em 150 segundos",[202,274,275],{},"A aba Invocations, depois o que o seu código estava esperando",[185,277,278,283,286],{},[202,279,280],{},[21,281,282],{},"546",[202,284,285],{},"Acabou o tempo de CPU ou a memória",[202,287,288],{},"A aba Logs diz qual",[185,290,291,294,297],{},[202,292,293],{},"Qualquer outro 4xx",[202,295,296],{},"O seu próprio código escolheu, por exemplo ao repassar a resposta de um serviço",[202,298,299],{},"A resposta",[10,301,302,303,308,309,314],{},"Os significados vêm da\n",[51,304,307],{"href":305,"rel":306},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fstatus-codes",[55],"referência de códigos de status do Supabase","\ne da ",[51,310,313],{"href":311,"rel":312},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Flimits",[55],"página de limites",". Um\n404 não precisa de nada além desta tabela: compare o nome da função no seu app\ncom a lista do painel e confira se ela está publicada no projeto com que o seu\napp conversa. As outras linhas têm uma seção cada, logo abaixo.",[36,316,318],{"id":317},"_500-a-sua-função-rodou-e-falhou","500: a sua função rodou e falhou",[10,320,321],{},"Alguma coisa no seu código lançou um erro, e a aba Logs tem a linha.",[10,323,324,325,330,331,333,334,337],{},"A ",[51,326,329],{"href":327,"rel":328},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ftroubleshooting\u002Fedge-function-500-error-response",[55],"página do Supabase sobre esse erro","\ndivide o caso em dois. Se a resposta diz exatamente ",[21,332,119],{},", o\nseu código caiu e o log mostra o tipo de erro e a linha onde ele aconteceu, por\nexemplo ",[21,335,336],{},"TypeError: Cannot read properties of undefined",". Se a resposta diz\noutra coisa, o seu código escreveu essa mensagem e devolveu o 500 de propósito,\nentão procure na função o status que ela enviou.",[10,339,340,341],{},"Uma causa vale descartar antes de todas as outras numa função que chama a\nOpenAI, o Stripe ou qualquer API paga: ",[31,342,343],{},"um segredo que existe na sua máquina e\nnão no seu projeto publicado.",[10,345,346,347,350,351,359,360,362],{},"Dentro da função, um segredo é lido com ",[21,348,349],{},"Deno.env.get('OPENAI_API_KEY')",". Quando\nnão existe segredo com esse nome, a documentação do Deno diz que isso\n",[51,352,355,356],{"href":353,"rel":354},"https:\u002F\u002Fdocs.deno.com\u002Fapi\u002Fdeno\u002F~\u002FDeno.Env.get",[55],"devolve ",[21,357,358],{},"undefined"," em vez de\nfalhar. Então a função segue em frente, monta uma requisição com a palavra\n",[21,361,358],{}," onde a chave deveria estar e envia. A OpenAI responde com um 401\npróprio, \"Incorrect API key provided\", e a sua função repassa isso ou cai ao ler\numa resposta que não esperava. Na imagem do envelope: o escritório abriu a sua\ncarta, foi até a gaveta onde a chave deveria estar, encontrou a gaveta vazia e\ndevolveu um bilhete sobre uma chave errada.",[10,364,365,366,369,370,375,376,379],{},"O conserto fica na página ",[31,367,368],{},"Edge Function Secrets"," do seu projeto no Supabase.\nO ",[51,371,374],{"href":372,"rel":373},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Fsecrets",[55],"guia de segredos do Supabase","\ndiz que uma função lê um segredo novo na hora, então você não precisa publicar\nde novo, e que nenhum nome de segredo pode começar com ",[21,377,378],{},"SUPABASE_",", porque esse\nprefixo é reservado para os valores que o Supabase define para você. Um segredo\nque você define para o desenvolvimento local fica na sua máquina; o projeto\npublicado tem a própria lista.",[36,381,383],{"id":382},"_401-recusada-antes-de-o-seu-código-rodar","401: recusada antes de o seu código rodar",[10,385,386,387,216,389,391],{},"Se a resposta diz ",[21,388,215],{},[21,390,219],{},", a sua função\nnunca viu a requisição. A plataforma do Supabase a barrou na porta.",[10,393,394,395,398,399,402,403,408],{},"Essa porta é uma verificação chamada ",[21,396,397],{},"verify_jwt",", ligada por padrão, que lê o\ncabeçalho ",[21,400,401],{},"Authorization"," de cada requisição antes de o seu código rodar. A\n",[51,404,407],{"href":405,"rel":406},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ftroubleshooting\u002Fedge-function-401-error-response",[55],"página do Supabase sobre o 401","\nlista três jeitos de não passar por ela:",[410,411,412,419,432],"ul",{},[413,414,415,418],"li",{},[31,416,417],{},"A chave não bate com as chaves do seu projeto."," Por exemplo, uma chave\ncopiada de outro projeto, ou uma antiga que continua configurada em algum\nlugar depois de uma rotação.",[413,420,421,427,428,431],{},[31,422,423,424,426],{},"Não existe cabeçalho ",[21,425,401],{}," nenhum."," O supabase-js adiciona um\npara você. Um ",[21,429,430],{},"fetch"," simples para o endereço da função, ou um webhook de\noutro serviço, não adiciona.",[413,433,434,437],{},[31,435,436],{},"O seu projeto usa as chaves de assinatura novas do Supabase."," A\nverificação embutida só entende o formato antigo, e a solução do Supabase é\ndesligar a verificação para essa função.",[10,439,440],{},"Esse último ponto vai além de um caso só. O Supabase agora recomenda desligar a\nverificação embutida e cuidar da autenticação direto no código da sua função. A\nrecomendação tem duas metades, e a segunda é a que fica pelo caminho.",[10,442,443,444,447,448,452,453,456,457,461],{},"Se o 401 veio com uma mensagem que o seu próprio código escreveu, a plataforma\ndeixou a requisição passar e a sua função a recusou, ou repassou um 401 do\nserviço que chamava, que muitas vezes é o segredo vazio da seção do 500. Essa\ntambém é uma verificação diferente da que está por trás de ",[21,445,446],{},"PGRST301"," nas suas\nconsultas ao banco, que ",[51,449,451],{"href":450},"\u002Fblog\u002Fsupabase-invalid-jwt","tem uma página própria",". Se\no log da função mostra ",[21,454,455],{},"invalid claim: missing sub claim",", ela perguntou ao\nSupabase Auth quem estava chamando e recebeu a chave do seu projeto no lugar de\num usuário logado, o que\n",[51,458,460],{"href":459},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","o post dessa mensagem"," acompanha passo a\npasso.",[83,463],{"alt":464,"caption":465,"src":466},"Uma requisição vai do navegador, passa por um portão, entra na função e segue para um serviço externo. Cada lugar onde ela pode parar leva o seu número: 401 no portão, 404 onde não há função no endereço, 500 dentro da função, 546 e 504 num relógio ao lado, e um 401 do serviço externo que a função devolve.","O status diz até onde a requisição chegou. Um 401 no portão nunca alcançou o seu código; um 401 devolvido pelo serviço chamado, sim.","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fhow-far-it-got-1600x720.png",[36,468,470],{"id":469},"_546-e-504-sem-recursos-ou-sem-tempo","546 e 504: sem recursos ou sem tempo",[10,472,473],{},"O Supabase para uma função que consome demais, e os dois números dizem qual\nlimite ela atingiu.",[10,475,476,479,480,483,484,487,488,491,492,495,496,216,499,502,503,508],{},[31,477,478],{},"546 é processamento."," A\n",[51,481,313],{"href":311,"rel":482},[55]," dá a uma\nfunção 256 MB de memória e a cada requisição 2 segundos de tempo de CPU. Passe\nde qualquer um dos dois e a resposta diz\n",[21,485,486],{},"Function failed due to not having enough compute resources (please check logs)",",\ncom o código ",[21,489,490],{},"WORKER_RESOURCE_LIMIT"," (logs antigos dizem ",[21,493,494],{},"WORKER_LIMIT","). A aba\nLogs diz ",[21,497,498],{},"CPU Time exceeded",[21,500,501],{},"Memory limit exceeded",". A\n",[51,504,507],{"href":505,"rel":506},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ftroubleshooting\u002Fedge-function-546-error-response",[55],"página do Supabase sobre o 546","\ndá como exemplos processamento de imagens, embeddings de IA e web scraping, e a\nresposta dela é fazer menos por requisição ou passar a parte pesada para outro\nserviço.",[10,510,511,514],{},[31,512,513],{},"504 é tempo."," Uma função que não envia resposta em 150 segundos recebe um\n504. O limite de CPU só conta o tempo em que o seu código está de fato\ncalculando: a página de limites diz que ele não inclui entrada e saída\nassíncronas, e esperar a rede é exatamente isso. Então uma função esperando um\nmodelo de IA lento não está gastando CPU. Ela está gastando o relógio de 150\nsegundos, e quando ele acaba você recebe um 504, não um 546.",[36,516,518],{"id":517},"duas-correções-que-pioram-tudo","Duas correções que pioram tudo",[10,520,521],{},"Duas mudanças fazem essa mensagem sumir em minutos, e as duas deixam você numa\nsituação pior do que o erro.",[10,523,524,527,528,531,532,536,537,541],{},[31,525,526],{},"Chamar a API direto pela página."," O jeito mais rápido de uma função que\nfalha parar de falhar é parar de usá-la: colocar a chave numa variável ",[21,529,530],{},"VITE_"," e\nchamar a OpenAI direto do seu frontend. Funciona na primeira tentativa. Também\ncoloca a chave no arquivo que todo visitante baixa, porque esse prefixo é\n",[51,533,535],{"href":534},"\u002Fblog\u002Fvite-and-next-public-env-vars","uma instrução para compilar o valor dentro do seu bundle",",\ne ali qualquer pessoa consegue ler. Entre os apps publicados que escaneamos, uma\nchave da OpenAI apareceu no JavaScript de 33, e\n",[51,538,540],{"href":539},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","o que um estranho pode fazer com ela","\ntem um artigo próprio.",[10,543,544,547,548,550,551,556],{},[31,545,546],{},"Desligar a verificação e parar por aí."," Resolver um 401 desligando o\n",[21,549,397],{}," é a primeira metade do próprio conselho do Supabase. O\n",[51,552,555],{"href":553,"rel":554},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Ffunctions\u002Ffunction-configuration",[55],"guia de configuração do Supabase","\ndeixa claro o que isso faz sozinho: qualquer pessoa passa a poder invocar a sua\nEdge Function sem um JWT válido. O endereço da sua função está no seu frontend,\nà vista de todos. Se a função guarda uma chave da OpenAI, um estranho agora pode\ngastá-la através de você. Se ela usa a chave secreta do projeto, que o Supabase\ncoloca no ambiente de toda função, a requisição de um estranho roda com uma\nchave que passa por cima de todas as regras de row level security que você\nescreveu.",[10,558,559,560,564],{},"A segunda metade, uma checagem dentro da função de quem está chamando, cabe em\npoucas linhas.\n",[51,561,563],{"href":562},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Mover um segredo para uma Edge Function","\ntraz essas linhas e explica por que até a verificação padrão deixa passar mais\ngente do que o nome sugere.",[10,566,567,568,61],{},"O primeiro erro dá para ver de fora, e foi assim que o contamos. A nossa\nvarredura gratuita lê o JavaScript do seu app publicado como um estranho leria e\naponta cada chave que encontra, dizendo se ela é das que devem estar ali. Leva\nuns 20 segundos e não precisa de conta: ",[51,569,571],{"href":570},"\u002Fsecurity-scanner","escaneie o seu app",[36,573,575],{"id":574},"para-a-chave-ficar-onde-você-a-colocou","Para a chave ficar onde você a colocou",[10,577,578,581],{},[31,579,580],{},"O conserto de hoje pode ser desfeito pelo prompt da semana que vem."," Um\nbuilder a quem você pede que faça uma função voltar a funcionar tem liberdade\npara pegar o atalho acima, e o seu app continua funcionando enquanto isso.",[10,583,584],{},[31,585,586,590],{},[51,587,589],{"href":588},"\u002Fwebsite-monitoring","O Reeve Monitor"," confere a cada hora por você:",[410,592,593,596,599,602],{},[413,594,595],{},"as nove verificações a cada hora, em até três apps",[413,597,598],{},"um e-mail no dia em que uma nova varredura avaliar o seu app pior que a anterior; uma chave secreta no seu JavaScript limita sozinha a nota a D",[413,600,601],{},"se o app está no ar, a cada 60 segundos",[413,603,604],{},"um relatório mensal do que ele viu",[10,606,607],{},[31,608,609,610,614],{},"Uma função que roda com a sua chave secreta passa por cima de todas as regras\nde row level security. ",[51,611,613],{"href":612},"\u002Fsupabase-backups","O Reeve Care"," guarda uma cópia do seu\nbanco Supabase onde nada no seu projeto alcança.",[410,616,617,620,623,626,629],{},[413,618,619],{},"uma cópia criptografada conforme uma agenda, guardada no armazenamento do próprio Reeve na UE, fora da sua conta Supabase",[413,621,622],{},"cada cópia verificada antes de contar, contando as linhas de cada tabela",[413,624,625],{},"uma restauração em um clique que salva o que está lá agora antes de substituir",[413,627,628],{},"também os seus arquivos enviados, assim que você conectar uma credencial de Storage",[413,630,631],{},"tudo o que o Monitor faz",[36,633,635],{"id":634},"o-que-fazer-agora","O que fazer agora",[637,638,639],"key-takeaways",{},[410,640,641,644,647,650,653,656],{},[413,642,643],{},"Reproduza a falha uma vez e anote o horário.",[413,645,646],{},"Abra a requisição na aba Network do navegador e leia o status e a resposta antes de mudar qualquer coisa.",[413,648,649],{},"Leia as abas Invocations e Logs da função no painel do Supabase naquele minuto.",[413,651,652],{},"Num 500 de uma função que chama uma API paga, confira se o segredo está definido na página Edge Function Secrets do projeto publicado. Depois não é preciso publicar de novo.",[413,654,655],{},"Num 401 da plataforma, corrija a chave ou desligue a verificação embutida, e acrescente na mesma mudança uma checagem de quem está chamando dentro da função.",[413,657,658,659,61],{},"Nunca resolva este erro movendo a chave para uma variável ",[21,660,530],{},[10,662,663,664,667,668,672],{},"A checagem de quem está chamando é o passo mais fácil de pular, e\n",[51,665,666],{"href":562},"o guia de segredos em Edge Functions","\ntrata dela por inteiro. A ",[51,669,671],{"href":670},"\u002Fchecklist","checklist de segurança de 10 minutos","\ncobre o que costuma ficar aberto num app recém-lançado.",{"title":23,"searchDepth":674,"depth":674,"links":675},3,[676,678,679,680,681,682,683,684,685],{"id":38,"depth":677,"text":39},2,{"id":90,"depth":677,"text":91},{"id":173,"depth":677,"text":174},{"id":317,"depth":677,"text":318},{"id":382,"depth":677,"text":383},{"id":469,"depth":677,"text":470},{"id":517,"depth":677,"text":518},{"id":574,"depth":677,"text":575},{"id":634,"depth":677,"text":635},"Noções de segurança","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcover-1200x630.png","Um envelope devolvido com um carimbo amarelo atravessado na frente e a aba aberta, com a carta dobrada ainda lá dentro.","\"Edge Function returned a non-2xx status code\" quer dizer que sua função do Supabase respondeu com um erro. Veja onde ler o erro real.",false,"md",[693,695,698,701,704],{"q":39,"a":694},"Significa que a sua Edge Function do Supabase respondeu com um status de erro, qualquer número fora dos 200, e o supabase-js transformou essa resposta numa frase fixa. A frase é a mesma para uma queda do código, uma chave faltando, uma requisição recusada antes de o seu código rodar e um tempo esgotado. A resposta em si, que diz qual deles foi, continua presa ao erro, e a função mantém um log próprio.",{"q":696,"a":697},"Como eu vejo o erro real por trás?","Abra o seu app publicado, aperte F12, escolha a aba Network e repita o que falhou. Clique na requisição cujo endereço contém \u002Ffunctions\u002Fv1\u002F e leia o status e a resposta: é isso que a função enviou de fato. Depois abra Edge Functions no painel do Supabase, escolha a função e leia as abas Invocations e Logs no mesmo horário. No código, o guia do Supabase lê essa mesma resposta com await error.context.json().",{"q":699,"a":700},"Por que a minha Edge Function funciona localmente e falha depois de publicada?","Confira primeiro se um segredo existe na sua máquina e não no seu projeto publicado. O ambiente local lê o próprio arquivo de ambiente, e a função publicada lê os segredos definidos no projeto. Um segredo que falta volta como undefined em vez de erro, então a função segue em frente e falha mais adiante, geralmente quando o serviço chamado recusa uma chave vazia. Defina-o na página Edge Function Secrets; o Supabase diz que um segredo novo é lido na hora, sem novo deploy.",{"q":702,"a":703},"Devo desligar a verificação de JWT para resolver um 401?","O Supabase agora recomenda desligar a verificação embutida e checar quem está chamando dentro da sua função. As duas metades importam. Desligada sozinha, a verificação não segura mais nada, e a própria documentação do Supabase avisa que assim qualquer pessoa pode invocar a sua função sem um JWT válido. Se a função guarda uma chave da OpenAI ou a chave secreta do projeto, isso é qualquer pessoa na internet gastando a sua cota ou passando por cima das suas regras de row level security.",{"q":705,"a":706},"O que significa o erro 546 numa Edge Function do Supabase?","A função ficou sem processamento: mais de 2 segundos de tempo de CPU, ou mais que a memória dela, numa requisição. A resposta diz \"Function failed due to not having enough compute resources (please check logs)\", e a aba Logs diz qual limite foi, CPU Time exceeded ou Memory limit exceeded. Esperar uma API lenta não conta como tempo de CPU; uma função que espera demais recebe um 504 no lugar.","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",[709,710,60,711,712,713,714,715],"edge function returned a non-2xx status code","erro edge function supabase","erro supabase functions invoke","supabase edge function 500","supabase edge function 401","logs edge function supabase","erro edge function lovable",{},true,"\"Edge Function returned a non-2xx status code\" no Supabase","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","2026-10-27",{"title":5,"description":689},"blog\u002Fedge-function-returned-a-non-2xx-status-code",[724,725,726],"\"Edge Function returned a non-2xx status code\" é o que o supabase-js diz de qualquer resposta da sua função fora dos 200. O motivo real voltou na mesma resposta, e os logs da função guardam o resto.","Leia primeiro o número de status. 401 quer dizer que a requisição foi recusada antes de o seu código rodar, 404 que não há função com esse nome publicada, 500 que o seu código falhou, 546 ou 504 que acabaram os recursos ou o tempo.","Duas correções rápidas calam a mensagem e abrem um buraco: chamar a API pelo seu frontend com a chave dentro, e desligar a verificação de JWT sem colocar uma checagem sua no lugar.","QkqnTWPExRR7M8J7XjXHUG4jtHNbjjMjhmNFOlVX0K0",[729,735,741,747,753,759,764,769,775,781,787,794,800,806,807,813,819,825,831,837,843,849,855,861,867,872,878,884,890,896,902,908,914,920,926,932,937,943,949,955,960,966,972,978,984,990,995,1001,1007,1013,1019,1025,1031,1037,1042,1048,1054,1060,1066,1072,1078,1084,1090,1096,1102,1108,1114,1120,1126,1131,1137,1143,1149,1155,1161,1167,1173,1179,1185,1191,1197,1203,1209,1215,1220,1226,1232,1238,1243,1249],{"path":730,"title":731,"description":732,"published":733,"category":686,"image":734,"draft":690},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\", explicado","Supabase \"max client connections reached\": o pooler não tem lugar para mais um cliente. A porta da sua string de conexão define o limite.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":736,"title":737,"description":738,"published":739,"category":686,"image":740,"draft":690},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Erro do Supabase: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\": o Google está desativado no seu projeto Supabase. Como ativar e corrigir o redirect_uri_mismatch.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":742,"title":743,"description":744,"published":745,"category":686,"image":746,"draft":690},"\u002Fblog\u002Fviolates-foreign-key-constraint","Erro do Supabase \"violates foreign key constraint\" ao inserir","Supabase \"insert or update on table violates foreign key constraint\": sua linha aponta para uma linha que não existe. Qual, por quê, e como corrigir.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":748,"title":749,"description":750,"published":751,"category":686,"image":752,"draft":690},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Erro do Supabase \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": uma coluna obrigatória chegou vazia. De onde veio o null, e como corrigir.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":754,"title":755,"description":756,"published":757,"category":686,"image":758,"draft":690},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": para onde foi a sessão","\"Auth session missing!\" é o supabase-js sem achar nenhuma sessão logada e sem chegar a perguntar ao Supabase. Para onde foi a sessão, e a correção.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":459,"title":760,"description":761,"published":762,"category":686,"image":763,"draft":690},"Supabase \"invalid claim: missing sub claim\": ninguém está logado","\"invalid claim: missing sub claim\": o Supabase Auth recebeu um token autêntico sem nenhum usuário, a chave do projeto no lugar de uma sessão.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":74,"title":765,"description":766,"published":767,"category":686,"image":768,"draft":690},"\"Failed to send a request to the Edge Function\": a causa real","\"Failed to send a request to the Edge Function\": o navegador não recebeu uma resposta legível. O console dele diz por quê e se a sua função rodou.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":770,"title":771,"description":772,"published":773,"category":686,"image":774,"draft":690},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Por que o Supabase redireciona links de e-mail para localhost:3000","Se o Supabase redireciona para localhost:3000, a Site URL nunca foi trocada ou o seu endereço falta em Redirect URLs. A solução, e o curinga a evitar.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":776,"title":777,"description":778,"published":779,"category":686,"image":780,"draft":690},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" num link novo","Num link enviado há um minuto, \"Email link is invalid or has expired\" no Supabase costuma significar que um filtro de e-mail o usou antes. Como resolver.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":782,"title":783,"description":784,"published":785,"category":686,"image":786,"draft":690},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\", explicado","Supabase \"canceling statement due to statement timeout\": uma consulta passou do limite do seu papel, 3 segundos para um visitante. Veja antes a política RLS.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":788,"title":789,"description":790,"published":791,"category":792,"image":793,"draft":690},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" no Supabase, e o que vai junto","\"Database error deleting user\" no Supabase: seu banco recusou a exclusão. O motivo está nos seus logs, e a correção decide o que mais é apagado.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":795,"title":796,"description":797,"published":798,"category":686,"image":799,"draft":690},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" no Supabase","O webhook do Stripe numa Edge Function do Supabase diz \"No signatures found matching the expected signature\"? São duas causas. Continue verificando.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":801,"title":802,"description":803,"published":804,"category":686,"image":805,"draft":690},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" no Supabase: as três causas","O Supabase diz \"Invalid login credentials\" para senha errada, e-mail desconhecido e conta Google. Como saber qual é, e por que é vago.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":719,"title":5,"description":689,"published":720,"category":686,"image":707,"draft":690},{"path":808,"title":809,"description":810,"published":811,"category":686,"image":812,"draft":690},"\u002Fblog\u002Fcertificate-not-trusted","Certificado não confiável: três causas além do vencimento","Certificado não confiável mesmo com a data certa? Ele cita outro endereço, assinou a si mesmo ou falta um elo na cadeia. Veja como saber qual.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":814,"title":815,"description":816,"published":817,"category":686,"image":818,"draft":690},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": leia as aspas","Supabase \"invalid input syntax for type uuid\": seu app enviou algo que não é um id. Leia as aspas, segure a consulta, mantenha a coluna.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":820,"title":821,"description":822,"published":823,"category":686,"image":824,"draft":690},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\", explicado","Supabase \"duplicate key value violates unique constraint\": o valor já está em uso. Ache a coluna, escolha uma correção e tire o valor da tela.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":826,"title":827,"description":828,"published":829,"category":686,"image":830,"draft":690},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\" e a tabela está lá","Supabase \"relation does not exist\" ou PGRST205: nenhuma tabela tem esse nome nesse schema. Quatro verificações, e o que expor um schema abre.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":832,"title":833,"description":834,"published":835,"category":686,"image":836,"draft":690},"\u002Fblog\u002Fsupabase-function-not-found","Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" mostra os nomes de argumentos que seu app enviou. Compare-os com a função.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":838,"title":839,"description":840,"published":841,"category":686,"image":842,"draft":690},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" costuma ser um nome que não bate. Quatro verificações e a linha que recarrega.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":844,"title":845,"description":846,"published":847,"category":686,"image":848,"draft":690},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": dois limites, um só código","Supabase \"Email Rate Limit Exceeded\" limita cada email que seu projeto envia: 2 por hora no remetente embutido. O que conta e como aumentar.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":850,"title":851,"description":852,"published":853,"category":686,"image":854,"draft":690},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 causas","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" desconecta seus usuários. Três causas, e como o log do Auth separa cada uma.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":856,"title":857,"description":858,"published":859,"category":686,"image":860,"draft":690},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": três causas","Supabase \"permission denied for schema public\" é um grant que falta no schema. O que o removeu, e a linha que o devolve.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":862,"title":863,"description":864,"published":865,"category":686,"image":866,"draft":690},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": as três coisas que isso significa","Supabase \"Bucket not found\" é uma de três coisas: um link público para um bucket privado, um nome que não bate exatamente ou o projeto errado.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":450,"title":868,"description":869,"published":870,"category":686,"image":871,"draft":690},"Supabase invalid JWT: qual chave parou de funcionar?","Um erro Supabase invalid JWT é o PGRST301: um token assinado não passou na verificação. Num projeto novo isso é a sessão, não a chave de API.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":873,"title":874,"description":875,"published":876,"category":686,"image":877,"draft":690},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" quase sempre é nenhuma","O Supabase devolve PGRST116, \"JSON object requested, multiple (or no) rows returned\", quando a consulta não achou nada. Linha escondida parece ausente.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":879,"title":880,"description":881,"published":882,"category":686,"image":883,"draft":690},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" no Supabase: onde olhar","\"Database error saving new user\" quer dizer que algo preso ao seu cadastro no Supabase falhou e tudo foi desfeito. O erro real está nos seus logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":885,"title":886,"description":887,"published":888,"category":686,"image":889,"draft":690},"\u002Fblog\u002Fwhat-is-supabase","O que é Supabase? O banco de dados que seu builder escolheu","O que é Supabase: o banco de dados, o login e o armazenamento de arquivos do seu app. O Supabase cuida dos servidores; as regras das suas linhas são suas.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":891,"title":892,"description":893,"published":894,"category":686,"image":895,"draft":690},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Uma chave AWS exposta no seu frontend não é como uma chave OpenAI","Uma chave de acesso da AWS exposta no seu frontend lê e grava no seu armazenamento. A solução costuma ser uma presigned URL, não uma chave nova.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":897,"title":898,"description":899,"published":900,"category":686,"image":901,"draft":690},"\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":903,"title":904,"description":905,"published":906,"category":686,"image":907,"draft":690},"\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":909,"title":910,"description":911,"published":912,"category":686,"image":913,"draft":690},"\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":915,"title":916,"description":917,"published":918,"category":686,"image":919,"draft":690},"\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":921,"title":922,"description":923,"published":924,"category":686,"image":925,"draft":690},"\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":927,"title":928,"description":929,"published":930,"category":686,"image":931,"draft":690},"\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":933,"description":934,"published":935,"category":686,"image":936,"draft":690},"Esconder uma chave de API: mova para uma Edge Function do Supabase","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.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":938,"title":939,"description":940,"published":941,"category":686,"image":942,"draft":690},"\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":944,"title":945,"description":946,"published":947,"category":686,"image":948,"draft":690},"\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":950,"title":951,"description":952,"published":953,"category":686,"image":954,"draft":690},"\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":79,"title":956,"description":957,"published":958,"category":686,"image":959,"draft":690},"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":961,"title":962,"description":963,"published":964,"category":686,"image":965,"draft":690},"\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":967,"title":968,"description":969,"published":970,"category":686,"image":971,"draft":690},"\u002Fblog\u002Fsupabase-free-plan-limits","O Supabase é gratuito? Sim, com estes limites e sem backups","Sim: o plano gratuito do Supabase vai até 500 MB de banco e 5 GB de egress, sem nenhum backup. O que para em cada limite e o que muda no Pro de $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":973,"title":974,"description":975,"published":976,"category":792,"image":977,"draft":690},"\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","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":979,"title":980,"description":981,"published":982,"category":792,"image":983,"draft":690},"\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":985,"title":986,"description":987,"published":988,"category":792,"image":989,"draft":690},"\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":991,"title":992,"description":993,"published":988,"category":686,"image":994,"draft":690},"\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":996,"title":997,"description":998,"published":999,"category":686,"image":1000,"draft":690},"\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":1002,"title":1003,"description":1004,"published":1005,"category":686,"image":1006,"draft":690},"\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":1008,"title":1009,"description":1010,"published":1011,"category":792,"image":1012,"draft":690},"\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":1014,"title":1015,"description":1016,"published":1017,"category":686,"image":1018,"draft":690},"\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":1020,"title":1021,"description":1022,"published":1023,"category":686,"image":1024,"draft":690},"\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":1026,"title":1027,"description":1028,"published":1029,"category":686,"image":1030,"draft":690},"\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":1032,"title":1033,"description":1034,"published":1035,"category":686,"image":1036,"draft":690},"\u002Fblog\u002Fstripe-secret-key-in-frontend","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":534,"title":1038,"description":1039,"published":1040,"category":686,"image":1041,"draft":690},"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":1043,"title":1044,"description":1045,"published":1046,"category":686,"image":1047,"draft":690},"\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":1049,"title":1050,"description":1051,"published":1052,"category":686,"image":1053,"draft":690},"\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":1055,"title":1056,"description":1057,"published":1058,"category":686,"image":1059,"draft":690},"\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":1061,"title":1062,"description":1063,"published":1064,"category":792,"image":1065,"draft":690},"\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":1067,"title":1068,"description":1069,"published":1070,"category":792,"image":1071,"draft":690},"\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":1073,"title":1074,"description":1075,"published":1076,"category":792,"image":1077,"draft":690},"\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":1079,"title":1080,"description":1081,"published":1082,"category":686,"image":1083,"draft":690},"\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":1085,"title":1086,"description":1087,"published":1088,"category":686,"image":1089,"draft":690},"\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":1091,"title":1092,"description":1093,"published":1094,"category":686,"image":1095,"draft":690},"\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":1097,"title":1098,"description":1099,"published":1100,"category":686,"image":1101,"draft":690},"\u002Fblog\u002Frotate-supabase-service-role-key","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":1103,"title":1104,"description":1105,"published":1106,"category":686,"image":1107,"draft":690},"\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. Oito ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1109,"title":1110,"description":1111,"published":1112,"category":686,"image":1113,"draft":690},"\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":1115,"title":1116,"description":1117,"published":1118,"category":686,"image":1119,"draft":690},"\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":1121,"title":1122,"description":1123,"published":1124,"category":686,"image":1125,"draft":690},"\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":539,"title":1127,"description":1128,"published":1129,"category":686,"image":1130,"draft":690},"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":1132,"title":1133,"description":1134,"published":1135,"category":686,"image":1136,"draft":690},"\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":1138,"title":1139,"description":1140,"published":1141,"category":792,"image":1142,"draft":690},"\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":1144,"title":1145,"description":1146,"published":1147,"category":686,"image":1148,"draft":690},"\u002Fblog\u002Freplit-secrets-explained","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":1150,"title":1151,"description":1152,"published":1153,"category":792,"image":1154,"draft":690},"\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":1156,"title":1157,"description":1158,"published":1159,"category":686,"image":1160,"draft":690},"\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":1162,"title":1163,"description":1164,"published":1165,"category":686,"image":1166,"draft":690},"\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":1168,"title":1169,"description":1170,"published":1171,"category":686,"image":1172,"draft":690},"\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":1174,"title":1175,"description":1176,"published":1177,"category":686,"image":1178,"draft":690},"\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":1180,"title":1181,"description":1182,"published":1183,"category":792,"image":1184,"draft":690},"\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":1186,"title":1187,"description":1188,"published":1189,"category":792,"image":1190,"draft":690},"\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":1192,"title":1193,"description":1194,"published":1195,"category":686,"image":1196,"draft":690},"\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":1198,"title":1199,"description":1200,"published":1201,"category":686,"image":1202,"draft":690},"\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":1204,"title":1205,"description":1206,"published":1207,"category":792,"image":1208,"draft":690},"\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":1210,"title":1211,"description":1212,"published":1213,"category":686,"image":1214,"draft":690},"\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":1216,"title":1217,"description":1218,"published":1213,"category":686,"image":1219,"draft":690},"\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":1221,"title":1222,"description":1223,"published":1224,"category":686,"image":1225,"draft":690},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: é a mesma coisa que a anon key?","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":1227,"title":1228,"description":1229,"published":1230,"category":792,"image":1231,"draft":690},"\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":1233,"title":1234,"description":1235,"published":1236,"category":686,"image":1237,"draft":690},"\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":1239,"title":1240,"description":1241,"published":1236,"category":792,"image":1242,"draft":690},"\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":1244,"title":1245,"description":1246,"published":1247,"category":792,"image":1248,"draft":690},"\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":1250,"title":1251,"description":1252,"published":1247,"category":686,"image":1253,"draft":690},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","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",1794213649060]