[{"data":1,"prerenderedAt":1043},["ShallowReactive",2],{"blog-pt-supabase-single-row-error":3,"blog-index-pt":512},{"id":4,"title":5,"body":6,"category":469,"cover":470,"coverAlt":471,"description":472,"draft":473,"extension":474,"faq":475,"image":491,"keywords":492,"meta":500,"navigation":501,"ogTitle":502,"path":503,"published":504,"seo":505,"stem":506,"tldr":507,"updated":504,"__hash__":511},"blog_pt\u002Fblog\u002Fsupabase-single-row-error.md","Supabase \"multiple (or no) rows returned\" quase sempre é nenhuma",{"type":7,"value":8,"toc":455},"minimark",[9,13,16,27,43,48,51,54,61,65,72,96,102,111,137,141,147,164,174,177,181,184,193,196,202,205,212,216,219,250,253,261,265,270,273,279,285,289,292,295,298,302,310,315,331,336,345,349,355,364,379,389,406,410,442],[10,11,12],"p",{},"Seu app diz a alguém que um registro não foi encontrado. Você abre o Table Editor\ndo Supabase e o registro está ali, na tabela, com o id certo.",[10,14,15],{},"Isto foi o que voltou do banco:",[17,18,23],"pre",{"className":19,"code":21,"language":22},[20],"language-text","{\n  \"code\": \"PGRST116\",\n  \"message\": \"JSON object requested, multiple (or no) rows returned\",\n  \"details\": \"Results contain 0 rows, application\u002Fvnd.pgrst.object+json requires 1 row\"\n}\n","text",[24,25,21],"code",{"__ignoreMap":26},"",[10,28,29,30,34,35,38,39,42],{},"E esta é a parte que guia após guia erra: ",[31,32,33],"strong",{},"zero linhas é uma resposta que suas\npróprias regras conseguem produzir, e ela se lê exatamente como dados que\nsumiram."," Procure essa mensagem e vão te dizer para trocar ",[24,36,37],{},".single()"," por\n",[24,40,41],{},".maybeSingle()",". Isso de fato para o erro. Não te diz nada sobre a linha estar\nfaltando ou sobre seu visitante nunca ter tido permissão de vê-la, e esses dois\ncasos se consertam de formas diferentes.",[44,45,47],"h2",{"id":46},"o-que-significa-json-object-requested-multiple-or-no-rows-returned","O que significa \"JSON object requested, multiple (or no) rows returned\"?",[10,49,50],{},"Sua consulta pediu ao banco exatamente uma linha e o resultado tinha outro\nnúmero. Quase sempre esse número é zero.",[10,52,53],{},"Pense numa sala de leitura onde você preenche uma ficha e alguém atrás do balcão\nvai buscar o livro. Sua ficha diz: traga o único livro com este número. O balcão\nvolta e diz que não há nada correspondente à ficha. Essa é a única resposta que o\nbalcão dá, e é a mesma tanto se o livro nunca esteve no catálogo quanto se ele\nestá numa estante para a qual você não tem autorização. Ninguém está te\nenrolando. O sistema de fichas foi construído para que aquilo que você não tem\nautorização de ver simplesmente não apareça na sua visão do catálogo.",[10,55,56,57,60],{},"Seu app é quem segura a ficha, e o número com que o balcão voltou está escrito na\nlinha ",[24,58,59],{},"details"," da resposta.",[44,62,64],{"id":63},"duas-mensagens-diferentes-e-o-mesmo-código-de-erro","Duas mensagens diferentes, e o mesmo código de erro",[10,66,67,68,71],{},"O código é estável e a frase não é, então se guie pelo ",[24,69,70],{},"PGRST116",".",[10,73,74,75,78,79,81,82,85,86,89,90,92,93,71],{},"Há duas redações em circulação para esse único erro, e qual você vê depende de\nqual versão do PostgREST seu projeto roda. O PostgREST é o servidor que transforma\nsuas tabelas do Supabase na API HTTP com que seu app conversa. A documentação da\nversão 12 dá a mensagem\n",[24,76,77],{},"JSON object requested, multiple (or no) rows returned",", com uma linha ",[24,80,59],{},"\ndizendo\n",[24,83,84],{},"Results contain 0 rows, application\u002Fvnd.pgrst.object+json requires 1 row",". Nas\nversões 13 e 14 a mesma situação está documentada como\n",[24,87,88],{},"Cannot coerce the result to a single JSON object",", com ",[24,91,59],{}," dizendo\n",[24,94,95],{},"The result contains 0 rows",[10,97,98,99,101],{},"A frase mais antiga tem uma segunda vida além dos projetos velhos. Quando você\nchama ",[24,100,41],{}," e mais de uma linha bate, o cliente JavaScript do Supabase\nescreve o erro ele mesmo em vez de repassar um do servidor, e a mensagem que ele\nescreve é a redação antiga. Então a primeira frase continua chegando em apps cujo\nbanco teria mandado a segunda.",[10,103,104,105,107,108,110],{},"O que não se move é o código. A tabela de erros do PostgREST lista ",[24,106,70],{}," em\n406 nas três versões, com a mesma descrição: mais de uma linha, ou nenhuma,\nquando exatamente uma foi pedida. Leia o campo ",[24,109,24],{}," e ignore o texto.",[112,113,115],"callout",{"type":114},"warn",[10,116,117,120,121,124,125,128,129,132,133,136],{},[31,118,119],{},"Se você compara a mensagem como texto no seu próprio código, compare o código\nem vez disso."," Um bloco ",[24,122,123],{},"catch"," que mede ",[24,126,127],{},"error.message"," contra\n",[24,130,131],{},"'JSON object requested, multiple (or no) rows returned'"," funciona hoje e para de\nfuncionar no dia em que seu projeto passar para um PostgREST mais novo, sem\nnenhum deploy seu no meio. ",[24,134,135],{},"error.code === 'PGRST116'"," sobrevive a isso.",[44,138,140],{"id":139},"por-que-single-produz-isso","Por que .single() produz isso",[10,142,143,144,146],{},"Porque ",[24,145,37],{}," é uma instrução sobre a forma da resposta e não um filtro\nsobre os dados.",[10,148,149,150,152,153,156,157,160,161,71],{},"Quando você escreve ",[24,151,37],{},", o cliente do Supabase acrescenta um cabeçalho ao\npedido: ",[24,154,155],{},"Accept: application\u002Fvnd.pgrst.object+json",". Esse cabeçalho pede que o\nbanco mande a linha sozinha, como um registro. É ele que deixa seu código\nescrever ",[24,158,159],{},"data.name"," onde de outra forma teria de escrever ",[24,162,163],{},"data[0].name",[10,165,166,167,169,170,173],{},"O banco cumpre isso à risca. Uma linha volta como um registro. Qualquer outro\nnúmero de linhas não pode ser mandado nessa forma, então a resposta é um 406 e um\nobjeto de erro. Tire o ",[24,168,37],{}," e a consulta idêntica devolve ",[24,171,172],{},"[]"," com um 200 e\nnenhum erro em lugar nenhum.",[10,175,176],{},"Então nada precisou quebrar para produzir isso. Um resultado vazio virou um erro\nporque sua consulta disse que a resposta tinha de conter exatamente um registro.",[44,178,180],{"id":179},"causa-1-a-linha-está-lá-e-suas-regras-dizem-não","Causa 1: a linha está lá e suas regras dizem não",[10,182,183],{},"Row Level Security não recusa sua consulta. Ela tira linhas dela, e uma linha\ntirada nunca esteve no resultado que é contado.",[10,185,186,187,189,190,192],{},"Row Level Security é o conjunto de regras em cada tabela do Supabase que decide,\nlinha a linha, quais linhas um dado visitante pode ler. Quando nenhuma regra\npermite que seu visitante leia a linha que sua consulta nomeou, essa linha é\nretirada antes de o resultado ser medido. A contagem é zero. Seu ",[24,188,37],{},"\nqueria uma. Você recebe ",[24,191,70],{},", e nenhuma parte da resposta menciona que\nhouve uma regra no meio.",[10,194,195],{},"É a sala de leitura de novo, e é por isso que o balcão diz a mesma coisa duas\nvezes. Sua autorização é aplicada antes mesmo de a estante ser vasculhada, então\num livro que você não pode levar e um livro que não existe produzem uma ficha\nidêntica de volta.",[197,198],"diagram",{"alt":199,"caption":200,"src":201},"Um pedido entra pela esquerda e se divide em duas faixas. Na faixa de cima uma estante tem uma linha desenhada em teal, e a faixa é parada por uma barra âmbar antes de chegar à estante. Na faixa de baixo a estante está vazia e desenhada em linha tracejada. As duas faixas terminam na mesma bandeja vazia, marcada com um zero.","Uma linha que suas regras escondem e uma linha que não está deixam o resultado vazio do mesmo jeito. A resposta conta linhas, então as duas chegam como o mesmo erro.","\u002Fblog\u002Fsupabase-single-row-error\u002Ftwo-reasons-one-answer-1600x700.png",[10,203,204],{},"É também por isso que o Table Editor te engana. O SQL Editor e o Table Editor do\nseu painel do Supabase rodam com privilégios aos quais suas policies não se\naplicam, então mostram todas as linhas. O pedido do seu app leva sua publishable\nkey e a sessão do seu visitante, e nele as policies se aplicam. Duas visões de\numa mesma tabela, e só uma delas é a que seus usuários recebem.",[10,206,207,208,211],{},"Essa diferença dá para ler de fora, e é assim que conseguimos contá-la. Nosso\nscanner lê apps no ar como um estranho faria. Atrás de 8.435 dos apps que ele\navaliou há um projeto Supabase. Em 3.680 deles a pergunta \"alguém sem conta\nconsegue ler esta tabela?\" teve uma resposta utilizável, e ",[31,209,210],{},"1.584 responderam\nque não",": um estranho que pediu as linhas não recebeu nada. Esse nada é o mesmo\nnada que o seu próprio app recebe quando nenhuma policy se aplica a ele.",[44,213,215],{"id":214},"como-distinguir-uma-linha-escondida-de-uma-que-falta","Como distinguir uma linha escondida de uma que falta",[10,217,218],{},"Rode a mesma busca duas vezes, uma onde as policies se aplicam e outra onde não\nse aplicam. Uma consulta resolve.",[220,221,222,238,244],"ol",{},[223,224,225,226,229,230,233,234,237],"li",{},"Abra seu painel do Supabase, vá no ",[31,227,228],{},"SQL Editor"," e pegue a linha pelo mesmo\nvalor que seu app usou:\n",[24,231,232],{},"select * from your_table where id = 'the-id-your-app-sent';",". Uma consulta a\npartir do SQL Editor roda pelo papel ",[24,235,236],{},"postgres",", ao qual suas policies não se\naplicam.",[223,239,240,243],{},[31,241,242],{},"Se ela devolver a linha",", a linha existe e alguma coisa entre seu app e a\nlinha a retirou. Essa coisa é uma policy, e você está na causa 1. Leia as\npolicies daquela tabela.",[223,245,246,249],{},[31,247,248],{},"Se ela também não devolver nada",", a linha falta de verdade e você está na\ncausa 3 mais abaixo. Suas regras não têm nada a ver.",[10,251,252],{},"Faça isso antes de mudar uma linha de código. As duas causas produzem o mesmo\nobjeto de erro, e os dois consertos não têm nada em comum.",[10,254,255,256,71],{},"Já que você está olhando as policies daquela tabela, vale saber o que elas dizem\nhoje para alguém sem conta nenhuma. Nosso scan gratuito lê seu app no ar e diz\nquais das suas tabelas respondem a um estranho. Leva cerca de 20 segundos e não\nprecisa de conta: ",[257,258,260],"a",{"href":259},"\u002Fsecurity-scanner","escanear seu app",[44,262,264],{"id":263},"causa-2-voltaram-várias-linhas","Causa 2: voltaram várias linhas",[10,266,267,269],{},[24,268,37],{}," foi usado numa busca que pode bater com mais de uma linha.",[10,271,272],{},"Uma busca por chave primária bate com uma linha ou com nenhuma, por definição.\nUma busca por email, por slug, por nome, por status, por chave estrangeira:\nqualquer uma delas pode tocar duas. A história de sempre é que a coluna tinha um\nvalor por linha nos seus dados de teste e deixou de ter quando gente de verdade\nchegou.",[10,274,275,276,278],{},"A resposta te diz em qual causa você está. As duas redações da linha ",[24,277,59],{},"\ndizem quantas linhas o resultado continha. Zero te manda para a causa 1 ou para a\ncausa 3. Um número acima de zero aponta esta aqui, e é a contagem das linhas que\nbateram.",[10,280,281,282,284],{},"O conserto não é ",[24,283,41],{},". Ele aceita zero linhas e continua dando erro\ncom duas, então aqui não muda nada. Ou você estreita a consulta para uma linha\ncom a coluna que é de fato única, ou aceita que há várias e lê uma lista.",[44,286,288],{"id":287},"causa-3-a-linha-sumiu-mesmo","Causa 3: a linha sumiu mesmo",[10,290,291],{},"Às vezes a linha falta, e a consulta da seção anterior é o que confirma isso.",[10,293,294],{},"Os motivos comuns, na ordem em que aparecem num app feito no vibe coding. O valor\npelo qual sua consulta filtrava estava vazio, porque o id não tinha carregado\nquando a consulta saiu, então nada bateu. A linha foi apagada, por você ou por um\nprompt que reescreveu mais do que você esperava. Ou a consulta nomeia uma tabela\nque foi refeita com outro nome e as linhas antigas foram junto com a tabela\nantiga.",[10,296,297],{},"Nada disso é um problema de segurança, e nenhum se resolve mudando uma policy. Se\no SQL Editor não achar nada, pare de ler sobre Row Level Security e vá ver o que\nseu app está passando.",[44,299,301],{"id":300},"single-ou-maybesingle-qual-a-sua-consulta-quer","single ou maybeSingle: qual a sua consulta quer",[10,303,304,306,307,309],{},[24,305,41],{}," onde não achar nada é uma resposta legítima. ",[24,308,37],{}," onde\nnão é.",[10,311,312,314],{},[24,313,37],{}," trata qualquer número de linhas diferente de um como erro. É o\ncomportamento certo para uma busca por chave primária, onde zero linhas quer\ndizer que o registro de que seu código trata não existe e seguir em frente seria\npior do que parar.",[10,316,317,319,320,323,324,327,328,330],{},[24,318,41],{}," aceita zero linhas: devolve ",[24,321,322],{},"data"," como ",[24,325,326],{},"null",", sem erro e com\num 200. Mais de uma linha continua sendo erro, com o mesmo código ",[24,329,70],{},".\nEntão ele serve para uma linha de perfil que pode ainda não ter sido criada, ou\npara um registro opcional para o qual sua página desenha um estado vazio.",[197,332],{"alt":333,"caption":334,"src":335},"Duas faixas rotuladas single e maybeSingle. Cada faixa tem três casas marcadas 0, 1 e 2. Na faixa single a casa 1 está aceita em teal e as casas 0 e 2 levam uma cruz âmbar. Na faixa maybeSingle as casas 0 e 1 estão aceitas e só a casa 2 está cruzada.","A única diferença está no que cada um faz com um resultado vazio. Os dois recusam duas linhas, e nenhum deles muda o que o banco realmente devolveu.","\u002Fblog\u002Fsupabase-single-row-error\u002Fwhat-each-one-accepts-1600x640.png",[10,337,338,339,341,342,344],{},"Uma coisa para tomar cuidado. Trocar ",[24,340,37],{}," por ",[24,343,41],{}," muda como\nseu app se comporta e não muda nada do que o banco mandou. Se uma policy estava\nescondendo a linha, você transformou um erro visível numa página que aparece como\nse o registro não existisse, justo para a única pessoa que deveria vê-lo. O erro\nestava te dizendo alguma coisa. Faça a troca depois do teste acima, quando você\nsouber que zero é a resposta honesta.",[44,346,348],{"id":347},"ficar-de-olho-nas-suas-regras-depois-de-mudá-las","Ficar de olho nas suas regras depois de mudá-las",[10,350,351,354],{},[31,352,353],{},"Uma policy que você abre para se livrar desse erro é uma mudança que ninguém vê\nde dentro do seu app."," Sua própria sessão continua funcionando, o erro sumiu, e\nse aquela tabela agora responde a um estranho é uma pergunta que alguém precisa\nir fazer.",[10,356,357],{},[31,358,359,363],{},[257,360,362],{"href":361},"\u002Fwebsite-monitoring","O Reeve Monitor"," faz ela por você:",[365,366,367,370,373,376],"ul",{},[223,368,369],{},"as nove verificações a cada hora, em até três apps",[223,371,372],{},"um email no dia em que um novo scan avaliar seu app pior que o anterior",[223,374,375],{},"se o app responde, a cada 60 segundos",[223,377,378],{},"um relatório mensal do que ele viu",[10,380,381],{},[31,382,383,384,388],{},"Uma regra afrouxada o bastante para se livrar de um erro pode deixar um\nestranho mudar linhas além de lê-las.\n",[257,385,387],{"href":386},"\u002Fsupabase-backups","O Reeve Care"," guarda uma cópia do seu banco de dados do\nSupabase onde nenhuma mudança nas suas regras alcança.",[365,390,391,394,397,400,403],{},[223,392,393],{},"uma cópia criptografada todo dia, guardada fora da sua conta do Supabase",[223,395,396],{},"cada cópia verificada antes de contar, contando as linhas de cada tabela",[223,398,399],{},"uma restauração em um clique que salva o que está lá antes de substituir",[223,401,402],{},"seus arquivos enviados também, assim que você conectar um acesso de Storage",[223,404,405],{},"tudo o que o Monitor faz",[44,407,409],{"id":408},"o-que-fazer-hoje","O que fazer hoje",[411,412,413],"key-takeaways",{},[365,414,415,424,430,433,439],{},[223,416,417,418,420,421,423],{},"Se guie pelo campo ",[24,419,24],{},". ",[24,422,70],{}," chega sob duas frases diferentes, e qual delas você recebe depende da versão do PostgREST que seu projeto roda.",[223,425,426,427,429],{},"Leia a contagem de linhas na linha ",[24,428,59],{},". Zero quer dizer resultado vazio. Acima de zero, sua busca tocou várias linhas e precisa de uma coluna única.",[223,431,432],{},"Num resultado vazio, rode a mesma busca no SQL Editor antes de mudar código. Se a linha voltar lá e não no seu app, uma policy a retirou.",[223,434,435,436,438],{},"Passe para ",[24,437,41],{}," quando souber que zero é a resposta honesta. Numa linha que uma policy esconde, ele troca um erro por uma página vazia, sem aviso.",[223,440,441],{},"Depois de mudar uma policy para se livrar disso, verifique o que aquela tabela devolve agora para alguém sem conta.",[10,443,444,445,449,450,454],{},"Comece por uma consulta no SQL Editor, porque é ela que decide qual metade deste\nartigo vale para você. Se a resposta for uma policy,\n",[257,446,448],{"href":447},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","ligar Row Level Security em todas as tabelas","\nmostra como escrever uma regra que deixa a pessoa certa passar, e\n",[257,451,453],{"href":452},"\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 uma escrita que você vê com\nos próprios olhos.",{"title":26,"searchDepth":456,"depth":456,"links":457},3,[458,460,461,462,463,464,465,466,467,468],{"id":46,"depth":459,"text":47},2,{"id":63,"depth":459,"text":64},{"id":139,"depth":459,"text":140},{"id":179,"depth":459,"text":180},{"id":214,"depth":459,"text":215},{"id":263,"depth":459,"text":264},{"id":287,"depth":459,"text":288},{"id":300,"depth":459,"text":301},{"id":347,"depth":459,"text":348},{"id":408,"depth":459,"text":409},"Noções de segurança","\u002Fblog\u002Fsupabase-single-row-error\u002Fcover-1200x630.png","Uma ficha de pedido e uma bandeja de devolução vazia sobre um balcão, e atrás uma estante com uma linha destacada em teal por trás de uma barra âmbar.","O Supabase devolve PGRST116, \"JSON object requested, multiple (or no) rows returned\", quando a consulta não achou nada. Linha escondida parece ausente.",false,"md",[476,479,482,485,488],{"q":477,"a":478},"O que significa PGRST116?","Significa que sua consulta pediu ao banco exatamente uma linha e o resultado tinha outro número. O PostgREST, a parte do Supabase que responde ao seu app por HTTP, devolve isso como HTTP 406 com o código PGRST116. O número está na linha details da resposta, e quase sempre é zero.",{"q":480,"a":481},"Por que minha consulta não devolve linha nenhuma se eu vejo a linha no Supabase?","Porque o SQL Editor do seu painel roda com privilégios aos quais suas policies de Row Level Security não se aplicam, e seu app não. Se nenhuma policy permite que seu visitante leia aquela linha, ela é retirada do resultado dele antes de o resultado ser contado, e o que volta é um zero. A linha está lá. Ela nunca esteve na resposta.",{"q":483,"a":484},"Qual é a diferença entre single e maybeSingle?","single() trata qualquer número de linhas diferente de um como erro. maybeSingle() aceita zero linhas e devolve data como null, sem erro, e continua dando erro quando mais de uma linha bate. Então maybeSingle() serve onde não achar nada é uma resposta legítima, como um perfil que ainda não existe, e single() serve para uma busca por uma coluna que só pode bater com uma linha.",{"q":486,"a":487},"Row Level Security causa esse erro?","É a causa mais comum num app feito com Lovable, Bolt, Replit ou v0. Row Level Security filtra linhas para fora do resultado em vez de recusar o pedido, então uma linha que ninguém pode ler é indistinguível de uma linha que não existe. As duas dão contagem zero, e uma consulta que exige exatamente uma linha falha nas duas.",{"q":489,"a":490},"Por que é um 406?","406 Not Acceptable é o status de um pedido que o servidor não consegue responder na forma pedida. Sua consulta levava um cabeçalho Accept dizendo que a resposta tinha de ser um registro único e não uma lista, e sem linha nenhuma para pôr dentro não há resposta aceitável para mandar. Tire esse cabeçalho e a mesma consulta devolve uma lista vazia com um 200.","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",[493,494,495,496,497,498,499],"json object requested multiple (or no) rows returned","pgrst116","supabase single row error","supabase single() error","406 not acceptable supabase","maybesingle supabase","supabase returns no rows but row exists",{},true,"\"Multiple (or no) rows returned\" quase sempre é nenhuma linha","\u002Fblog\u002Fsupabase-single-row-error","2026-10-15",{"title":5,"description":472},"blog\u002Fsupabase-single-row-error",[508,509,510],"\"JSON object requested, multiple (or no) rows returned\" é o erro PGRST116, e quer dizer que sua consulta voltou com um número de linhas diferente de um. Quase sempre esse número é zero.","Com Row Level Security ligada, uma linha que seu visitante não pode ler volta como nenhuma linha. Então um registro que você vê no Table Editor do Supabase pode faltar no seu app enquanto os dados estão perfeitamente bem.","Use maybeSingle() onde não achar nada for uma resposta legítima e single() onde não for. Rode antes uma consulta no SQL Editor, para saber qual dos dois casos você tem.","GGDzDmCxBwUnvf0zBEPv8bS3MY_cBE84I41R-oIIBuQ",[513,519,525,531,537,543,549,555,561,567,573,580,586,592,598,604,610,616,622,628,634,640,646,652,658,664,665,671,677,683,689,695,701,707,713,719,725,731,737,743,749,755,761,767,773,779,784,790,796,802,808,814,820,826,832,838,844,850,856,862,868,874,879,885,891,897,903,909,915,921,927,933,939,945,951,957,962,968,974,980,986,992,998,1004,1009,1015,1021,1027,1032,1038],{"path":514,"title":515,"description":516,"published":517,"category":469,"image":518,"draft":473},"\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":520,"title":521,"description":522,"published":523,"category":469,"image":524,"draft":473},"\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":526,"title":527,"description":528,"published":529,"category":469,"image":530,"draft":473},"\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":532,"title":533,"description":534,"published":535,"category":469,"image":536,"draft":473},"\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":538,"title":539,"description":540,"published":541,"category":469,"image":542,"draft":473},"\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":544,"title":545,"description":546,"published":547,"category":469,"image":548,"draft":473},"\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":550,"title":551,"description":552,"published":553,"category":469,"image":554,"draft":473},"\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":556,"title":557,"description":558,"published":559,"category":469,"image":560,"draft":473},"\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":562,"title":563,"description":564,"published":565,"category":469,"image":566,"draft":473},"\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":568,"title":569,"description":570,"published":571,"category":469,"image":572,"draft":473},"\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":574,"title":575,"description":576,"published":577,"category":578,"image":579,"draft":473},"\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":581,"title":582,"description":583,"published":584,"category":469,"image":585,"draft":473},"\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":587,"title":588,"description":589,"published":590,"category":469,"image":591,"draft":473},"\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":593,"title":594,"description":595,"published":596,"category":469,"image":597,"draft":473},"\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":599,"title":600,"description":601,"published":602,"category":469,"image":603,"draft":473},"\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":605,"title":606,"description":607,"published":608,"category":469,"image":609,"draft":473},"\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":611,"title":612,"description":613,"published":614,"category":469,"image":615,"draft":473},"\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":617,"title":618,"description":619,"published":620,"category":469,"image":621,"draft":473},"\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":623,"title":624,"description":625,"published":626,"category":469,"image":627,"draft":473},"\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":629,"title":630,"description":631,"published":632,"category":469,"image":633,"draft":473},"\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":635,"title":636,"description":637,"published":638,"category":469,"image":639,"draft":473},"\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":641,"title":642,"description":643,"published":644,"category":469,"image":645,"draft":473},"\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":647,"title":648,"description":649,"published":650,"category":469,"image":651,"draft":473},"\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":653,"title":654,"description":655,"published":656,"category":469,"image":657,"draft":473},"\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":659,"title":660,"description":661,"published":662,"category":469,"image":663,"draft":473},"\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":503,"title":5,"description":472,"published":504,"category":469,"image":491,"draft":473},{"path":666,"title":667,"description":668,"published":669,"category":469,"image":670,"draft":473},"\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":672,"title":673,"description":674,"published":675,"category":469,"image":676,"draft":473},"\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":678,"title":679,"description":680,"published":681,"category":469,"image":682,"draft":473},"\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":684,"title":685,"description":686,"published":687,"category":469,"image":688,"draft":473},"\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":690,"title":691,"description":692,"published":693,"category":469,"image":694,"draft":473},"\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":696,"title":697,"description":698,"published":699,"category":469,"image":700,"draft":473},"\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":702,"title":703,"description":704,"published":705,"category":469,"image":706,"draft":473},"\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":708,"title":709,"description":710,"published":711,"category":469,"image":712,"draft":473},"\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":714,"title":715,"description":716,"published":717,"category":469,"image":718,"draft":473},"\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":720,"title":721,"description":722,"published":723,"category":469,"image":724,"draft":473},"\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":726,"title":727,"description":728,"published":729,"category":469,"image":730,"draft":473},"\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":732,"title":733,"description":734,"published":735,"category":469,"image":736,"draft":473},"\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":738,"title":739,"description":740,"published":741,"category":469,"image":742,"draft":473},"\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":744,"title":745,"description":746,"published":747,"category":469,"image":748,"draft":473},"\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":750,"title":751,"description":752,"published":753,"category":469,"image":754,"draft":473},"\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":756,"title":757,"description":758,"published":759,"category":469,"image":760,"draft":473},"\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":762,"title":763,"description":764,"published":765,"category":578,"image":766,"draft":473},"\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":768,"title":769,"description":770,"published":771,"category":578,"image":772,"draft":473},"\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":774,"title":775,"description":776,"published":777,"category":578,"image":778,"draft":473},"\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":780,"title":781,"description":782,"published":777,"category":469,"image":783,"draft":473},"\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":785,"title":786,"description":787,"published":788,"category":469,"image":789,"draft":473},"\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":791,"title":792,"description":793,"published":794,"category":469,"image":795,"draft":473},"\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":797,"title":798,"description":799,"published":800,"category":578,"image":801,"draft":473},"\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":803,"title":804,"description":805,"published":806,"category":469,"image":807,"draft":473},"\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":809,"title":810,"description":811,"published":812,"category":469,"image":813,"draft":473},"\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":815,"title":816,"description":817,"published":818,"category":469,"image":819,"draft":473},"\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":821,"title":822,"description":823,"published":824,"category":469,"image":825,"draft":473},"\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":827,"title":828,"description":829,"published":830,"category":469,"image":831,"draft":473},"\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":833,"title":834,"description":835,"published":836,"category":469,"image":837,"draft":473},"\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":839,"title":840,"description":841,"published":842,"category":469,"image":843,"draft":473},"\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":845,"title":846,"description":847,"published":848,"category":469,"image":849,"draft":473},"\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":851,"title":852,"description":853,"published":854,"category":578,"image":855,"draft":473},"\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":857,"title":858,"description":859,"published":860,"category":578,"image":861,"draft":473},"\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":863,"title":864,"description":865,"published":866,"category":578,"image":867,"draft":473},"\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":869,"title":870,"description":871,"published":872,"category":469,"image":873,"draft":473},"\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":447,"title":875,"description":876,"published":877,"category":469,"image":878,"draft":473},"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":880,"title":881,"description":882,"published":883,"category":469,"image":884,"draft":473},"\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":886,"title":887,"description":888,"published":889,"category":469,"image":890,"draft":473},"\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":892,"title":893,"description":894,"published":895,"category":469,"image":896,"draft":473},"\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":898,"title":899,"description":900,"published":901,"category":469,"image":902,"draft":473},"\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":904,"title":905,"description":906,"published":907,"category":469,"image":908,"draft":473},"\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":910,"title":911,"description":912,"published":913,"category":469,"image":914,"draft":473},"\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":916,"title":917,"description":918,"published":919,"category":469,"image":920,"draft":473},"\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":922,"title":923,"description":924,"published":925,"category":469,"image":926,"draft":473},"\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":928,"title":929,"description":930,"published":931,"category":578,"image":932,"draft":473},"\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":934,"title":935,"description":936,"published":937,"category":469,"image":938,"draft":473},"\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":940,"title":941,"description":942,"published":943,"category":578,"image":944,"draft":473},"\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":946,"title":947,"description":948,"published":949,"category":469,"image":950,"draft":473},"\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":952,"title":953,"description":954,"published":955,"category":469,"image":956,"draft":473},"\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":452,"title":958,"description":959,"published":960,"category":469,"image":961,"draft":473},"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":963,"title":964,"description":965,"published":966,"category":469,"image":967,"draft":473},"\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":969,"title":970,"description":971,"published":972,"category":578,"image":973,"draft":473},"\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":975,"title":976,"description":977,"published":978,"category":578,"image":979,"draft":473},"\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":981,"title":982,"description":983,"published":984,"category":469,"image":985,"draft":473},"\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":987,"title":988,"description":989,"published":990,"category":469,"image":991,"draft":473},"\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":993,"title":994,"description":995,"published":996,"category":578,"image":997,"draft":473},"\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":999,"title":1000,"description":1001,"published":1002,"category":469,"image":1003,"draft":473},"\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":1005,"title":1006,"description":1007,"published":1002,"category":469,"image":1008,"draft":473},"\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":1010,"title":1011,"description":1012,"published":1013,"category":469,"image":1014,"draft":473},"\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":1016,"title":1017,"description":1018,"published":1019,"category":578,"image":1020,"draft":473},"\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":1022,"title":1023,"description":1024,"published":1025,"category":469,"image":1026,"draft":473},"\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":1028,"title":1029,"description":1030,"published":1025,"category":578,"image":1031,"draft":473},"\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":1033,"title":1034,"description":1035,"published":1036,"category":578,"image":1037,"draft":473},"\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":1039,"title":1040,"description":1041,"published":1036,"category":469,"image":1042,"draft":473},"\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",1794213649241]