[{"data":1,"prerenderedAt":1090},["ShallowReactive",2],{"blog-pt-database-error-saving-new-user":3,"blog-index-pt":564},{"id":4,"title":5,"body":6,"category":521,"cover":522,"coverAlt":523,"description":524,"draft":525,"extension":526,"faq":527,"image":543,"keywords":544,"meta":552,"navigation":553,"ogTitle":554,"path":555,"published":556,"seo":557,"stem":558,"tldr":559,"updated":556,"__hash__":563},"blog_pt\u002Fblog\u002Fdatabase-error-saving-new-user.md","\"Database error saving new user\" no Supabase: onde olhar",{"type":7,"value":8,"toc":508},"minimark",[9,13,24,27,35,40,43,57,60,63,76,82,86,89,92,95,120,132,138,142,149,159,162,165,169,175,182,196,201,207,211,217,220,226,237,244,257,261,264,273,285,310,316,326,337,348,366,370,373,379,399,402,406,412,421,436,446,463,467,495],[10,11,12],"p",{},"Alguém tenta criar uma conta no seu app e recebe de volta uma resposta que não é\nsobre ele:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Database error saving new user\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Ninguém consegue se cadastrar. O formulário funcionava quando você construiu, o\nseu projeto está no ar, e a única coisa que você tem é uma frase que não nomeia\ntabela, nem coluna, nem motivo.",[10,28,29,30,34],{},"Aqui está a parte que um guia atrás do outro erra: ",[31,32,33],"strong",{},"essa mensagem foi feita para\nnão te dizer nada, e o seu erro real já está escrito em outro lugar."," Procure a\nfrase e te entregam um bloco de SQL para colar, normalmente a versão de alguém de\numa função que escreve numa tabela com os nomes de coluna dessa pessoa. Colar ou\nfunciona, ou soma um segundo problema ao primeiro. A linha que diz o que falhou\nestá nos logs do seu próprio projeto, e ela nomeia a tabela.",[36,37,39],"h2",{"id":38},"o-que-quer-dizer-database-error-saving-new-user","O que quer dizer \"Database error saving new user\"",[10,41,42],{},"O Supabase aceitou a conta nova e depois desfez, porque algo preso ao cadastro\nfalhou.",[10,44,45,46,49,50,53,54,56],{},"Um cadastro escreve uma linha, numa tabela chamada ",[21,47,48],{},"auth.users"," que o Supabase\nadministra para você. A maioria dos projetos prende alguma coisa a essa escrita:\num trigger que copia a pessoa nova para uma tabela ",[21,51,52],{},"profiles"," sua, uma\nconstraint, uma chave estrangeira. Quando essa coisa presa levanta um erro, o\nbanco desfaz a operação inteira, e isso inclui a linha em ",[21,55,48],{},". Não sobra\nnenhuma conta pela metade. E também não tem nada na resposta dizendo qual das\ncoisas presas foi.",[10,58,59],{},"Pense num balcão com uma sala nos fundos. Alguém assina o livro no balcão, e um\nfuncionário leva o nome novo para trás para copiar num segundo livro. Se o\nfuncionário não consegue entrar na sala onde esse livro fica, a inscrição não\nvale: a linha do balcão é riscada e dizem à pessoa que houve um problema. O que\nninguém conta a ela é que o problema era uma porta trancada doze metros adiante.",[10,61,62],{},"A vagueza é de propósito, e é a decisão certa. O seu formulário de cadastro está\naberto na internet. Uma mensagem que nomeasse as suas tabelas estaria descrevendo\no seu banco para qualquer um disposto a digitar um e-mail nele.",[10,64,65,66,69,70,75],{},"Se a resposta disser ",[21,67,68],{},"email rate limit exceeded",", o problema não é o seu banco:\no Supabase se recusou a enviar o e-mail de confirmação, e\n",[71,72,74],"a",{"href":73},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","esse erro tem uma página própria",".",[77,78],"diagram",{"alt":79,"caption":80,"src":81},"À esquerda um livro com linhas e a mais recente riscada, uma seta para a direita levando a uma figura, e o caminho dessa figura até um segundo livro cortado por uma barra âmbar. Um painel separado ao lado mostra três linhas anotadas, uma delas em destaque.","A linha em auth.users é escrita e tirada de volta, então da falha não sobra nada além de uma linha num log que a resposta nunca menciona.","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fthe-rollback-1600x660.png",[36,83,85],{"id":84},"onde-está-o-erro-real","Onde está o erro real?",[10,87,88],{},"Nos logs do seu projeto, em dois passos, e a própria página de solução do\nSupabase dá a ordem.",[10,90,91],{},"Reproduza uma vez antes de sair procurando, para ter uma hora com que casar.\nTente um cadastro no seu app em produção, deixe falhar e anote o momento.",[10,93,94],{},"Depois, no painel do Supabase:",[96,97,98,110],"ol",{},[99,100,101,102,105,106,109],"li",{},"Abra ",[31,103,104],{},"Logs"," e leia os logs do ",[31,107,108],{},"Auth",". Ache a entrada naquela hora. Ela\ncarrega o erro que o Auth anotou por conta própria, mais específico do que a\nfrase que o seu app recebeu.",[99,111,112,113,115,116,119],{},"Se essa entrada apontar para o banco, volte em ",[31,114,104],{}," e abra os do\n",[31,117,118],{},"Postgres",". A linha do mesmo momento é o seu erro real, escrita no\nvocabulário comum do Postgres: uma coluna, uma relação, um tipo, uma\npermissão.",[10,121,122,123,125,126,128,129,131],{},"A nota de solução do Supabase para essa mensagem lista três causas. Você tem um\ntrigger ou uma função de trigger na tabela ",[21,124,48],{}," com um erro. Você\nadicionou em ",[21,127,48],{}," uma constraint que não está sendo atendida. Ou você\nestá usando Prisma e ele quebrou as permissões em ",[21,130,48],{},". É dessa mesma\nnota que vem o caminho de dois passos pelos logs acima.",[10,133,134,135,137],{},"Num app feito com Lovable, Bolt, Replit ou v0 a primeira causa cobre a maioria,\nporque copiar um cadastro novo para uma tabela ",[21,136,52],{}," é o padrão a que todo\nbuilder recorre, e um trigger é como isso é feito.",[36,139,141],{"id":140},"causa-1-o-trigger-não-alcança-a-sua-tabela","Causa 1: o trigger não alcança a sua tabela",[10,143,144,145,148],{},"O papel de banco que executa o seu trigger não pode sair do schema ",[21,146,147],{},"auth",", e o\nseu trigger escreve fora dele.",[10,150,151,152,155,156,158],{},"O Supabase explica isso no próprio fórum de discussão, e vale ter a formulação\nexata. O papel de banco que administra a autenticação, ",[21,153,154],{},"supabase_auth_admin",", só\ntem as permissões de que precisa para as próprias tarefas, então quando um\ntrigger operado por ",[21,157,154],{}," interage fora do schema auth, isso\nprovoca um erro de permissão.",[10,160,161],{},"Esse é o crachá do funcionário. Abre o escritório da frente, porque é ali que\nestá o trabalho dele. O segundo livro fica numa sala para a qual esse crachá\nnunca foi feito, e uma porta trancada não informa por que está trancada.",[10,163,164],{},"No log do Postgres isso chega como um erro de permissão que nomeia a tabela em\nque o seu trigger estava escrevendo.",[36,166,168],{"id":167},"a-saída-e-o-que-ela-entrega","A saída, e o que ela entrega",[10,170,171,174],{},[21,172,173],{},"security definer"," na função, que a faz rodar com os privilégios de quem a criou\nem vez dos de quem a chamou.",[10,176,177,178,181],{},"O Supabase diz numa linha: uma função security definer mantém os privilégios do\nusuário de banco que a criou, e enquanto esse for o papel ",[21,179,180],{},"postgres",", os seus\ntriggers de auth deveriam conseguir interagir com tabelas de fora. O funcionário\ndeixa de levar o próprio crachá e leva o do gerente.",[10,183,184,185,188,189,192,193,195],{},"Isso é uma transferência real de autoridade, então vale saber o que você\nescreveu antes de colar. Cada instrução dentro dessa função agora roda como o\ndono. O próprio exemplo do Supabase deixa o search_path vazio, com\n",[21,186,187],{},"security definer set search_path = ''",", e é por isso que o insert ali nomeia\n",[21,190,191],{},"public.profiles"," inteiro em vez de ",[21,194,52],{},". Com o search_path vazio um nome\nde tabela sozinho não resolve mais para nada. Numa função que carrega os\nprivilégios do dono ninguém consegue então trocar o alvo em silêncio por outra\ntabela, conforme o que o search_path de quem chama estiver dizendo.",[77,197],{"alt":198,"caption":199,"src":200},"O mesmo caminho desenhado duas vezes. Em cima, uma figura com um crachá pequeno é parada por uma porta trancada diante de um painel com um livro. Embaixo, a mesma figura leva um crachá maior, a porta está aberta e o caminho segue para dentro do painel.","Qual crachá a função carrega é toda a diferença. security definer é a faixa de baixo, e é o crachá do dono.","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Ftwo-passes-1600x620.png",[10,202,203,204,206],{},"O que isso não autoriza é recorrer a ",[21,205,173],{}," na próxima vez que algo\nfor negado. Deixe a função fazendo uma coisa e retornando, que é o que a versão\ndo Supabase faz.",[36,208,210],{"id":209},"causa-2-uma-regra-na-tabela-em-que-você-escreve","Causa 2: uma regra na tabela em que você escreve",[10,212,213,214,216],{},"Row Level Security na sua tabela ",[21,215,52],{}," pode recusar o insert, e o cadastro\nfalha então exatamente do mesmo jeito.",[10,218,219],{},"O guia do Supabase para esse padrão manda ligar Row Level Security nessa tabela,\ne essa instrução está certa. Para o seu trigger quer dizer que o insert precisa\nestar permitido, ou por uma policy que o cubra, ou por uma função que rode como\nalguém a quem as policies não se aplicam.",[10,221,222,223,225],{},"É aqui que isso deixa de ser um bug e vira uma decisão que alguém toma às onze da\nnoite. Ninguém consegue se cadastrar, o erro não diz nada, e no painel tem um\ninterruptor, escrito em linguagem clara, que faz o erro sumir: desligar Row Level\nSecurity em ",[21,224,52],{},". A tentativa seguinte funciona. O que também acontece é\nque uma tabela com os seus usuários, com tudo o que você guarda nela ao lado dos\nnomes deles, passa a responder a qualquer um que pedir.",[10,227,228,229,232,233,236],{},"Essa parte dá para ver de fora, e é assim que conseguimos contar. O nosso scanner\nlê apps em produção como um estranho leria. Encontramos um projeto Supabase atrás\nde 8.435 dos apps que ele avaliou. Em 3.680 deles a pergunta \"alguém sem conta\nconsegue ler esta tabela\" teve uma resposta utilizável, e ",[31,230,231],{},"2.096 responderam que\nsim",". Em ",[31,234,235],{},"394"," deles a tabela aberta tinha nome de tabela de pessoas.",[10,238,239,240,75],{},"Parte disso é de propósito, porque um cardápio publicado e uma página de anúncios\nficam em tabelas que um estranho deve ler, e o nosso scanner não consegue\ndistinguir essas de uma tabela de clientes que alguém abriu para se livrar de um\nerro. Ele relata o que respondeu. Se você prefere ver a sua própria resposta a\nficar raciocinando sobre ela, a nossa varredura gratuita lê o seu app em produção\ne diz quais tabelas responderam. Leva uns 20 segundos e não precisa de conta:\n",[71,241,243],{"href":242},"\u002Fsecurity-scanner","escaneie o seu app",[10,245,246,247,251,252,256],{},"A policy de que um trigger precisa é bem mais estreita do que desligar as regras.\n",[71,248,250],{"href":249},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Ligar Row Level Security em toda tabela","\nexplica como escrever uma, e\n",[71,253,255],{"href":254},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","\"new row violates row-level security policy\"","\né a mensagem que você recebe quando uma policy recusa um insert que você está\nvendo com os próprios olhos.",[36,258,260],{"id":259},"as-outras-causas-e-como-cada-uma-aparece-no-log","As outras causas, e como cada uma aparece no log",[10,262,263],{},"Mais quatro, e a linha do log distingue todas em poucas palavras.",[10,265,266,269,270,272],{},[31,267,268],{},"Uma tabela que não está lá."," A nota do Supabase cobre isso: uma função de\ntrigger que aponta para uma tabela que não existe ou foi apagada. Uma tabela\n",[21,271,52],{}," apagada e reconstruída com outro nome leva junto todo cadastro, e o\nlog nomeia a relação que falta.",[10,274,275,280,281,75],{},[31,276,277,278,75],{},"Uma constraint em ",[21,279,48],{}," Um check ou uma chave estrangeira adicionada\nnessa tabela que a linha nova não satisfaz. Vale procurar mesmo que você tenha\ncerteza de não ter criado trigger nenhum, porque uma chave estrangeira entre uma\ntabela sua e o usuário do auth é o jeito mais comum de essa causa chegar. No\ncomportamento padrão, essa mesma chave estrangeira é a que recusa a exclusão\nquando essa pessoa é removida depois, e\n",[71,282,284],{"href":283},"\u002Fblog\u002Fdatabase-error-deleting-user","essa mensagem tem um post só dela",[10,286,287,290,291,294,295,298,299,301,302,305,306,309],{},[31,288,289],{},"Um valor que não é do tipo certo."," Essa aparece palavra por palavra. Um\ntrigger que copia campos do cadastro de dentro de ",[21,292,293],{},"raw_user_meta_data"," lê com\n",[21,296,297],{},"->>",", e ",[21,300,297],{}," devolve texto independentemente da cara que o valor tivesse ao\nentrar. Escrever esse texto numa coluna ",[21,303,304],{},"date"," produziu, num caso relatado,\n",[21,307,308],{},"column \"birth_date\" is of type date but expression is of type text",". O conserto\né um cast, com a extração entre parênteses primeiro:",[14,311,314],{"className":312,"code":313,"language":19},[17],"(new.raw_user_meta_data->>'birthDate')::date,\n(new.raw_user_meta_data->>'height')::integer,\n",[21,315,313],{"__ignoreMap":23},[10,317,318,321,322,325],{},[31,319,320],{},"Linhas inseridas na mão."," A nota do Supabase cobre também as contas criadas\ndireto por SQL em vez de pela API do Auth, em que colunas obrigatórias do schema\nauth ficam como NULL em vez de strings vazias. Se alguém semeou usuários com um\n",[21,323,324],{},"insert",", esse é um conserto diferente de todos os de cima.",[10,327,328,329,332,333,75],{},"Mais uma linha que você pode encontrar ali:\n",[21,330,331],{},"duplicate key value violates unique constraint",". Ela quer dizer que a linha que o\nseu trigger grava já estava lá, por exemplo porque seu app insere o mesmo perfil\ndepois do cadastro, e\n",[71,334,336],{"href":335},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","esse erro tem um post só dele",[10,338,339,340,343,344,75],{},"E mais uma: ",[21,341,342],{},"null value in column … violates not-null constraint",". Seu trigger\ngravou um valor vazio numa coluna que exige um, quase sempre um campo de cadastro\nque o formulário nunca mandou, e\n",[71,345,347],{"href":346},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","esse também tem um post só dele",[10,349,350,351,354,355,358,359,362,363,75],{},"A última que você pode encontrar é\n",[21,352,353],{},"insert or update on table \"profiles\" violates foreign key constraint",". Quase\nsempre significa que o trigger foi criado com ",[21,356,357],{},"before insert",", então a pessoa\npara quem ele grava um perfil ainda não foi salva. O padrão do Supabase mais\nabaixo usa ",[21,360,361],{},"after insert",", e\n",[71,364,284],{"href":365},"\u002Fblog\u002Fviolates-foreign-key-constraint",[36,367,369],{"id":368},"a-versão-que-funciona-inteira","A versão que funciona, inteira",[10,371,372],{},"Comece pelo padrão que o Supabase publica e não por um resultado de busca, porque\nquatro coisas ali sustentam o peso e uma paráfrase costuma perder uma delas.",[14,374,377],{"className":375,"code":376,"language":19},[17],"create function public.handle_new_user()\nreturns trigger\nlanguage plpgsql\nsecurity definer set search_path = ''\nas $$\nbegin\n  insert into public.profiles (id, first_name, last_name)\n  values (new.id, new.raw_user_meta_data ->> 'first_name', new.raw_user_meta_data ->> 'last_name');\n  return new;\nend;\n$$;\n\ncreate trigger on_auth_user_created\n  after insert on auth.users\n  for each row execute procedure public.handle_new_user();\n",[21,378,376],{"__ignoreMap":23},[10,380,381,382,384,385,388,389,391,392,395,396,398],{},"As quatro são ",[21,383,173],{},", o ",[21,386,387],{},"search_path"," vazio, o ",[21,390,191],{},"\nescrito inteiro e o ",[21,393,394],{},"return new"," que deixa o cadastro seguir. Os seus próprios\nnomes de coluna entram no insert, e toda coluna que você nomear ali precisa\nexistir e precisa aceitar o que ",[21,397,297],{}," entrega.",[10,400,401],{},"O guia do Supabase acrescenta a frase que vale repetir: se o trigger falhar, ele\npode bloquear os cadastros, então teste o seu código a fundo. Crie uma conta de\nverdade no seu app em produção depois de cada mudança nele.",[36,403,405],{"id":404},"como-manter-o-seu-cadastro-funcionando-depois-de-mexer","Como manter o seu cadastro funcionando depois de mexer",[10,407,408,411],{},[31,409,410],{},"Um cadastro é a parte do seu app que você para de testar no dia em que\nfunciona."," Você se cadastrou uma vez, tem conta, e daí em diante você faz login.\nO próximo prompt que mexer nas suas tabelas pode quebrar o cadastro para todo\nmundo enquanto a sua própria sessão continua se comportando normalmente.",[10,413,414],{},[31,415,416,420],{},[71,417,419],{"href":418},"\u002Fwebsite-monitoring","O Reeve Monitor"," olha por você:",[422,423,424,427,430,433],"ul",{},[99,425,426],{},"as nove verificações a cada hora, em até três apps",[99,428,429],{},"um e-mail no dia em que uma nova varredura avaliar o seu app pior que a anterior",[99,431,432],{},"se o app está no ar, a cada 60 segundos",[99,434,435],{},"um relatório mensal do que ele viu",[10,437,438],{},[31,439,440,441,445],{},"Uma regra desligada para se livrar de um erro deixa legível uma tabela de\npessoas. ",[71,442,444],{"href":443},"\u002Fsupabase-backups","O Reeve Care"," guarda uma cópia do seu banco Supabase\nonde nenhuma mudança nas suas regras alcança.",[422,447,448,451,454,457,460],{},[99,449,450],{},"uma cópia criptografada todo dia, guardada fora da sua conta Supabase",[99,452,453],{},"cada cópia verificada antes de contar, contando as linhas de cada tabela",[99,455,456],{},"uma restauração em um clique que salva o que está lá agora antes de substituir",[99,458,459],{},"também os seus arquivos enviados, assim que você conectar uma credencial de Storage",[99,461,462],{},"tudo o que o Monitor faz",[36,464,466],{"id":465},"o-que-fazer-hoje","O que fazer hoje",[468,469,470],"key-takeaways",{},[422,471,472,475,478,489,492],{},[99,473,474],{},"Reproduza um cadastro que falhou e anote a hora antes de mudar qualquer coisa.",[99,476,477],{},"Leia a entrada do log do Auth naquele momento, e depois a linha do log do Postgres na mesma hora se a entrada do Auth apontar para o banco. Essa linha nomeia a coluna, a relação ou a permissão que falhou.",[99,479,480,481,483,484,486,487,75],{},"Confira se a sua função de trigger carrega ",[21,482,173],{}," e nomeia o alvo inteiro, como ",[21,485,191],{}," em vez de ",[21,488,52],{},[99,490,491],{},"Se uma policy nessa tabela está recusando o insert, escreva uma policy para ele. Desligar Row Level Security tira o erro e deixa essa tabela legível para qualquer um que pedir.",[99,493,494],{},"Crie uma conta de verdade no seu app em produção depois de cada mudança num trigger de cadastro. A sua própria sessão esconde completamente um cadastro quebrado de você.",[10,496,497,498,502,503,507],{},"Comece pela tabela em que o seu trigger escreve, e depois leia as policies de\ntoda tabela em que você mexeu na mesma semana. A\n",[71,499,501],{"href":500},"\u002Fchecklist","lista de segurança de 10 minutos"," cobre o que mais costuma ficar\naberto num app recém-lançado, e o\n",[71,504,506],{"href":505},"\u002Fis-your-supabase-app-safe","guia de segurança do Supabase"," passa pelo resto do\nque um estranho consegue alcançar.",{"title":23,"searchDepth":509,"depth":509,"links":510},3,[511,513,514,515,516,517,518,519,520],{"id":38,"depth":512,"text":39},2,{"id":84,"depth":512,"text":85},{"id":140,"depth":512,"text":141},{"id":167,"depth":512,"text":168},{"id":209,"depth":512,"text":210},{"id":259,"depth":512,"text":260},{"id":368,"depth":512,"text":369},{"id":404,"depth":512,"text":405},{"id":465,"depth":512,"text":466},"Noções de segurança","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcover-1200x630.png","Um livro de registro sobre um balcão com a linha mais recente já riscada, e atrás dele um segundo livro numa sala com a porta trancada.","\"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.",false,"md",[528,531,534,537,540],{"q":529,"a":530},"O que quer dizer \"Database error saving new user\"?","Quer dizer que o Supabase escreveu a pessoa nova na própria tabela auth.users, que algo preso a essa escrita falhou e que o banco desfez a operação inteira, incluindo a linha nova. Então nenhuma conta foi criada e não sobrou nada pela metade para limpar. A mensagem não nomeia tabela nem motivo de propósito, porque o seu formulário de cadastro está aberto na internet e um erro específico descreveria o seu banco para qualquer um que digitasse um e-mail nele.",{"q":532,"a":533},"Onde eu acho o erro real?","Nos logs do seu projeto, e a própria página de solução do Supabase dá a ordem. Tente um cadastro, deixe falhar e anote a hora. Abra Logs e leia a entrada do Auth daquele momento, que carrega o que o Auth anotou por conta própria. Se essa entrada apontar para o banco, abra os logs do Postgres na mesma hora: essa linha nomeia a coluna, a relação ou a permissão que de fato falhou.",{"q":535,"a":536},"Row Level Security na minha tabela profiles quebra o cadastro?","Pode quebrar. Se o seu trigger insere numa tabela com Row Level Security e nenhuma policy permite esse insert, o insert é recusado e o cadastro falha com a mesma mensagem vaga. A saída é uma policy para ele, ou uma função que roda com privilégios aos quais as policies não se aplicam. Desligar as regras nessa tabela também tira o erro, e deixa uma tabela com os seus usuários legível para qualquer um que pedir.",{"q":538,"a":539},"O que é security definer e é seguro?","Faz a função rodar com os privilégios de quem a criou em vez dos de quem a chama, que é justamente o que permite a um trigger executado pelo papel do auth escrever numa tabela sua. É o padrão que o Supabase publica, e é uma transferência real de autoridade, então a função deveria fazer uma coisa só e bem delimitada. O Supabase ainda deixa o search_path vazio no exemplo dele, e é por isso que ali o insert nomeia public.profiles inteiro e não só profiles.",{"q":541,"a":542},"Eu nunca criei trigger nenhum. O que mais pode ser?","Outras três coisas. Uma constraint ou uma chave estrangeira adicionada em auth.users que a linha nova não satisfaz. Uma função de trigger que aponta para uma tabela renomeada ou apagada. E a nota do Supabase cita o Prisma pelo nome, porque ele pode quebrar as permissões em auth.users. Qual delas é, a linha do log do Postgres te diz.","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",[545,546,547,548,549,550,551],"database error saving new user","supabase database error saving new user","erro de cadastro supabase","erro trigger auth.users","handle_new_user não funciona","supabase security definer trigger","supabase erro 500 cadastro",{},true,"\"Database error saving new user\" no Supabase","\u002Fblog\u002Fdatabase-error-saving-new-user","2026-10-14",{"title":5,"description":524},"blog\u002Fdatabase-error-saving-new-user",[560,561,562],"\"Database error saving new user\" quer dizer que o Supabase aceitou o cadastro, algo preso a ele falhou e tudo foi desfeito. Nenhuma conta foi criada.","A mensagem é vaga de propósito, e a de verdade já está anotada. A própria página de solução do Supabase manda você primeiro nos logs do Auth e depois nos do Postgres, na linha que fica embaixo.","Quase sempre é um trigger em auth.users que não alcança a tabela em que escreve. A saída é uma função security definer, e o que precisa ficar certo é quanto ela tem permissão de fazer.","82rLOQQMna7rCEVIP_g25juVb5NM6_blMaZTTP-RNR0",[565,571,577,582,587,593,599,605,611,617,623,629,635,641,647,653,659,664,670,676,682,687,693,699,705,711,717,718,724,730,736,742,748,754,760,766,772,778,784,790,796,802,808,814,820,826,831,837,843,849,855,861,867,873,879,885,891,897,903,909,915,921,926,932,938,944,950,956,962,968,974,980,986,992,998,1004,1009,1015,1021,1027,1033,1039,1045,1051,1056,1062,1068,1074,1079,1085],{"path":566,"title":567,"description":568,"published":569,"category":521,"image":570,"draft":525},"\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":572,"title":573,"description":574,"published":575,"category":521,"image":576,"draft":525},"\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":365,"title":578,"description":579,"published":580,"category":521,"image":581,"draft":525},"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":346,"title":583,"description":584,"published":585,"category":521,"image":586,"draft":525},"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":588,"title":589,"description":590,"published":591,"category":521,"image":592,"draft":525},"\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":594,"title":595,"description":596,"published":597,"category":521,"image":598,"draft":525},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","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":600,"title":601,"description":602,"published":603,"category":521,"image":604,"draft":525},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"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":606,"title":607,"description":608,"published":609,"category":521,"image":610,"draft":525},"\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":612,"title":613,"description":614,"published":615,"category":521,"image":616,"draft":525},"\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":618,"title":619,"description":620,"published":621,"category":521,"image":622,"draft":525},"\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":283,"title":624,"description":625,"published":626,"category":627,"image":628,"draft":525},"\"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":630,"title":631,"description":632,"published":633,"category":521,"image":634,"draft":525},"\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":636,"title":637,"description":638,"published":639,"category":521,"image":640,"draft":525},"\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":642,"title":643,"description":644,"published":645,"category":521,"image":646,"draft":525},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": o erro real","\"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.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":648,"title":649,"description":650,"published":651,"category":521,"image":652,"draft":525},"\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":654,"title":655,"description":656,"published":657,"category":521,"image":658,"draft":525},"\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":335,"title":660,"description":661,"published":662,"category":521,"image":663,"draft":525},"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":665,"title":666,"description":667,"published":668,"category":521,"image":669,"draft":525},"\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":671,"title":672,"description":673,"published":674,"category":521,"image":675,"draft":525},"\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":677,"title":678,"description":679,"published":680,"category":521,"image":681,"draft":525},"\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":73,"title":683,"description":684,"published":685,"category":521,"image":686,"draft":525},"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":688,"title":689,"description":690,"published":691,"category":521,"image":692,"draft":525},"\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":694,"title":695,"description":696,"published":697,"category":521,"image":698,"draft":525},"\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":700,"title":701,"description":702,"published":703,"category":521,"image":704,"draft":525},"\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":706,"title":707,"description":708,"published":709,"category":521,"image":710,"draft":525},"\u002Fblog\u002Fsupabase-invalid-jwt","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":712,"title":713,"description":714,"published":715,"category":521,"image":716,"draft":525},"\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":555,"title":5,"description":524,"published":556,"category":521,"image":543,"draft":525},{"path":719,"title":720,"description":721,"published":722,"category":521,"image":723,"draft":525},"\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":725,"title":726,"description":727,"published":728,"category":521,"image":729,"draft":525},"\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":731,"title":732,"description":733,"published":734,"category":521,"image":735,"draft":525},"\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":737,"title":738,"description":739,"published":740,"category":521,"image":741,"draft":525},"\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":743,"title":744,"description":745,"published":746,"category":521,"image":747,"draft":525},"\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":749,"title":750,"description":751,"published":752,"category":521,"image":753,"draft":525},"\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":755,"title":756,"description":757,"published":758,"category":521,"image":759,"draft":525},"\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":761,"title":762,"description":763,"published":764,"category":521,"image":765,"draft":525},"\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":767,"title":768,"description":769,"published":770,"category":521,"image":771,"draft":525},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","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":773,"title":774,"description":775,"published":776,"category":521,"image":777,"draft":525},"\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":779,"title":780,"description":781,"published":782,"category":521,"image":783,"draft":525},"\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":785,"title":786,"description":787,"published":788,"category":521,"image":789,"draft":525},"\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":791,"title":792,"description":793,"published":794,"category":521,"image":795,"draft":525},"\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":797,"title":798,"description":799,"published":800,"category":521,"image":801,"draft":525},"\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":803,"title":804,"description":805,"published":806,"category":521,"image":807,"draft":525},"\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":809,"title":810,"description":811,"published":812,"category":627,"image":813,"draft":525},"\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":815,"title":816,"description":817,"published":818,"category":627,"image":819,"draft":525},"\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":821,"title":822,"description":823,"published":824,"category":627,"image":825,"draft":525},"\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":827,"title":828,"description":829,"published":824,"category":521,"image":830,"draft":525},"\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":832,"title":833,"description":834,"published":835,"category":521,"image":836,"draft":525},"\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":838,"title":839,"description":840,"published":841,"category":521,"image":842,"draft":525},"\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":844,"title":845,"description":846,"published":847,"category":627,"image":848,"draft":525},"\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":850,"title":851,"description":852,"published":853,"category":521,"image":854,"draft":525},"\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":856,"title":857,"description":858,"published":859,"category":521,"image":860,"draft":525},"\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":862,"title":863,"description":864,"published":865,"category":521,"image":866,"draft":525},"\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":868,"title":869,"description":870,"published":871,"category":521,"image":872,"draft":525},"\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":874,"title":875,"description":876,"published":877,"category":521,"image":878,"draft":525},"\u002Fblog\u002Fvite-and-next-public-env-vars","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":880,"title":881,"description":882,"published":883,"category":521,"image":884,"draft":525},"\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":886,"title":887,"description":888,"published":889,"category":521,"image":890,"draft":525},"\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":892,"title":893,"description":894,"published":895,"category":521,"image":896,"draft":525},"\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":898,"title":899,"description":900,"published":901,"category":627,"image":902,"draft":525},"\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":904,"title":905,"description":906,"published":907,"category":627,"image":908,"draft":525},"\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":910,"title":911,"description":912,"published":913,"category":627,"image":914,"draft":525},"\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":916,"title":917,"description":918,"published":919,"category":521,"image":920,"draft":525},"\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":249,"title":922,"description":923,"published":924,"category":521,"image":925,"draft":525},"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":927,"title":928,"description":929,"published":930,"category":521,"image":931,"draft":525},"\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":933,"title":934,"description":935,"published":936,"category":521,"image":937,"draft":525},"\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":939,"title":940,"description":941,"published":942,"category":521,"image":943,"draft":525},"\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":945,"title":946,"description":947,"published":948,"category":521,"image":949,"draft":525},"\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":951,"title":952,"description":953,"published":954,"category":521,"image":955,"draft":525},"\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":957,"title":958,"description":959,"published":960,"category":521,"image":961,"draft":525},"\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":963,"title":964,"description":965,"published":966,"category":521,"image":967,"draft":525},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","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":969,"title":970,"description":971,"published":972,"category":521,"image":973,"draft":525},"\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":975,"title":976,"description":977,"published":978,"category":627,"image":979,"draft":525},"\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":981,"title":982,"description":983,"published":984,"category":521,"image":985,"draft":525},"\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":987,"title":988,"description":989,"published":990,"category":627,"image":991,"draft":525},"\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":993,"title":994,"description":995,"published":996,"category":521,"image":997,"draft":525},"\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":999,"title":1000,"description":1001,"published":1002,"category":521,"image":1003,"draft":525},"\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":254,"title":1005,"description":1006,"published":1007,"category":521,"image":1008,"draft":525},"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":1010,"title":1011,"description":1012,"published":1013,"category":521,"image":1014,"draft":525},"\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":1016,"title":1017,"description":1018,"published":1019,"category":627,"image":1020,"draft":525},"\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":1022,"title":1023,"description":1024,"published":1025,"category":627,"image":1026,"draft":525},"\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":1028,"title":1029,"description":1030,"published":1031,"category":521,"image":1032,"draft":525},"\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":1034,"title":1035,"description":1036,"published":1037,"category":521,"image":1038,"draft":525},"\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":1040,"title":1041,"description":1042,"published":1043,"category":627,"image":1044,"draft":525},"\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":1046,"title":1047,"description":1048,"published":1049,"category":521,"image":1050,"draft":525},"\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":1052,"title":1053,"description":1054,"published":1049,"category":521,"image":1055,"draft":525},"\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":1057,"title":1058,"description":1059,"published":1060,"category":521,"image":1061,"draft":525},"\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":1063,"title":1064,"description":1065,"published":1066,"category":627,"image":1067,"draft":525},"\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":1069,"title":1070,"description":1071,"published":1072,"category":521,"image":1073,"draft":525},"\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":1075,"title":1076,"description":1077,"published":1072,"category":627,"image":1078,"draft":525},"\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":1080,"title":1081,"description":1082,"published":1083,"category":627,"image":1084,"draft":525},"\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":1086,"title":1087,"description":1088,"published":1083,"category":521,"image":1089,"draft":525},"\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",1794213649245]