[{"data":1,"prerenderedAt":1333},["ShallowReactive",2],{"blog-pt-supabase-function-not-found":3,"blog-index-pt":806},{"id":4,"title":5,"body":6,"category":763,"cover":764,"coverAlt":765,"description":766,"draft":767,"extension":768,"faq":769,"image":785,"keywords":786,"meta":795,"navigation":796,"ogTitle":5,"path":797,"published":798,"seo":799,"stem":800,"tldr":801,"updated":798,"__hash__":805},"blog_pt\u002Fblog\u002Fsupabase-function-not-found.md","Supabase PGRST202: \"Could not find the function in the schema cache\"",{"type":7,"value":8,"toc":749},"minimark",[9,13,24,31,47,52,55,62,73,100,103,109,113,116,124,135,144,179,208,211,219,225,253,257,264,279,285,296,299,306,320,325,329,345,348,377,397,423,427,430,466,469,483,487,514,517,523,530,534,541,547,558,561,567,570,575,579,595,601,616,622,630,634,637,646,666,675,693,697,742],[10,11,12],"p",{},"Seu builder escreveu uma função no banco para carregar os pedidos de um cliente, e\na página que a chama fica vazia. O console do navegador mostra isto:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","{\n  \"code\": \"PGRST202\",\n  \"details\": \"Searched for the function public.get_orders with parameter userId or with a single unnamed json\u002Fjsonb parameter, but no matches were found in the schema cache.\",\n  \"hint\": \"Perhaps you meant to call the function public.get_orders(user_id)\",\n  \"message\": \"Could not find the function public.get_orders(userId) in the schema cache\"\n}\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,30],{},"Supabase \"Could not find the function in the schema cache\" significa que o\nPostgREST não tem nenhuma função com esse nome que aceite exatamente os argumentos\nque seu app enviou. O PostgREST é a parte do Supabase que responde às chamadas\n",[21,28,29],{},"supabase.rpc()"," do seu app, e ele mantém a própria lista de todas as funções que\npode chamar, chamada schema cache.",[10,32,33,34,38,39,42,43,46],{},"Aqui está a parte que quase toda resposta erra: ",[35,36,37],"strong",{},"ela manda você recarregar o\nschema cache."," No Supabase essa lista se atualiza sozinha sempre que uma função é\ncriada ou alterada. A mensagem já disse o que está errado. ",[21,40,41],{},"userId",", entre\nparênteses, é o que seu app enviou. ",[21,44,45],{},"user_id",", na dica, é o que a função espera.",[48,49,51],"h2",{"id":50},"o-que-significa-could-not-find-the-function-in-the-schema-cache","O que significa \"Could not find the function in the schema cache\"?",[10,53,54],{},"Que nenhuma função no schema onde o PostgREST procurou tem esse nome junto com\nexatamente esses nomes de argumentos.",[10,56,57,58,61],{},"Pense em cada função do banco como um formulário impresso pregado atrás de um\nbalcão: o nome dela no alto e um campo rotulado para cada argumento. Quando seu app\nchama ",[21,59,60],{},"supabase.rpc('get_orders', { userId: id })",", ele entrega uma cópia\npreenchida. O PostgREST procura na parede um formulário com o mesmo nome e os\nmesmos rótulos. Se nenhum tiver, a cópia é recusada no balcão, e a mensagem lê de\nvolta os rótulos que você preencheu.",[10,63,64,65,72],{},"Quatro detalhes estão fixos no\n",[66,67,71],"a",{"href":68,"rel":69},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FError.hs",[70],"nofollow","próprio código do PostgREST",":",[74,75,76,84,91,97],"ul",{},[77,78,79,80,83],"li",{},"o código é ",[21,81,82],{},"PGRST202"," e o status é HTTP 404, o de uma página que não existe",[77,85,86,87,90],{},"os parênteses listam os nomes de argumentos que seu app enviou. Quando ele não\nenviou nenhum, a mensagem diz ",[21,88,89],{},"without parameters"," no lugar",[77,92,93,96],{},[21,94,95],{},"public."," antes do nome é o schema onde o PostgREST procurou",[77,98,99],{},"a dica, quando existe, nomeia a função mais parecida que o PostgREST conhece,\ncom os nomes de argumentos dela",[10,101,102],{},"Compare os parênteses com a dica antes de qualquer outra coisa.",[104,105],"diagram",{"alt":106,"caption":107,"src":108},"Uma cópia preenchida do formulário get_orders ao lado do formulário get_orders pregado na parede. O campo limit da cópia se liga ao campo limit da parede e está marcado. O campo userId da cópia segue em âmbar até um sinal de diferente ao lado de user_id e desce até uma placa com PGRST202 e 404.","O PostgREST casa uma chamada pelo nome da função e por cada nome de argumento. userId e user_id são dois rótulos diferentes, então nenhum formulário da parede bate.","\u002Fblog\u002Fsupabase-function-not-found\u002Fargument-names-must-match-1600x680.png",[48,110,112],{"id":111},"causa-1-os-nomes-dos-argumentos-não-batem","Causa 1: os nomes dos argumentos não batem",[10,114,115],{},"O PostgREST escolhe uma função pelo nome e pelos nomes dos argumentos juntos, então\numa função chamada com os nomes errados é, para o PostgREST, uma função que não\nexiste.",[10,117,118,119,72],{},"As regras, tiradas da busca no\n",[66,120,123],{"href":121,"rel":122},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FPlan.hs",[70],"planejador do PostgREST",[74,125,126,129,132],{},[77,127,128],{},"todo argumento sem valor padrão precisa ser enviado, com o nome exato",[77,130,131],{},"um argumento com valor padrão pode ficar de fora",[77,133,134],{},"um nome que a função não declara a descarta, mesmo quando todos os outros nomes\nbatem",[10,136,137,138,140,141,143],{},"Um nome pode estar errado de três jeitos fáceis de deixar passar. O primeiro é o\nJavaScript encontrando o SQL: seu app escreve ",[21,139,41],{}," e a função declara\n",[21,142,45],{},".",[10,145,146,147,150,151,153,154,157,158,163,164,167,168,171,172,167,175,178],{},"O segundo é um prefixo. Algumas funções chamam os argumentos de ",[21,148,149],{},"p_user_id",", para\nnão serem confundidos com uma coluna chamada ",[21,152,45],{},", e aí a chamada também\nprecisa levar o ",[21,155,156],{},"p_",". Numa\n",[66,159,162],{"href":160,"rel":161},"https:\u002F\u002Fgithub.com\u002Forgs\u002Fsupabase\u002Fdiscussions\u002F28379",[70],"discussão do Supabase"," a\nchamada enviava ",[21,165,166],{},"id",", ",[21,169,170],{},"nombre"," e mais três, a função declarava ",[21,173,174],{},"p_id",[21,176,177],{},"p_nombre","\ne o resto, e a dica imprimiu cada um dos nomes certos.",[10,180,181,182,185,186,189,190,195,196,198,199,202,203,207],{},"O terceiro é a regra que também renomeia colunas. Um nome digitado em SQL sem\naspas duplas vai para minúsculas, então ",[21,183,184],{},"create function get_orders(userId uuid)","\nsalva o argumento como ",[21,187,188],{},"userid",". Um\n",[66,191,194],{"href":192,"rel":193},"https:\u002F\u002Fcommunity.flutterflow.io\u002Fask-the-community\u002Fpost\u002Fcustom-action-calling-a-supabase-function---fails-with-a-postgres-IsfG19NQeLRmfRP",[70],"usuário do FlutterFlow","\ncaiu exatamente nisso: a chamada enviava ",[21,197,41],{},", e a dica respondeu ",[21,200,201],{},"(userid)",".\n",[66,204,206],{"href":205},"\u002Fblog\u002Fsupabase-schema-cache-column-error","A versão deste erro para colunas"," tem\numa tabela do que cada grafia cria.",[10,209,210],{},"Para ver os nomes que o banco salvou, rode isto no SQL Editor:",[14,212,217],{"className":213,"code":215,"language":216,"meta":23},[214],"language-sql","select p.proname, pg_get_function_arguments(p.oid)\nfrom pg_proc p\njoin pg_namespace n on n.oid = p.pronamespace\nwhere n.nspname = 'public' and p.proname = 'get_orders';\n","sql",[21,218,215],{"__ignoreMap":23},[10,220,221,224],{},[21,222,223],{},"pg_get_function_arguments"," mostra os argumentos como foram declarados, com os\nvalores padrão, então também mostra quais você pode deixar de fora.",[10,226,227,228,231,232,234,235,238,239,242,243,248,249,252],{},"A correção mais segura fica no app, porque não muda nada no banco. Peça ao seu\nbuilder para chamar a função pelos nomes salvos: \"",[21,229,230],{},"get_orders"," recebe ",[21,233,45],{},";\npasse ",[21,236,237],{},"{ user_id: … }"," em toda chamada ",[21,240,241],{},".rpc()"," para ela\". Renomear o argumento é\nmais difícil do que parece. A\n",[66,244,247],{"href":245,"rel":246},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002Fcurrent\u002Fsql-createfunction.html",[70],"documentação do Postgres","\ndiz sobre ",[21,250,251],{},"CREATE OR REPLACE FUNCTION",": \"You cannot change the name already\nassigned to any input parameter\". A função precisa ser apagada e criada de novo, e\nqualquer outra tela que a chame pelo nome antigo passa a falhar do mesmo jeito.",[48,254,256],{"id":255},"causa-2-o-valor-era-undefined-então-o-nome-nunca-foi-enviado","Causa 2: o valor era undefined, então o nome nunca foi enviado",[10,258,259,260,263],{},"Um argumento cujo valor é ",[21,261,262],{},"undefined"," nunca chega ao PostgREST, e a função passa a\nser procurada sem ele.",[10,265,266,267,269,270,278],{},"O supabase-js envia seus argumentos como JSON, e JSON não tem ",[21,268,262],{},". A\n",[66,271,274,275],{"href":272,"rel":273},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FJSON\u002Fstringify",[70],"referência do MDN sobre ",[21,276,277],{},"JSON.stringify","\ndiz que esses valores \"are either omitted (when found in an object) or changed to\nnull (when found in an array)\". Então esta chamada, feita antes de o usuário\nlogado carregar:",[14,280,283],{"className":281,"code":282,"language":19},[17],"await supabase.rpc('get_orders', { user_id: user?.id })\n",[21,284,282],{"__ignoreMap":23},[10,286,287,288,291,292,295],{},"envia ",[21,289,290],{},"{}",", e a resposta é\n",[21,293,294],{},"Could not find the function public.get_orders without parameters in the schema cache",".\nCom dois argumentos e um deles undefined, os parênteses listam só o que chegou.",[10,297,298],{},"O nome no seu código está certo, e é por isso que ler o código não encontra o\nproblema. A mensagem encontra: os parênteses estão vazios, ou têm um nome a menos\ndo que o código passa.",[10,300,301,302,305],{},"A correção é fazer a chamada quando o valor já existir. Quando a função foi\nescrita para lidar com um valor ausente, passe ",[21,303,304],{},"null"," de propósito, que o JSON\nmantém.",[10,307,308,309,312,313,315,316,143],{},"Um filtro faz o contrário com o mesmo valor. ",[21,310,311],{},".eq('user_id', user?.id)"," o coloca\nna requisição como a palavra ",[21,314,262],{},", e uma coluna uuid responde\n",[66,317,319],{"href":318},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","invalid input syntax for type uuid",[104,321],{"alt":322,"caption":323,"src":324},"Uma cópia preenchida de get_orders com user_id contendo undefined em âmbar e limit contendo 10. Uma seta marcada JSON.stringify leva à cópia que de fato é enviada, onde o campo user_id é um espaço vazio tracejado e só limit 10 sobra. Uma segunda seta leva a uma placa com PGRST202 e 404.","O JSON deixa de fora um valor undefined, então o argumento some no caminho e o PostgREST procura uma função sem ele.","\u002Fblog\u002Fsupabase-function-not-found\u002Fundefined-is-never-sent-1600x560.png",[48,326,328],{"id":327},"causa-3-a-função-está-em-outro-schema","Causa 3: a função está em outro schema",[10,330,331,332,334,335,338,339,344],{},"O ",[21,333,29],{}," procura no schema ",[21,336,337],{},"public",", o que a mensagem cita, a não ser que\nvocê diga outra coisa. Uma função criada em outro lugar nem está na lista do\nPostgREST:\n",[66,340,343],{"href":341,"rel":342},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FSchemaCache.hs",[70],"ele carrega funções","\nsó dos schemas que o seu projeto expõe pela API.",[10,346,347],{},"Isso aparece de dois jeitos:",[74,349,350,364],{},[77,351,352,353,356,357,360,361],{},"a função foi criada num schema próprio, como ",[21,354,355],{},"private"," ou ",[21,358,359],{},"billing",", e é chamada\ncom um simples ",[21,362,363],{},".rpc('get_orders')",[77,365,366,367,370,371,373,374],{},"o schema está escrito no nome, como ",[21,368,369],{},".rpc('billing.get_orders')",". O PostgREST lê\na string inteira como um nome só e procura em ",[21,372,337],{},", então a mensagem diz\n",[21,375,376],{},"public.billing.get_orders",[10,378,379,380,383,384,389,390,167,393,396],{},"Uma função de outro schema é chamada com ",[21,381,382],{},".schema('billing').rpc('get_orders', …)",",\ne esse schema precisa estar em Exposed schemas, nas configurações de API do\nprojeto, como mostra\n",[66,385,388],{"href":386,"rel":387},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fapi\u002Fusing-custom-schemas",[70],"o guia do Supabase sobre schemas próprios",".\nAté lá a resposta muda para ",[21,391,392],{},"PGRST106",[21,394,395],{},"Invalid schema: billing",", com uma dica que\nlista os schemas expostos.",[10,398,399,400,403,404,407,408,412,413,417,418,422],{},"Expor um schema do jeito que esse guia faz abre todas as tabelas dele. O guia dá a\n",[21,401,402],{},"anon"," e ",[21,405,406],{},"authenticated"," acesso a todas as tabelas do schema novo, e a partir daí\nsó as suas regras de ",[66,409,411],{"href":410},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security","\ndecidem o que um visitante pode ler ali.\n",[66,414,416],{"href":415},"\u002Fblog\u002Fsupabase-relation-does-not-exist","A versão deste erro para tabelas"," tem a\nconsulta que lista quais tabelas de um schema estão com essas regras desligadas,\npara rodar antes de expor o schema. Algumas funções ficam num schema privado\njustamente para ninguém chamá-las de fora: nosso\n",[66,419,421],{"href":420},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","guia sobre recursão infinita numa policy","\ncoloca uma ali exatamente por isso. Uma chamada a uma função assim pelo navegador\nrecebe PGRST202 de propósito, e o schema dela deve continuar sem ser exposto.",[48,424,426],{"id":425},"causa-4-o-nome-da-própria-função-ou-função-nenhuma","Causa 4: o nome da própria função, ou função nenhuma",[10,428,429],{},"O PostgREST procura o nome de forma exata, letra por letra, com maiúsculas e\nminúsculas.",[74,431,432,442,452],{},[77,433,434,435,438,439,441],{},"um erro de digitação, ou ",[21,436,437],{},"getOrders"," na chamada contra ",[21,440,230],{}," no banco",[77,443,444,445,447,448,451],{},"uma função criada como ",[21,446,437],{}," sem aspas duplas, que fica salva como\n",[21,449,450],{},"getorders"," pela mesma regra dos argumentos",[77,453,454,455,458,459,461,462,465],{},"uma procedure. O PostgREST só lista funções, então ",[21,456,457],{},"create procedure"," cria algo\nque o ",[21,460,241],{}," não alcança, e o mesmo vale para uma função que\n",[21,463,464],{},"returns trigger",", que roda a partir de um trigger e nunca a partir do seu app",[10,467,468],{},"A dica ajuda aqui também. Quando não existe função com esse nome, o PostgREST\nsugere o nome mais próximo que tem, se algum for parecido o bastante.",[10,470,471,472,477,478,482],{},"Ou a função nunca foi criada no banco que o seu app chama. Se você constrói com o\nLovable, volte pelo chat procurando um SQL que pediram para você aprovar. A\n",[66,473,476],{"href":474,"rel":475},"https:\u002F\u002Fdocs.lovable.dev\u002Fintegrations\u002Fsupabase",[70],"documentação do Lovable sobre o Supabase","\ndiz que ele \"writes the SQL, shows it to you, and asks for your approval in the\nproject chat before running it\". Até você aprovar, a função só existe no código que\na chama. Se alguém criou na mão, confira se ela foi para o projeto com que o seu\napp conversa: ",[66,479,481],{"href":480},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","uma branch é um projeto separado","\ncom banco próprio.",[48,484,486],{"id":485},"causa-5-o-cache-está-mesmo-desatualizado","Causa 5: o cache está mesmo desatualizado",[10,488,489,490,493,494,497,498,403,501,504,505,508,509,143],{},"No Supabase este é o caso raro. Todo banco do Supabase tem um event trigger,\n",[21,491,492],{},"pgrst_ddl_watch",", que manda ",[21,495,496],{},"NOTIFY pgrst, 'reload schema'"," depois de cada\n",[21,499,500],{},"CREATE FUNCTION",[21,502,503],{},"ALTER FUNCTION",", e um segundo, ",[21,506,507],{},"pgrst_drop_watch",", manda a\nmesma mensagem quando uma função é apagada. Os dois estão na\n",[66,510,513],{"href":511,"rel":512},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fpostgres\u002Fblob\u002Fdevelop\u002Fmigrations\u002Fschema-17.sql",[70],"configuração de banco do Supabase",[10,515,516],{},"Quando essa mensagem não chega, recarregue a lista na mão no SQL Editor:",[14,518,521],{"className":519,"code":520,"language":216,"meta":23},[214],"NOTIFY pgrst, 'reload schema';\n",[21,522,520],{"__ignoreMap":23},[10,524,525,526,529],{},"Se nada mudar,\n",[66,527,528],{"href":205},"a versão deste erro para colunas"," cobre\nos dois passos seguintes, a fila de notificações travada e o reinício do projeto.\nOs dois funcionam do mesmo jeito para funções.",[48,531,533],{"id":532},"quando-duas-funções-dividem-um-nome","Quando duas funções dividem um nome",[10,535,536,537,540],{},"O PostgREST não chuta entre elas. Quando duas funções têm o mesmo nome e as duas\naceitam os argumentos que seu app enviou, a chamada falha com ",[21,538,539],{},"PGRST203"," e\nHTTP 300:",[14,542,545],{"className":543,"code":544,"language":19},[17],"Could not choose the best candidate function between: public.get_orders(user_id => uuid), public.get_orders(user_id => text)\n",[21,546,544],{"__ignoreMap":23},[10,548,549,550,552,553,557],{},"Corrigir um PGRST202 é um jeito de chegar aqui. Seu builder muda o tipo de um\nargumento com ",[21,551,251],{},", e o Postgres não substitui nada. A\n",[66,554,556],{"href":245,"rel":555},[70],"documentação dele","\ndiz que os tipos dos argumentos não podem ser mudados assim: \"if you tried, you\nwould actually be creating a new, distinct function\". Agora as duas versões\nexistem lado a lado.",[10,559,560],{},"A dica do PostgREST para este caso diz \"Try renaming the parameters or the function\nitself in the database so function overloading can be resolved\". A correção mais\nsimples é apagar a versão que você não quer, dizendo o tipo do argumento dela para\no Postgres saber de qual se trata:",[14,562,565],{"className":563,"code":564,"language":216,"meta":23},[214],"drop function public.get_orders(text);\n",[21,566,564],{"__ignoreMap":23},[10,568,569],{},"Confira qual versão o seu app chama antes de apagar qualquer uma das duas.",[104,571],{"alt":572,"caption":573,"src":574},"Uma cópia preenchida de get_orders com user_id e dois formulários get_orders pregados na parede, um cujo campo user_id recebe uuid e outro que recebe text. Linhas tracejadas em âmbar vão da cópia até os dois formulários, e a cópia desce até uma placa com PGRST203 e 300.","Mudar o tipo de um argumento com CREATE OR REPLACE cria uma segunda função com o mesmo nome. Uma chamada que serve para as duas é recusada.","\u002Fblog\u002Fsupabase-function-not-found\u002Ftwo-functions-one-name-1600x700.png",[48,576,578],{"id":577},"como-chamar-uma-função-do-supabase-do-jeito-certo","Como chamar uma função do Supabase do jeito certo",[10,580,581,582,587,588,591,592,143],{},"Passe um objeto cujas chaves são os nomes dos argumentos da função, escritos como o\nbanco os salvou. No\n",[66,583,586],{"href":584,"rel":585},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fdatabase\u002Ffunctions",[70],"guia do Supabase sobre funções de banco",",\numa função declarada como ",[21,589,590],{},"add_planet(name text)"," é chamada com\n",[21,593,594],{},"supabase.rpc('add_planet', { name: 'Jakku' })",[10,596,597,598,600],{},"Assim que seu app consegue chamar a função, qualquer outra pessoa também consegue.\nO mesmo guia diz isso com todas as letras: \"By default, any role can run a database\nfunction.\" Isso inclui ",[21,599,402],{},", o papel por trás de cada requisição de um visitante\nque não fez login. Uma função que seu app chama pelo navegador pode ser chamada por\nqualquer pessoa que tenha sua chave pública, com os argumentos que quiser.",[10,602,603,604,607,608,610,611,613,614,143],{},"Para uma função que só usuários logados devem executar, siga o guia: tire o\n",[21,605,606],{},"execute"," de ",[21,609,337],{}," e de ",[21,612,402],{},", e devolva para ",[21,615,406],{},[14,617,620],{"className":618,"code":619,"language":216,"meta":23},[214],"revoke execute on function public.get_orders from public, anon;\ngrant execute on function public.get_orders to authenticated;\n",[21,621,619],{"__ignoreMap":23},[10,623,624,625,629],{},"Suas tabelas são a outra metade do que essa chave pública alcança. Nossa\n",[66,626,628],{"href":627},"\u002Fsecurity-scanner","varredura gratuita"," verifica de fora se elas entregam linhas\npara quem tem a chave, e não pede conta.",[48,631,633],{"id":632},"mudar-uma-função-da-qual-seu-app-depende","Mudar uma função da qual seu app depende",[10,635,636],{},"Guarde uma cópia do banco de antes da mudança e fique sabendo quando mudar algo\nque seu app expõe.",[10,638,639],{},[35,640,331,641,645],{},[66,642,644],{"href":643},"\u002Fsupabase-backups","Reeve Care"," guarda uma cópia do seu banco do Supabase:",[74,647,648,651,654,657,660,663],{},[77,649,650],{},"uma cópia criptografada num cronograma, no armazenamento próprio da Reeve na UE, fora da sua conta do Supabase",[77,652,653],{},"a cópia de antes da sua mudança tem suas funções como estavam definidas na época, ao lado das tabelas e linhas",[77,655,656],{},"cada cópia verificada antes de contar, contando as linhas de cada tabela",[77,658,659],{},"também seus arquivos enviados, assim que você conecta uma credencial do Storage",[77,661,662],{},"restauração com um clique, com uma cópia de segurança do estado atual feita antes",[77,664,665],{},"tudo o que o Monitor faz",[10,667,668],{},[35,669,331,670,674],{},[66,671,673],{"href":672},"\u002Fwebsite-monitoring","Reeve Monitor"," continua verificando de fora:",[74,676,677,680,683,690],{},[77,678,679],{},"se o seu app está no ar, verificado a cada minuto",[77,681,682],{},"a verificação de segurança completa a cada hora, em até três apps",[77,684,685,686,689],{},"uma mensagem quando um resultado ",[35,687,688],{},"muda",", para que um deploy que muda o que seu app expõe chegue até você sem você ir olhar",[77,691,692],{},"um relatório mensal, em linguagem simples, do que ele viu",[48,694,696],{"id":695},"o-que-fazer-agora","O que fazer agora",[698,699,700],"key-takeaways",{},[74,701,702,705,711,717,724,727,734],{},[77,703,704],{},"Leia a mensagem: os nomes entre parênteses são o que seu app enviou, e a dica nomeia o que o banco tem.",[77,706,707,708,710],{},"Compare os nomes dos argumentos letra por letra, incluindo um prefixo ",[21,709,156],{},". Um nome digitado em SQL sem aspas fica salvo em minúsculas.",[77,712,713,714,716],{},"Se os parênteses estiverem vazios ou com um nome a menos, procure um valor que estava ",[21,715,262],{}," na hora da chamada.",[77,718,719,720,723],{},"Confira o schema na mensagem. Uma função em outro schema precisa de ",[21,721,722],{},".schema('nome').rpc(…)"," e de um schema exposto, e expor um deixa as tabelas dele acessíveis também.",[77,725,726],{},"Se duas funções dividem o nome, apague a versão que seu app não chama.",[77,728,729,730,733],{},"Rode ",[21,731,732],{},"NOTIFY pgrst, 'reload schema';"," só depois que os nomes baterem.",[77,735,736,737,607,739,741],{},"Tire o ",[21,738,606],{},[21,740,402],{}," em qualquer função que um visitante sem login nunca deva rodar.",[10,743,744,745,748],{},"Comece pelos parênteses, porque eles têm exatamente o que seu app enviou. Antes de\napagar ou substituir uma função da qual seu app depende,\n",[66,746,747],{"href":643},"guarde uma cópia do banco"," de antes da mudança.",{"title":23,"searchDepth":750,"depth":750,"links":751},3,[752,754,755,756,757,758,759,760,761,762],{"id":50,"depth":753,"text":51},2,{"id":111,"depth":753,"text":112},{"id":255,"depth":753,"text":256},{"id":327,"depth":753,"text":328},{"id":425,"depth":753,"text":426},{"id":485,"depth":753,"text":486},{"id":532,"depth":753,"text":533},{"id":577,"depth":753,"text":578},{"id":632,"depth":753,"text":633},{"id":695,"depth":753,"text":696},"Noções de segurança","\u002Fblog\u002Fsupabase-function-not-found\u002Fcover-1200x630.png","Um formulário impresso pregado na parede com uma fileira de campos rotulados e, na frente, uma cópia preenchida com um campo aceso em âmbar.","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.",false,"md",[770,773,776,779,782],{"q":771,"a":772},"O que significa PGRST202?","PGRST202 é o código que o PostgREST, a parte do Supabase que responde às chamadas supabase.rpc(), devolve quando nenhuma função corresponde a uma chamada. Ele vem com HTTP 404 e a mensagem \"Could not find the function public.name(arguments) in the schema cache\". Os nomes entre parênteses são os argumentos que seu app enviou, e public é o schema onde ele procurou.",{"q":774,"a":775},"A função existe. Por que minha chamada RPC diz que ela não existe?","O PostgREST reconhece uma função pelo nome e pelos nomes dos argumentos juntos. Envie todo argumento que não tem valor padrão, exatamente com o nome que o banco salvou, e nada que a função não declare. Um nome escrito em SQL sem aspas duplas é salvo em minúsculas, então userId num create function vira userid.",{"q":777,"a":778},"Por que o erro diz \"without parameters\"?","Seu app não enviou nenhum argumento. Com o supabase-js o motivo comum é um valor que estava undefined na hora da chamada: os argumentos viajam como JSON, que deixa de fora os valores undefined, então { user_id: undefined } chega como {}. Faça a chamada quando o valor existir, ou passe null se a função foi escrita para lidar com um valor ausente.",{"q":780,"a":781},"A função precisa estar no schema public?","O supabase.rpc() procura em public, a não ser que você escolha outro schema com .schema('nome'), e esse schema precisa estar em Exposed schemas, nas configurações de API do projeto. Expor um schema deixa o que está nele acessível pela API, então vale decidir isso de propósito.",{"q":783,"a":784},"Como recarrego o schema cache do Supabase?","Rode NOTIFY pgrst, 'reload schema'; no SQL Editor. O Supabase já manda essa mensagem sozinho sempre que uma função é criada, alterada ou apagada, então recarregar só ajuda quando a mensagem não chegou. Confira os nomes primeiro.","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",[787,788,789,790,791,792,793,794],"could not find the function in the schema cache","pgrst202","supabase rpc função não encontrada","supabase rpc 404","supabase função parâmetros não batem","could not find the function without parameters in the schema cache","pgrst203","could not choose the best candidate function",{},true,"\u002Fblog\u002Fsupabase-function-not-found","2026-10-22",{"title":5,"description":766},"blog\u002Fsupabase-function-not-found",[802,803,804],"Supabase \"Could not find the function in the schema cache\" (PGRST202) significa que nenhuma função tem esse nome e aceita exatamente os nomes de argumentos que seu app enviou. Os nomes entre parênteses na mensagem são os que seu app enviou.","Confira primeiro os nomes dos argumentos: userId enviado para uma função que declara user_id, um prefixo p_ que faltou, ou um valor que estava undefined e por isso nunca foi enviado.","O Supabase atualiza sozinho a lista de funções sempre que uma é criada, alterada ou apagada, então confira os nomes e o schema antes de recarregar qualquer coisa.","6yXnLbzO3gmI2FySxd4e72b5PsT4oFq7XaXk76wpcx0",[807,813,819,825,831,837,843,849,855,861,867,874,880,886,892,898,903,909,914,915,920,926,932,938,944,950,956,962,968,974,980,986,992,997,1003,1009,1015,1021,1027,1033,1039,1045,1051,1057,1063,1069,1074,1080,1086,1092,1098,1104,1110,1116,1122,1128,1134,1140,1146,1152,1158,1164,1169,1175,1181,1187,1193,1199,1205,1211,1217,1223,1229,1235,1241,1247,1253,1259,1264,1270,1276,1282,1288,1294,1299,1305,1311,1317,1322,1328],{"path":808,"title":809,"description":810,"published":811,"category":763,"image":812,"draft":767},"\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":814,"title":815,"description":816,"published":817,"category":763,"image":818,"draft":767},"\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":820,"title":821,"description":822,"published":823,"category":763,"image":824,"draft":767},"\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":826,"title":827,"description":828,"published":829,"category":763,"image":830,"draft":767},"\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":832,"title":833,"description":834,"published":835,"category":763,"image":836,"draft":767},"\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":838,"title":839,"description":840,"published":841,"category":763,"image":842,"draft":767},"\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":844,"title":845,"description":846,"published":847,"category":763,"image":848,"draft":767},"\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":850,"title":851,"description":852,"published":853,"category":763,"image":854,"draft":767},"\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":856,"title":857,"description":858,"published":859,"category":763,"image":860,"draft":767},"\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":862,"title":863,"description":864,"published":865,"category":763,"image":866,"draft":767},"\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":868,"title":869,"description":870,"published":871,"category":872,"image":873,"draft":767},"\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":875,"title":876,"description":877,"published":878,"category":763,"image":879,"draft":767},"\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":881,"title":882,"description":883,"published":884,"category":763,"image":885,"draft":767},"\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":887,"title":888,"description":889,"published":890,"category":763,"image":891,"draft":767},"\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":893,"title":894,"description":895,"published":896,"category":763,"image":897,"draft":767},"\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":318,"title":899,"description":900,"published":901,"category":763,"image":902,"draft":767},"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":904,"title":905,"description":906,"published":907,"category":763,"image":908,"draft":767},"\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":415,"title":910,"description":911,"published":912,"category":763,"image":913,"draft":767},"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":797,"title":5,"description":766,"published":798,"category":763,"image":785,"draft":767},{"path":205,"title":916,"description":917,"published":918,"category":763,"image":919,"draft":767},"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":921,"title":922,"description":923,"published":924,"category":763,"image":925,"draft":767},"\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":927,"title":928,"description":929,"published":930,"category":763,"image":931,"draft":767},"\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":933,"title":934,"description":935,"published":936,"category":763,"image":937,"draft":767},"\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":939,"title":940,"description":941,"published":942,"category":763,"image":943,"draft":767},"\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":945,"title":946,"description":947,"published":948,"category":763,"image":949,"draft":767},"\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":951,"title":952,"description":953,"published":954,"category":763,"image":955,"draft":767},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" quase sempre é nenhuma","O Supabase devolve PGRST116, \"JSON object requested, multiple (or no) rows returned\", quando a consulta não achou nada. Linha escondida parece ausente.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":957,"title":958,"description":959,"published":960,"category":763,"image":961,"draft":767},"\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":963,"title":964,"description":965,"published":966,"category":763,"image":967,"draft":767},"\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":969,"title":970,"description":971,"published":972,"category":763,"image":973,"draft":767},"\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":975,"title":976,"description":977,"published":978,"category":763,"image":979,"draft":767},"\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":981,"title":982,"description":983,"published":984,"category":763,"image":985,"draft":767},"\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":987,"title":988,"description":989,"published":990,"category":763,"image":991,"draft":767},"\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":420,"title":993,"description":994,"published":995,"category":763,"image":996,"draft":767},"\"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":998,"title":999,"description":1000,"published":1001,"category":763,"image":1002,"draft":767},"\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":1004,"title":1005,"description":1006,"published":1007,"category":763,"image":1008,"draft":767},"\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":1010,"title":1011,"description":1012,"published":1013,"category":763,"image":1014,"draft":767},"\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":1016,"title":1017,"description":1018,"published":1019,"category":763,"image":1020,"draft":767},"\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":1022,"title":1023,"description":1024,"published":1025,"category":763,"image":1026,"draft":767},"\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":1028,"title":1029,"description":1030,"published":1031,"category":763,"image":1032,"draft":767},"\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":1034,"title":1035,"description":1036,"published":1037,"category":763,"image":1038,"draft":767},"\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":1040,"title":1041,"description":1042,"published":1043,"category":763,"image":1044,"draft":767},"\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":1046,"title":1047,"description":1048,"published":1049,"category":763,"image":1050,"draft":767},"\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":1052,"title":1053,"description":1054,"published":1055,"category":872,"image":1056,"draft":767},"\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":1058,"title":1059,"description":1060,"published":1061,"category":872,"image":1062,"draft":767},"\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":1064,"title":1065,"description":1066,"published":1067,"category":872,"image":1068,"draft":767},"\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":1070,"title":1071,"description":1072,"published":1067,"category":763,"image":1073,"draft":767},"\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":1075,"title":1076,"description":1077,"published":1078,"category":763,"image":1079,"draft":767},"\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":1081,"title":1082,"description":1083,"published":1084,"category":763,"image":1085,"draft":767},"\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":1087,"title":1088,"description":1089,"published":1090,"category":872,"image":1091,"draft":767},"\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":1093,"title":1094,"description":1095,"published":1096,"category":763,"image":1097,"draft":767},"\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":1099,"title":1100,"description":1101,"published":1102,"category":763,"image":1103,"draft":767},"\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":1105,"title":1106,"description":1107,"published":1108,"category":763,"image":1109,"draft":767},"\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":1111,"title":1112,"description":1113,"published":1114,"category":763,"image":1115,"draft":767},"\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":1117,"title":1118,"description":1119,"published":1120,"category":763,"image":1121,"draft":767},"\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":1123,"title":1124,"description":1125,"published":1126,"category":763,"image":1127,"draft":767},"\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":1129,"title":1130,"description":1131,"published":1132,"category":763,"image":1133,"draft":767},"\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":1135,"title":1136,"description":1137,"published":1138,"category":763,"image":1139,"draft":767},"\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":1141,"title":1142,"description":1143,"published":1144,"category":872,"image":1145,"draft":767},"\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":1147,"title":1148,"description":1149,"published":1150,"category":872,"image":1151,"draft":767},"\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":1153,"title":1154,"description":1155,"published":1156,"category":872,"image":1157,"draft":767},"\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":1159,"title":1160,"description":1161,"published":1162,"category":763,"image":1163,"draft":767},"\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":410,"title":1165,"description":1166,"published":1167,"category":763,"image":1168,"draft":767},"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":1170,"title":1171,"description":1172,"published":1173,"category":763,"image":1174,"draft":767},"\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":1176,"title":1177,"description":1178,"published":1179,"category":763,"image":1180,"draft":767},"\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":1182,"title":1183,"description":1184,"published":1185,"category":763,"image":1186,"draft":767},"\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":1188,"title":1189,"description":1190,"published":1191,"category":763,"image":1192,"draft":767},"\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":1194,"title":1195,"description":1196,"published":1197,"category":763,"image":1198,"draft":767},"\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":1200,"title":1201,"description":1202,"published":1203,"category":763,"image":1204,"draft":767},"\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":1206,"title":1207,"description":1208,"published":1209,"category":763,"image":1210,"draft":767},"\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":1212,"title":1213,"description":1214,"published":1215,"category":763,"image":1216,"draft":767},"\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":1218,"title":1219,"description":1220,"published":1221,"category":872,"image":1222,"draft":767},"\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":1224,"title":1225,"description":1226,"published":1227,"category":763,"image":1228,"draft":767},"\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":1230,"title":1231,"description":1232,"published":1233,"category":872,"image":1234,"draft":767},"\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":1236,"title":1237,"description":1238,"published":1239,"category":763,"image":1240,"draft":767},"\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":1242,"title":1243,"description":1244,"published":1245,"category":763,"image":1246,"draft":767},"\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":1248,"title":1249,"description":1250,"published":1251,"category":763,"image":1252,"draft":767},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy no Supabase. E agora?","\"New row violates row-level security policy\" significa que o Supabase recusou uma escrita. O conserto rápido reabre a tabela para qualquer um.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1254,"title":1255,"description":1256,"published":1257,"category":763,"image":1258,"draft":767},"\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":480,"title":1260,"description":1261,"published":1262,"category":872,"image":1263,"draft":767},"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":1265,"title":1266,"description":1267,"published":1268,"category":872,"image":1269,"draft":767},"\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":1271,"title":1272,"description":1273,"published":1274,"category":763,"image":1275,"draft":767},"\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":1277,"title":1278,"description":1279,"published":1280,"category":763,"image":1281,"draft":767},"\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":1283,"title":1284,"description":1285,"published":1286,"category":872,"image":1287,"draft":767},"\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":1289,"title":1290,"description":1291,"published":1292,"category":763,"image":1293,"draft":767},"\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":1295,"title":1296,"description":1297,"published":1292,"category":763,"image":1298,"draft":767},"\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":1300,"title":1301,"description":1302,"published":1303,"category":763,"image":1304,"draft":767},"\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":1306,"title":1307,"description":1308,"published":1309,"category":872,"image":1310,"draft":767},"\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":1312,"title":1313,"description":1314,"published":1315,"category":763,"image":1316,"draft":767},"\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":1318,"title":1319,"description":1320,"published":1315,"category":872,"image":1321,"draft":767},"\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":1323,"title":1324,"description":1325,"published":1326,"category":872,"image":1327,"draft":767},"\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":1329,"title":1330,"description":1331,"published":1326,"category":763,"image":1332,"draft":767},"\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",1794213649160]