[{"data":1,"prerenderedAt":923},["ShallowReactive",2],{"blog-pt-infinite-recursion-in-policy-for-relation":3,"blog-index-pt":569},{"id":4,"title":5,"body":6,"category":526,"cover":527,"coverAlt":528,"description":529,"draft":530,"extension":531,"faq":532,"image":547,"keywords":548,"meta":557,"navigation":558,"ogTitle":559,"path":560,"published":561,"seo":562,"stem":563,"tldr":564,"updated":561,"__hash__":568},"blog_pt\u002Fblog\u002Finfinite-recursion-in-policy-for-relation.md","\"Infinite recursion detected in policy\" sem desligar o RLS",{"type":7,"value":8,"toc":513},"minimark",[9,13,24,32,37,40,43,60,63,67,70,78,94,100,103,107,113,119,122,126,135,141,144,147,200,211,219,223,229,232,237,240,243,295,298,301,308,316,320,323,333,336,354,370,374,377,394,397,401,407,416,434,445,462,466,505],[10,11,12],"p",{},"Você ligou o Row Level Security, escreveu uma regra para que admins vejam todos\nos perfis e cada um veja só o seu, e agora nenhuma tela do seu app carrega. Toda\nleitura volta com a mesma linha:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","infinite recursion detected in policy for relation \"profiles\"\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,31],{},"A maioria das respostas que você vai achar diz a mesma coisa, e é a coisa\nerrada: ",[28,29,30],"strong",{},"desligue o Row Level Security nessa tabela até resolver."," O erro\nrealmente para. O que faz ele parar é que a tabela agora pode ser lida por\nqualquer um que visite o seu site.",[33,34,36],"h2",{"id":35},"o-que-significa-infinite-recursion-detected-in-policy-for-relation","O que significa \"infinite recursion detected in policy for relation\"",[10,38,39],{},"Uma regra numa tabela precisou ler essa mesma tabela antes de conseguir\nresponder.",[10,41,42],{},"Imagine um porteiro que confere cada visitante numa lista de convidados, e a\nlista fica dentro da sala que ele está guardando. Para ler a lista ele tem que\nentrar. Para entrar ele tem que conferir a lista. Não existe primeiro passo,\nentão ele fica no corredor e ninguém vai a lugar nenhum.",[10,44,45,46,49,50,52,53,55,56,59],{},"Foi isso que aconteceu com o seu banco. Pediram algumas linhas de ",[21,47,48],{},"profiles",",\nele foi até a regra de ",[21,51,48],{}," para descobrir quais você podia ver, e a regra\nmandou ele olhar em ",[21,54,48],{},". O Postgres percebe que está andando em círculo,\ndesiste e levanta o erro com o código ",[21,57,58],{},"42P17"," junto. A Supabase repassa isso\nintacto para o seu app, e é por isso que parece linguagem de máquina.",[10,61,62],{},"A consulta falha para todo mundo a quem a regra se aplica, então isso costuma\nchegar como um app inteiro ficando em branco de uma vez, e não como uma tela\nquebrada.",[33,64,66],{"id":65},"o-círculo-desenhado","O círculo, desenhado",[10,68,69],{},"A regra que provoca isso é a que quase todo mundo escreve primeiro, porque ela\ndiz exatamente o que você quer dizer:",[14,71,76],{"className":72,"code":74,"language":75,"meta":23},[73],"language-sql","-- Rejeitar: isto lê profiles para decidir quem pode ler profiles.\ncreate policy \"admins read every profile\" on profiles for select\nto authenticated\nusing (\n  exists (\n    select 1 from profiles\n    where id = (select auth.uid()) and role = 'admin'\n  )\n);\n","sql",[21,77,74],{"__ignoreMap":23},[10,79,80,81,84,85,87,88,90,91,93],{},"O ",[21,82,83],{},"exists (select 1 from profiles …)"," é o problema inteiro. Ler ",[21,86,48],{},"\nsignifica aplicar a regra de ",[21,89,48],{},", que roda ",[21,92,83],{}," de novo.",[95,96],"diagram",{"alt":97,"caption":98,"src":99},"A leitura de um visitante chega numa policy, desenhada como um cadeado. A policy manda uma pergunta para a tabela profiles e a tabela devolve para a policy, e esse par de setas forma um ciclo fechado marcado 42P17.","O pedido está certo. O ciclo está entre a regra e a tabela que a regra protege.","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fthe-circle-1600x660.png",[10,101,102],{},"O próprio guia de Row Level Security da Supabase nomeia a versão com duas\ntabelas: policies em duas tabelas que leem uma a outra nunca se resolvem, e a\nconsulta falha para cada papel a que as policies se aplicam. Uma tabela lendo a\nsi mesma é a mesma forma sem o desvio.",[33,104,106],{"id":105},"por-que-isso-sempre-acontece-na-tabela-profiles","Por que isso sempre acontece na tabela profiles?",[10,108,109,110,112],{},"Porque é em ",[21,111,48],{}," que fica quem é essa pessoa.",[10,114,115,116,118],{},"Qualquer regra que trate um tipo de pessoa diferente de outro precisa descobrir\nde que tipo é quem está chamando, e esse dado mora numa coluna de alguma tabela.\nSeja qual for o nome dessa tabela, a regra que protege ela acaba lendo ela. Num\napp feito com Lovable, Bolt, v0 ou Replit costuma ser ",[21,117,48],{},", porque é ali\nque vai parar a linha de cada pessoa logada. Uma regra sobre times, organizações\nou documentos compartilhados produz o mesmo círculo na tabela que guarda a\nparticipação.",[10,120,121],{},"Então a recursão sai de escrever a regra óbvia sobre a única tabela que precisa\nresponder uma pergunta sobre si mesma.",[33,123,125],{"id":124},"o-conserto-um-auxiliar-que-lê-a-tabela-fora-das-regras","O conserto: um auxiliar que lê a tabela fora das regras",[10,127,128,129,131,132,134],{},"Mude a pergunta para uma função pequena que roda como dona do banco, para que\nler ",[21,130,48],{}," e responder não passe pela regra de ",[21,133,48],{},".",[14,136,139],{"className":137,"code":138,"language":75,"meta":23},[73],"create schema if not exists private;\n\ncreate function private.is_admin()\nreturns boolean\nlanguage sql\nsecurity definer      -- roda como o papel que a criou\nset search_path = ''  -- assim todo nome lá dentro precisa vir por extenso\nstable\nas $$\n  select exists (\n    select 1 from public.profiles\n    where id = (select auth.uid()) and role = 'admin'\n  );\n$$;\n\nrevoke execute on function private.is_admin() from public;\ngrant usage on schema private to authenticated;\ngrant execute on function private.is_admin() to authenticated;\n\n-- A regra agora pergunta para a função em vez da tabela.\ncreate policy \"admins read every profile\" on profiles for select\nto authenticated\nusing ( (select private.is_admin()) );\n",[21,140,138],{"__ignoreMap":23},[10,142,143],{},"Agora o porteiro tem a lista de convidados numa mesa do corredor. Ele lê sem\nabrir a porta, e a porta continua fechada para todos que não estão nela.",[10,145,146],{},"Quatro linhas ali fazem um trabalho específico, e três delas são a diferença\nentre um conserto e um buraco novo:",[148,149,150,163,179,188],"ul",{},[151,152,153,158,159,162],"li",{},[28,154,155],{},[21,156,157],{},"security definer"," é o que quebra o círculo. O guia da Supabase define\nisso como uma função que roda sob o mesmo papel que criou a função, e na\nSupabase esse papel é o ",[21,160,161],{},"postgres",", que pode ler por cima das regras.",[151,164,165,170,171,174,175,178],{},[28,166,167],{},[21,168,169],{},"set search_path = ''"," cabe em cada uma delas. A orientação da Supabase é\ncolocar isso em toda função security definer e escrever os nomes de tabela por\nextenso, porque sem um ",[21,172,173],{},"search_path"," fixado quem chama pode apontar um nome\nnão qualificado para um objeto próprio e rodá-lo com os privilégios do dono da\nfunção. É por isso que a função escreve ",[21,176,177],{},"public.profiles"," por extenso.",[151,180,181,187],{},[28,182,183,184],{},"O schema ",[21,185,186],{},"private"," importa pelo mesmo motivo. O guia da Supabase avisa que\numa função security definer num schema exposto pode ser chamada pela Data API\ncom os privilégios de quem a criou, e diz para nunca criar uma num schema\nlistado em Exposed schemas nas configurações da sua API.",[151,189,190,195,196,199],{},[28,191,192],{},[21,193,194],{},"(select private.is_admin())",", embrulhado num select próprio. Isso deixa o\nPostgres calcular a resposta uma vez para o comando inteiro em vez de uma vez\npor linha, que é o que a Supabase documenta como motivo para embrulhar\n",[21,197,198],{},"auth.uid()"," do mesmo jeito.",[10,201,202,203,206,207,210],{},"As linhas ",[21,204,205],{},"revoke"," e ",[21,208,209],{},"grant"," mantêm a função chamável pelos usuários logados e\npor mais ninguém.",[10,212,213,214,134],{},"Essa policy cobre a leitura. Se salvar começar a falhar assim que as suas telas\nvoltarem a encher, você encontrou\n",[215,216,218],"a",{"href":217},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","outra mensagem com outra causa",[33,220,222],{"id":221},"o-conserto-que-não-conserta","O conserto que não conserta",[10,224,225,226,228],{},"Desligar o Row Level Security em ",[21,227,48],{}," também faz o erro parar, num clique,\ne entrega cada linha dessa tabela a quem tiver a chave que o seu app envia ao\nnavegador.",[10,230,231],{},"Essa chave é feita para ser pública. Ela está no código do seu site, e qualquer\npessoa consegue tirá-la de lá em alguns segundos. O que estava impedindo ela de\ndevolver a sua tabela de usuários inteira eram as regras que você acabou de\ndesligar.",[95,233],{"alt":234,"caption":235,"src":236},"Dois caminhos para a mesma tabela. No primeiro o cadeado continua de pé e uma função auxiliar ao lado devolve duas linhas de seis. No segundo o lugar do cadeado é só um contorno tracejado vazio e as seis linhas voltam em vermelho.","As duas fazem o erro parar. Só uma delas ainda responde a pergunta que foi feita à regra.","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Ftwo-ways-out-1600x700.png",[10,238,239],{},"O seu app fica com a mesma cara depois nos dois casos, e é essa parte que faz\nisso ficar. Nada nas suas telas diz qual das duas você escolheu, e o erro sumiu\nnas duas.",[10,241,242],{},"O que diz é o seu banco, perguntado de fora. Escaneamos 31.056 apps no ar feitos\ncom Lovable, Bolt, v0, Replit e os outros, e vimos um projeto Supabase atrás de\n8.435 deles. Foi isto que a verificação de Row Level Security encontrou:",[244,245,246,259],"table",{},[247,248,249],"thead",{},[250,251,252,256],"tr",{},[253,254,255],"th",{},"O que perguntamos",[253,257,258],{},"Apps",[260,261,262,271,279,287],"tbody",{},[250,263,264,268],{},[265,266,267],"td",{},"Tinham um projeto Supabase visível",[265,269,270],{},"8.435",[250,272,273,276],{},[265,274,275],{},"Deu para perguntar",[265,277,278],{},"3.680",[250,280,281,284],{},[265,282,283],{},"Devolveram linhas para um pedido sem login",[265,285,286],{},"2.096",[250,288,289,292],{},[265,290,291],{},"Dessas, de uma tabela de pessoas, pedidos ou mensagens",[265,293,294],{},"394",[10,296,297],{},"A linha do meio é a honesta. Em 4.755 desses apps a verificação não obteve\nresposta, e dizemos isso em vez de dá-los como limpos. E algumas das 2.096 são\npara serem lidas mesmo, porque uma tabela pública é uma coisa que se quer de\nverdade; de fora, um cardápio e uma lista de sócios são iguais.",[10,299,300],{},"Não dá para dizer quantas dessas tabelas foram abertas por alguém tirando da\nfrente exatamente este erro. Dá para dizer que uma tabela aberta é o fim comum\ndo conselho que aparece no topo dos resultados de busca.",[10,302,303,304,134],{},"Se você prefere não ter que pensar nisso, o nosso scan gratuito lê o seu site no\nar e diz quais das suas tabelas respondem a um estranho. Leva cerca de 20\nsegundos e não pede conta: ",[215,305,307],{"href":306},"\u002Fsecurity-scanner","escaneie o seu app",[10,309,310,311,315],{},"Mais uma coisa acontece quando você desliga. O próprio advisor da Supabase\ncomeça a reportar a tabela, que é o aviso\n",[215,312,314],{"href":313},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","RLS disabled in public",", e esse aviso vai\ncontinuar lá daqui a um mês.",[33,317,319],{"id":318},"como-saber-se-o-círculo-foi-mesmo-embora","Como saber se o círculo foi mesmo embora",[10,321,322],{},"O erro parar não é o teste, porque duas coisas diferentes fazem ele parar.",[10,324,325,326,328,329,332],{},"Existe ainda um jeito de a função auxiliar parecer certa e continuar recursiva,\ne a Supabase documenta: uma função security definer só pula as regras se o dono\ndela puder. Na Supabase o dono é o ",[21,327,161],{},", que tem esse privilégio, então o\npadrão acima funciona. Uma função que pertença a um papel sem ele, ou que leia\numa tabela com ",[21,330,331],{},"force row level security",", volta a passar pela regra e continua\nno círculo.",[10,334,335],{},"Duas conferidas, e faça as duas:",[10,337,338,341,342,345,346,349,350,353],{},[28,339,340],{},"Escreva os casos e rode."," O procedimento da Supabase é um arquivo ",[21,343,344],{},".sql"," em\n",[21,347,348],{},"supabase\u002Ftests\u002F"," afirmando permissão e recusa para cada operação, para um\nusuário logado e para um anônimo, rodado com ",[21,351,352],{},"supabase test db",". Um admin tem\nque ver todos os perfis, um membro o dele, um estranho nada. Até isso passar, o\nque você sabe é que o erro parou.",[10,355,356,359,360,364,365,369],{},[28,357,358],{},"Depois pergunte de fora, sem login."," Essa é a pergunta que o navegador de um\nvisitante faz, e a única que reflete o que o seu app realmente entrega.\n",[215,361,363],{"href":362},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Se um estranho consegue ler o seu banco","\nmostra o caminho, e\n",[215,366,368],{"href":367},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Row Level Security pode estar ligado e a tabela continuar pública","\ncobre o caso em que as regras existem e deixam todo mundo passar assim mesmo.",[33,371,373],{"id":372},"quando-a-recursão-está-dizendo-que-o-schema-está-errado","Quando a recursão está dizendo que o schema está errado",[10,375,376],{},"Às vezes não há pergunta circular para tirar, porque as duas tabelas dependem\nmesmo uma da outra.",[10,378,379,380,383,384,387,388,390,391,393],{},"O guia da Supabase usa compartilhamento como exemplo: uma regra em ",[21,381,382],{},"lists","\nconfere ",[21,385,386],{},"list_members"," para ver com quem a lista foi compartilhada, e uma regra\nem ",[21,389,386],{}," confere ",[21,392,382],{}," para ver de quem ela é. A regra de cada tabela\nlê a outra, e nenhuma pode ir primeiro. O mesmo auxiliar desfaz isso, com uma\nfunção que devolve os ids das listas a que quem chama pertence, e as duas regras\nperguntando para essa função em vez de perguntarem uma à outra.",[10,395,396],{},"O sinal que vale notar é quando você precisa de três ou quatro dessas para um\nschema funcionar. A essa altura a participação está sendo reconstruída dentro\ndas regras toda vez, e uma única tabela que diga claramente quem pode ver o quê\ncostuma dar menos manutenção do que as regras que você está desembaraçando.",[33,398,400],{"id":399},"como-manter-a-tabela-fechada-depois-de-consertar","Como manter a tabela fechada depois de consertar",[10,402,403,406],{},[28,404,405],{},"Uma regra que você consertou hoje descreve o banco de hoje."," A próxima\npolicy, a próxima tabela e a próxima vez que alguém tira um erro da frente à\nmeia-noite acontecem todas depois da última vez que você olhou, e nenhuma delas\nmuda nada que você consiga ver nas suas telas.",[10,408,409],{},[28,410,80,411,415],{},[215,412,414],{"href":413},"\u002Fpricing","Reeve Monitor"," faz ao seu app as mesmas perguntas de novo, com\nhorário:",[148,417,418,421,428,431],{},[151,419,420],{},"as nove verificações a cada hora, em até três apps",[151,422,423,424,427],{},"uma mensagem quando um resultado ",[28,425,426],{},"muda",", para que uma tabela que abriu de madrugada não espere você notar",[151,429,430],{},"se o app responde, a cada 60 segundos",[151,432,433],{},"um relatório mensal do que ele viu",[10,435,436,444],{},[28,437,438,439,443],{},"Se o seu app guarda os dados no seu próprio projeto Supabase, o\n",[215,440,442],{"href":441},"\u002Fsupabase-backups","Reeve Care"," ainda guarda uma cópia desse banco."," Uma regra\nque deixa um estranho ler é um problema. Uma regra que deixa um estranho\nescrever é o outro, e nenhuma verificação deste artigo traz linhas apagadas de\nvolta.",[148,446,447,450,453,456,459],{},[151,448,449],{},"uma cópia criptografada do seu banco Supabase toda noite, guardada onde o seu projeto não alcança",[151,451,452],{},"cada cópia verificada antes de contar, contando as linhas de cada tabela",[151,454,455],{},"uma restauração em um clique quando você precisar",[151,457,458],{},"os seus arquivos enviados também, assim que você conectar uma credencial de Storage",[151,460,461],{},"tudo o que o Monitor faz",[33,463,465],{"id":464},"o-que-fazer-agora","O que fazer agora",[467,468,469],"key-takeaways",{},[148,470,471,474,483,489,498],{},[151,472,473],{},"Deixe o Row Level Security ligado. O erro é sobre uma regra, e desligar as regras é uma mudança na tabela inteira.",[151,475,476,477,479,480,482],{},"Mude a conferência de papel para uma função ",[21,478,157],{}," num schema que não esteja exposto, com ",[21,481,169],{}," e cada nome de tabela escrito por extenso.",[151,484,485,486,488],{},"Aponte a policy para a função, embrulhada como ",[21,487,194],{},", para rodar uma vez por comando e não uma vez por linha.",[151,490,491,492,494,495,497],{},"Escreva os casos permitidos e negados em ",[21,493,348],{}," e rode ",[21,496,352],{},": um admin vê todos os perfis, um membro o dele, um estranho nada.",[151,499,500,501,134],{},"Se você já desligou o Row Level Security para destravar, religue hoje e conserte a regra direito. O advisor da Supabase vai continuar reportando essa tabela até lá, e ",[215,502,504],{"href":503},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","ele cabe em todas as tabelas que você tem",[10,506,507,508,512],{},"Se você quer o resto da lista para um app recém-lançado, a\n",[215,509,511],{"href":510},"\u002Fchecklist","checklist de segurança de 10 minutos"," cobre isto e as outras coisas\nque vale fechar antes de alguém encontrar.",{"title":23,"searchDepth":514,"depth":514,"links":515},3,[516,518,519,520,521,522,523,524,525],{"id":35,"depth":517,"text":36},2,{"id":65,"depth":517,"text":66},{"id":105,"depth":517,"text":106},{"id":124,"depth":517,"text":125},{"id":221,"depth":517,"text":222},{"id":318,"depth":517,"text":319},{"id":372,"depth":517,"text":373},{"id":399,"depth":517,"text":400},{"id":464,"depth":517,"text":465},"Noções de segurança","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcover-1200x630.png","Um painel de tabela trancado com a própria chave desenhada do lado de dentro, atrás do vidro, e uma barra atravessada na porta.","\"Infinite recursion detected in policy for relation\" significa que a sua policy perguntou à tabela que ela protege. Veja como quebrar o círculo.",false,"md",[533,536,539,542,544],{"q":534,"a":535},"O que causa \"infinite recursion detected in policy for relation\"?","Uma regra numa tabela que precisa ler essa mesma tabela antes de conseguir responder. A sua regra diz mais ou menos \"deixe esta pessoa passar se a linha dela em profiles disser que é admin\", então o banco vai ler essa linha em profiles, o que obriga a conferir a regra de profiles, que o manda ler a linha de novo. O Postgres percebe que está andando em círculo, para e levanta o erro 42P17. A mesma coisa acontece entre duas tabelas cujas regras leem uma a outra.",{"q":537,"a":538},"É seguro usar uma função security definer numa policy?","É, com duas condições que o próprio guia de Row Level Security da Supabase enuncia. Coloque search_path como string vazia e escreva cada nome de tabela por extenso lá dentro, ou seja public.profiles e não profiles. Sem isso, alguém pode apontar um nome não qualificado para um objeto próprio e fazê-lo rodar com os privilégios do dono da função. E crie a função num schema que não esteja exposto na API, porque uma função security definer num schema exposto pode ser chamada de fora com os privilégios de quem a criou.",{"q":540,"a":541},"Devo desligar o RLS para resolver?","Isso faz o erro parar e abre a tabela. Com Row Level Security desligado, cada linha dessa tabela pode ser lida por qualquer um que tenha a chave que o seu app envia ao navegador, e essa chave qualquer pessoa consegue tirar do seu site. O seu app se comporta igual nos dois casos, então depois nada diz qual das duas você escolheu. A função auxiliar logo abaixo faz o erro parar e mantém a tabela fechada.",{"q":106,"a":543},"Porque é em profiles que costuma ficar a resposta para \"quem é esta pessoa\". Uma regra que trata admins de um jeito, ou membros de um time de outro, precisa saber o que é quem está chamando, e esse dado está guardado em profiles. Então a regra que protege profiles acaba lendo profiles. Qualquer tabela que guarde o papel ou a participação de quem chama pode produzir isso, e num app feito com Lovable, Bolt ou v0 essa tabela costuma ser a chamada profiles.",{"q":545,"a":546},"Como eu confiro se a minha policy funciona mesmo?","Duas coisas diferentes fazem o erro parar, então o erro sumir sozinho diz muito pouco. Escreva os casos permitidos e negados num arquivo .sql em supabase\u002Ftests\u002F e rode supabase test db, que é o procedimento que a Supabase publica junto com o guia: um dono logado precisa passar e um estranho precisa ser recusado. Depois faça a mesma pergunta ao seu banco de fora, sem login nenhum, do jeito que o navegador de um visitante faria.","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",[549,550,551,552,553,554,555,556],"infinite recursion detected in policy for relation","supabase infinite recursion policy","infinite recursion rls supabase","erro recursao policy supabase","42P17 supabase","loop infinito policy rls","supabase profiles policy recursao","erro policy papel supabase",{},true,"Infinite recursion detected in policy","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","2026-10-08",{"title":5,"description":529},"blog\u002Finfinite-recursion-in-policy-for-relation",[565,566,567],"\"Infinite recursion detected in policy for relation\" é o erro 42P17 do Postgres. Uma regra de Row Level Security numa tabela foi fazer uma pergunta a essa mesma tabela, e a pergunta não tem fim.","Não é sinal de que Row Level Security era errado para o seu app. É sinal de que uma regra perguntou em círculo.","Uma função auxiliar pequena lê a tabela fora das regras e quebra o círculo. Desligar Row Level Security nessa tabela também faz o erro parar, entregando cada linha dela a quem tiver a chave que viaja dentro do seu app.","VwoN6n_hyRR3IQ9kkHhT1MP-ZZmhFCxlqoKmhI9wAbo",[570,576,582,588,589,595,601,607,613,619,625,631,637,643,650,656,662,667,673,679,685,691,697,703,709,715,721,727,733,739,745,751,757,762,767,773,779,785,791,797,803,809,815,821,827,833,839,844,850,856,862,868,874,880,885,890,896,902,907,912,918],{"path":571,"title":572,"description":573,"published":574,"category":526,"image":575,"draft":530},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" ao enviar","\"New row violates row-level security policy for table objects\" quer dizer que o seu envio não tem regra insert. Deixar o bucket público não cria nenhuma.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":577,"title":578,"description":579,"published":580,"category":526,"image":581,"draft":530},"\u002Fblog\u002Fbase44-security-scan","Scan de segurança do Base44: o que só ele enxerga","O scan de segurança do Base44 verifica sete tipos de problema por dentro. Esta é a metade que ele lê e mais ninguém, e a metade que ele nunca olha.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":583,"title":584,"description":585,"published":586,"category":526,"image":587,"draft":530},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Sua chave de API vazou. A ordem em que agir","Uma chave de API vazou e você não sabe o que fazer primeiro. Nem toda chave no seu frontend é um vazamento, e a ordem importa mais que a pressa.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":560,"title":5,"description":529,"published":561,"category":526,"image":547,"draft":530},{"path":590,"title":591,"description":592,"published":593,"category":526,"image":594,"draft":530},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" no Supabase, e a correção errada","\"No API key found in request\" significa que sua requisição chegou ao Supabase sem chave. Quase toda resposta aponta para as regras do seu banco.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":596,"title":597,"description":598,"published":599,"category":526,"image":600,"draft":530},"\u002Fblog\u002Fis-base44-safe","O Base44 é seguro? O que vimos em 5.442 apps Base44","O Base44 é seguro? Rodamos nove verificações em 5.442 apps Base44 no ar. Quase todas tiraram B por motivos que o dono nunca escolheu.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":602,"title":603,"description":604,"published":605,"category":526,"image":606,"draft":530},"\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":608,"title":609,"description":610,"published":611,"category":526,"image":612,"draft":530},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Seu arquivo .env está exposto? Os doze caminhos para testar","Seu arquivo .env está exposto no seu próprio servidor web? Doze endereços dizem isso em um minuto, e um acerto significa que tudo nele já é público.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":614,"title":615,"description":616,"published":617,"category":526,"image":618,"draft":530},"\u002Fblog\u002Fis-v0-safe","Segurança do v0: os 1.790 aplicativos v0 escaneados tiraram A","A segurança do v0 medida em 1.790 aplicativos v0 no ar: todos tiraram A. Só 17 citavam um banco de dados, e é sobretudo isso que esse A mede.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":620,"title":621,"description":622,"published":623,"category":526,"image":624,"draft":530},"\u002Fblog\u002Fis-bolt-safe","O Bolt é seguro? O que vimos em 1.123 aplicativos Bolt","O Bolt é seguro? Passamos 1.123 aplicativos Bolt no ar por nove verificações. A hospedagem saiu limpa. Os achados: chaves e tabelas abertas nos aplicativos.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":626,"title":627,"description":628,"published":629,"category":526,"image":630,"draft":530},"\u002Fblog\u002Fis-supabase-down-or-your-app","O Supabase caiu ou o problema é o seu app? Como saber","O Supabase caiu ou o problema é o seu app? Um projeto pausado, um banco cheio e um erro seu parecem iguais. Quatro verificações separam os casos.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":632,"title":633,"description":634,"published":635,"category":526,"image":636,"draft":530},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","O Supabase criptografa meus dados? Sim. Veja o que isso impede","O Supabase criptografa os dados? Sim: AES-256 em repouso, TLS em trânsito, SOC 2 e ISO 27001. O que cada um cobre, e o vazamento que nenhum deles impede.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":638,"title":639,"description":640,"published":641,"category":526,"image":642,"draft":530},"\u002Fblog\u002Fsupabase-free-plan-limits","Quanto custa o Supabase? Os limites do plano gratuito","Quanto custa o Supabase: o plano gratuito tem 500 MB de banco, 5 GB de egress e nenhum backup. O que acontece em cada limite e o que o Pro de $25 muda.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":644,"title":645,"description":646,"published":647,"category":648,"image":649,"draft":530},"\u002Fblog\u002Ftest-your-supabase-backup","Teste o backup do seu Supabase antes do dia em que precisar","Como testar o backup do seu Supabase: restaurar num projeto de teste, contar as linhas, entrar e procurar a linha que falta num arquivo cortado.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":651,"title":652,"description":653,"published":654,"category":648,"image":655,"draft":530},"\u002Fblog\u002Fsupabase-backup-github-action","Backup grátis do Supabase com uma GitHub Action, e a pegadinha","Um backup do Supabase com GitHub Action é grátis e serve para muitos apps. O workflow, a connection string certa e o egress de cada execução.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":657,"title":658,"description":659,"published":660,"category":648,"image":661,"draft":530},"\u002Fblog\u002Fdownload-your-supabase-backup","Por que você não consegue baixar seu backup do Supabase","Você não consegue baixar seu backup do Supabase num projeto atual, porque a cópia diária é um snapshot físico. Como conferir e como ter uma cópia só sua.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":663,"title":664,"description":665,"published":660,"category":526,"image":666,"draft":530},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": o grant que falta","A partir de 30 de outubro, uma tabela nova no Supabase responde \"permission denied for table\" até receber um grant. O e-mail mostra só metade.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":668,"title":669,"description":670,"published":671,"category":526,"image":672,"draft":530},"\u002Fblog\u002Fopen-api-endpoint-exposed","Um endpoint de API aberto é um problema? Leia o JSON","Seu scan apontou um endpoint de API aberto. Se isso importa depende do que voltou, e a maioria dos que encontramos era da própria plataforma.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":674,"title":675,"description":676,"published":677,"category":526,"image":678,"draft":530},"\u002Fblog\u002Flovable-security-scan","Escaneamento de segurança do Lovable: o que ele não prova","Escaneamento de segurança do Lovable: o que o Quick scan e o Deep scan checam, quando cada um roda, e a única coisa que nenhum escaneamento por dentro prova.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":680,"title":681,"description":682,"published":683,"category":648,"image":684,"draft":530},"\u002Fblog\u002Fsupabase-backup-auth-users","Por que seu dump do Supabase não tem usuários dentro","Rode supabase db dump sozinho e você recebe a forma do seu banco e nenhuma das linhas dele, sem o schema auth onde seus usuários moram.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":686,"title":687,"description":688,"published":689,"category":526,"image":690,"draft":530},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domínio expirado, site fora do ar: o que acontece agora","Seu domínio expirou e seu site está fora do ar. O relógio que começa a correr, por que o certificado é o problema menor, e como conferir os dois.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":692,"title":693,"description":694,"published":695,"category":526,"image":696,"draft":530},"\u002Fblog\u002Fis-lovable-safe","O Lovable é seguro? O que vimos em 18.554 aplicativos Lovable","O Lovable é seguro? Passamos 18.554 aplicativos Lovable no ar por nove verificações. A plataforma foi a mais limpa de cinco. Os achados estavam nos aplicativos.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":698,"title":699,"description":700,"published":701,"category":526,"image":702,"draft":530},"\u002Fblog\u002Fvibe-coded-app-security-checklist","O checklist de segurança do vibe coding, em nove verificações","Um checklist de segurança do vibe coding com nove itens, cada um verificável no seu app de fora por qualquer pessoa, e cada um com um teste de uma linha.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":704,"title":705,"description":706,"published":707,"category":526,"image":708,"draft":530},"\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":710,"title":711,"description":712,"published":713,"category":526,"image":714,"draft":530},"\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":716,"title":717,"description":718,"published":719,"category":526,"image":720,"draft":530},"\u002Fblog\u002Fbase44-source-maps","Segurança no Base44: o que um scan aponta e o que é seu para corrigir","Segurança no Base44 em 5.438 apps escaneados: três achados em quase todos são da plataforma, o source map é o selo do Base44, e a sua parte é uma lista curta.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":722,"title":723,"description":724,"published":725,"category":526,"image":726,"draft":530},"\u002Fblog\u002Fis-cursor-ai-safe","O Cursor AI é seguro? O editor, o código e o app que você publicou","O Cursor AI é seguro? Três perguntas em uma busca: o que o Cursor guarda, o que o código que ele escreve erra, e se o app que você publicou está aberto.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":728,"title":729,"description":730,"published":731,"category":526,"image":732,"draft":530},"\u002Fblog\u002Fis-replit-safe","O Replit é seguro? O que vimos em 3.042 aplicativos Replit no ar","O Replit é seguro? Passamos 3.042 aplicativos Replit no ar por nove verificações externas. Os achados estavam no aplicativo publicado, não no host.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":734,"title":735,"description":736,"published":737,"category":648,"image":738,"draft":530},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: sua cópia do banco não tem nenhum arquivo","Um Supabase storage backup é uma tarefa à parte. Os backups do banco guardam a lista dos seus arquivos e nenhum deles, então cada upload fica quebrado.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":740,"title":741,"description":742,"published":743,"category":648,"image":744,"draft":530},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery do Supabase: preço e limites","O point-in-time recovery do Supabase rebobina seu banco para qualquer segundo da última semana. Custa $100 por mês além do Pro e cobre só o banco.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":746,"title":747,"description":748,"published":749,"category":648,"image":750,"draft":530},"\u002Fblog\u002Fsupabase-project-paused-recover","Projeto Supabase pausado? Seus dados continuam lá","O Supabase pausou seu projeto depois de uma semana sem atividade. Nada foi apagado, Restaurar fica ao lado do nome e você tem um ano antes disso mudar.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":752,"title":753,"description":754,"published":755,"category":526,"image":756,"draft":530},"\u002Fblog\u002Fsafest-ai-app-builder","Qual builder de apps com IA é mais seguro? 30.998 apps testados","Qual builder de apps com IA é mais seguro? Escaneamos 30.998 apps no ar do Lovable, Base44, Replit, v0 e Bolt. O builder não é o que decide sua nota.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":503,"title":758,"description":759,"published":760,"category":526,"image":761,"draft":530},"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":313,"title":763,"description":764,"published":765,"category":526,"image":766,"draft":530},"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":768,"title":769,"description":770,"published":771,"category":526,"image":772,"draft":530},"\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":774,"title":775,"description":776,"published":777,"category":526,"image":778,"draft":530},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Scanners de segurança para vibe coding comparados, o nosso incluído","O melhor scanner de segurança para vibe coding depende de três perguntas que nenhuma lista de recursos responde. Dez ferramentas comparadas, com preços.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":780,"title":781,"description":782,"published":783,"category":526,"image":784,"draft":530},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: faça você mesmo as cinco verificações","Um Supabase security checker lê o seu app publicado em vez das configurações do projeto. Aqui estão as cinco verificações e como fazer cada uma sozinho.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":786,"title":787,"description":788,"published":789,"category":526,"image":790,"draft":530},"\u002Fblog\u002Fvibe-coding-security-scanner","Scanner de segurança para vibe coding: o que ele não vê","Um scanner de segurança para vibe coding lê seu app no ar, de fora. O que isso cobre, as quatro coisas que ele não consegue ver e como ler o resultado.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":792,"title":793,"description":794,"published":795,"category":526,"image":796,"draft":530},"\u002Fblog\u002Fmissing-security-headers","Cabeçalhos de segurança faltando: quando isso importa","Cabeçalhos de segurança faltando é o achado que nosso scanner mais imprime. Contra o que eles protegem e quando são a linha menos urgente do relatório.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":798,"title":799,"description":800,"published":801,"category":526,"image":802,"draft":530},"\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":804,"title":805,"description":806,"published":807,"category":526,"image":808,"draft":530},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Chave de API exposta no frontend: o que 30.998 apps entregam","Uma chave de API exposta no seu frontend costuma ser uma chave do Google Maps. Escaneamos 30.998 apps vibe-coded e contamos quais segredos vazam de verdade.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":810,"title":811,"description":812,"published":813,"category":648,"image":814,"draft":530},"\u002Fblog\u002Fsupabase-backup-tools-compared","Ferramentas de backup do Supabase comparadas, a nossa incluída","Quatro tipos de ferramenta de backup do Supabase, o que cada uma copia de verdade e quando uma GitHub Action gratuita ganha de pagar, nós inclusive.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":816,"title":817,"description":818,"published":819,"category":526,"image":820,"draft":530},"\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":822,"title":823,"description":824,"published":825,"category":648,"image":826,"draft":530},"\u002Fblog\u002Fback-up-supabase-free-tier","Backups do plano gratuito do Supabase: como fazer sem terminal","No plano gratuito do Supabase não existe backup nenhum: a cópia é você que faz. Como fazer uma pelo painel e o que a rota do CSV deixa para trás.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":828,"title":829,"description":830,"published":831,"category":526,"image":832,"draft":530},"\u002Fblog\u002Fis-supabase-secure","O Supabase é seguro? É. Seu projeto é outra pergunta","O Supabase é seguro? A plataforma é auditada, criptografada e passa por pentests. A documentação deles diz onde isso termina e começam suas configurações.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":834,"title":835,"description":836,"published":837,"category":526,"image":838,"draft":530},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Onde ficam as chaves de API do Supabase: anon, service_role e URL","A URL do projeto, a chave anon e a chave service_role ficam todas numa página do painel. Aqui está onde ela fica, e qual dos quatro valores vai no seu app.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":217,"title":840,"description":841,"published":842,"category":526,"image":843,"draft":530},"New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":845,"title":846,"description":847,"published":848,"category":526,"image":849,"draft":530},"\u002Fblog\u002Fcors-wildcard-security-risk","Um curinga CORS é um risco de segurança? Quase nunca.","Um curinga CORS é um risco de segurança? Em geral é o padrão do seu builder e não entrega nada que o seu servidor já não desse a qualquer um que pedisse.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":851,"title":852,"description":853,"published":854,"category":648,"image":855,"draft":530},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching do Supabase não é backup. Ele só anda para a frente.","Por que o branching do Supabase não é backup: um branch começa sem os seus dados e um merge só leva o esquema. Para que ele serve e o que usar no lugar.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":857,"title":858,"description":859,"published":860,"category":648,"image":861,"draft":530},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Como restaurar um backup do Supabase, e o que quebra depois","Como restaurar um backup do Supabase pelo painel ou por um arquivo de dump, o que a restauração substitui e por que o seu app pode continuar quebrado no fim.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":863,"title":864,"description":865,"published":866,"category":526,"image":867,"draft":530},"\u002Fblog\u002Fsupabase-storage-bucket-public","Seu bucket do Supabase Storage é público. Isso é um problema?","Um bucket público do Supabase Storage significa que quem tem a URL de um arquivo pode abri-lo. Não significa que alguém possa listar o que está lá dentro.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":869,"title":870,"description":871,"published":872,"category":526,"image":873,"draft":530},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Uma chave de API do Google no frontend é um problema?","Uma chave de API do Google exposta no seu frontend é a chave que nosso scanner mais encontra, e quase sempre está tudo bem. Um ajuste gratuito decide isso.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":875,"title":876,"description":877,"published":878,"category":648,"image":879,"draft":530},"\u002Fblog\u002Fai-agent-deleted-my-database","Um agente de IA apagou meus dados do Supabase. O que eu recupero?","Um agente de IA apagou dados do seu banco. O que você recupera já estava decidido antes de ele rodar, e os próximos minutos decidem o resto.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":362,"title":881,"description":882,"published":883,"category":526,"image":884,"draft":530},"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":886,"title":887,"description":888,"published":883,"category":526,"image":889,"draft":530},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source maps expostos: seu app está publicando o código original","Um source map exposto deixa qualquer um ler o código original do seu app, comentários incluídos. A verificação de 30 segundos e o que importa de verdade.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":891,"title":892,"description":893,"published":894,"category":526,"image":895,"draft":530},"\u002Fblog\u002Fsupabase-new-api-keys","As novas chaves de API do Supabase: qual vai no seu app?","O Supabase trocou anon e service_role por chaves publicáveis e secretas. Qual delas pertence ao seu app e qual nunca deve estar lá?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":897,"title":898,"description":899,"published":900,"category":648,"image":901,"draft":530},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","O Supabase faz backup do meu banco de dados? Depende do plano.","O Supabase faz backup do seu banco de dados? Todo dia nos planos pagos, e nada no gratuito. Como descobrir o que você tem e o que essa cópia não cobre.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":367,"title":903,"description":904,"published":905,"category":526,"image":906,"draft":530},"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":908,"title":909,"description":910,"published":905,"category":648,"image":911,"draft":530},"\u002Fblog\u002Fversion-history-is-not-a-backup","O histórico de versões não é backup. Ele não desfaz um delete.","Lovable e Bolt guardam um histórico de versões do seu código. Seu banco de dados é um serviço à parte, e voltar atrás não traz os seus dados de volta.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":913,"title":914,"description":915,"published":916,"category":648,"image":917,"draft":530},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Três formas de fazer backup de um banco Supabase, e o que falta","O painel, o pg_dump e um serviço gerenciado. O que cada um salva de verdade, o que deixa de fora sem avisar e qual sobrevive a perder a conta.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":919,"title":920,"description":921,"published":916,"category":526,"image":922,"draft":530},"\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",1791705963228]