[{"data":1,"prerenderedAt":1328},["ShallowReactive",2],{"blog-uk-supabase-function-not-found":3,"blog-index-uk":801},{"id":4,"title":5,"body":6,"category":758,"cover":759,"coverAlt":760,"description":761,"draft":762,"extension":763,"faq":764,"image":780,"keywords":781,"meta":790,"navigation":791,"ogTitle":5,"path":792,"published":793,"seo":794,"stem":795,"tldr":796,"updated":793,"__hash__":800},"blog_uk\u002Fblog\u002Fsupabase-function-not-found.md","Supabase PGRST202: \"Could not find the function in the schema cache\"",{"type":7,"value":8,"toc":744},"minimark",[9,13,24,31,47,52,55,62,73,99,102,108,112,115,123,134,143,178,206,209,217,223,251,255,262,276,282,293,296,303,317,322,326,341,344,373,393,419,423,426,462,465,479,483,510,513,519,526,530,537,543,554,557,563,566,571,575,591,597,611,617,625,629,632,641,661,670,688,692,737],[10,11,12],"p",{},"Ваш білдер написав функцію бази даних, яка завантажує замовлення клієнта, а\nсторінка, що її викликає, лишається порожньою. Консоль браузера показує ось це:",[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\" означає, що в PostgREST\nнемає функції з такою назвою, яка приймає саме ті аргументи, що надіслав ваш\nзастосунок. PostgREST є частиною Supabase, яка відповідає на виклики\n",[21,28,29],{},"supabase.rpc()"," вашого застосунку, і він веде власний список усіх функцій, які\nможе викликати. Цей список називається schema cache.",[10,32,33,34,38,39,42,43,46],{},"Ось що більшість відповідей подає неправильно: ",[35,36,37],"strong",{},"вони радять перезавантажити\nschema cache."," У Supabase цей список оновлюється сам щоразу, коли функцію\nстворюють або змінюють. Повідомлення вже сказало вам, що не так. ",[21,40,41],{},"userId"," у дужках\nнадіслав ваш застосунок. ",[21,44,45],{},"user_id"," у підказці очікує функція.",[48,49,51],"h2",{"id":50},"що-означає-could-not-find-the-function-in-the-schema-cache","Що означає \"Could not find the function in the schema cache\"?",[10,53,54],{},"Жодна функція в схемі, де шукав PostgREST, не має такої назви разом саме з такими\nназвами аргументів.",[10,56,57,58,61],{},"Уявіть кожну функцію бази даних як надрукований бланк, приколотий на стіні за\nвіконцем: угорі її назва, а нижче підписане поле для кожного аргументу. Коли ваш\nзастосунок викликає ",[21,59,60],{},"supabase.rpc('get_orders', { userId: id })",", він подає\nзаповнену копію. PostgREST шукає на стіні бланк із такою самою назвою й такими\nсамими підписами полів. Якщо такого немає, копію розвертають біля віконця, а\nповідомлення зачитує вам підписи, які ви заповнили.",[10,63,64,65,72],{},"Чотири речі зафіксовані у\n",[66,67,71],"a",{"href":68,"rel":69},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FError.hs",[70],"nofollow","власному коді PostgREST",":",[74,75,76,84,90,96],"ul",{},[77,78,79,80,83],"li",{},"код ",[21,81,82],{},"PGRST202",", а статус HTTP 404, той самий, що в сторінки, якої не існує",[77,85,86,87],{},"у дужках перелічено назви аргументів, які надіслав ваш застосунок. Якщо він не\nнадіслав жодного, замість них у повідомленні стоїть ",[21,88,89],{},"without parameters",[77,91,92,95],{},[21,93,94],{},"public."," перед назвою означає схему, у якій шукав PostgREST",[77,97,98],{},"підказка, якщо вона є, називає найближчу функцію, яку PostgREST знає, з її\nвласними назвами аргументів",[10,100,101],{},"Насамперед порівняйте дужки з підказкою.",[103,104],"diagram",{"alt":105,"caption":106,"src":107},"Заповнена копія бланка get_orders поруч із бланком get_orders на стіні. Поле limit на копії з'єднане з полем limit на стіні й позначене галочкою. Поле userId на копії тягнеться бурштиновою лінією до знака нерівності біля user_id і спускається до таблички з PGRST202 і 404.","PostgREST зіставляє виклик за назвою функції та кожною назвою аргументу. userId і user_id два різні підписи, тож жоден бланк на стіні не підходить.","\u002Fblog\u002Fsupabase-function-not-found\u002Fargument-names-must-match-1600x680.png",[48,109,111],{"id":110},"причина-1-назви-аргументів-не-збігаються","Причина 1: назви аргументів не збігаються",[10,113,114],{},"PostgREST вибирає функцію за її назвою та назвами аргументів разом, тож функція,\nяку викликали з неправильними назвами, для PostgREST просто не існує.",[10,116,117,118,72],{},"Правила, з пошуку в\n",[66,119,122],{"href":120,"rel":121},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FPlan.hs",[70],"планувальнику PostgREST",[74,124,125,128,131],{},[77,126,127],{},"кожен аргумент без значення за замовчуванням треба надіслати під його точною\nназвою",[77,129,130],{},"аргумент зі значенням за замовчуванням можна пропустити",[77,132,133],{},"назва, якої функція не оголошує, виключає цю функцію, навіть коли всі інші назви\nзбігаються",[10,135,136,137,139,140,142],{},"Назва може бути неправильною трьома способами, які легко проґавити. Перший\nвиникає, коли JavaScript зустрічає SQL: ваш застосунок пише ",[21,138,41],{},", а функція\nоголошує ",[21,141,45],{},".",[10,144,145,146,149,150,152,153,156,157,162,163,166,167,170,171,166,174,177],{},"Другий стосується префікса. Деякі функції називають свої аргументи ",[21,147,148],{},"p_user_id",",\nщоб їх не сплутали зі стовпцем ",[21,151,45],{},", і тоді виклик теж мусить нести ",[21,154,155],{},"p_",". В\nодному\n",[66,158,161],{"href":159,"rel":160},"https:\u002F\u002Fgithub.com\u002Forgs\u002Fsupabase\u002Fdiscussions\u002F28379",[70],"обговоренні Supabase"," виклик\nнадсилав ",[21,164,165],{},"id",", ",[21,168,169],{},"nombre"," і ще три назви, функція оголошувала ",[21,172,173],{},"p_id",[21,175,176],{},"p_nombre"," і\nрешту, а підказка надрукувала всі правильні назви.",[10,179,180,181,184,185,188,189,194,195,197,198,188,201,205],{},"Третій пов'язаний із правилом, яке перейменовує й стовпці. Назву, написану в SQL\nбез подвійних лапок, переводять у нижній регістр, тож\n",[21,182,183],{},"create function get_orders(userId uuid)"," зберігає аргумент як ",[21,186,187],{},"userid",".\n",[66,190,193],{"href":191,"rel":192},"https:\u002F\u002Fcommunity.flutterflow.io\u002Fask-the-community\u002Fpost\u002Fcustom-action-calling-a-supabase-function---fails-with-a-postgres-IsfG19NQeLRmfRP",[70],"Користувач FlutterFlow","\nнатрапив саме на це: виклик надсилав ",[21,196,41],{},", а підказка відповіла ",[21,199,200],{},"(userid)",[66,202,204],{"href":203},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Версія цієї помилки для стовпців"," має\nтаблицю того, що створює кожне написання.",[10,207,208],{},"Щоб побачити назви, які зберегла база, виконайте це в SQL Editor:",[14,210,215],{"className":211,"code":213,"language":214,"meta":23},[212],"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,216,213],{"__ignoreMap":23},[10,218,219,222],{},[21,220,221],{},"pg_get_function_arguments"," показує аргументи так, як їх оголосили, разом зі\nзначеннями за замовчуванням, тож видно й те, які з них можна пропустити.",[10,224,225,226,229,230,232,233,236,237,240,241,246,247,250],{},"Безпечніше виправлення робиться в застосунку, бо воно нічого не змінює в базі.\nПопросіть білдер викликати функцію за збереженими назвами: \"",[21,227,228],{},"get_orders"," приймає\n",[21,231,45],{},"; передавайте ",[21,234,235],{},"{ user_id: … }"," у кожному виклику ",[21,238,239],{},".rpc()"," до неї\".\nПерейменувати аргумент складніше, ніж здається.\n",[66,242,245],{"href":243,"rel":244},"https:\u002F\u002Fwww.postgresql.org\u002Fdocs\u002Fcurrent\u002Fsql-createfunction.html",[70],"Документація Postgres","\nкаже про ",[21,248,249],{},"CREATE OR REPLACE FUNCTION",": \"You cannot change the name already\nassigned to any input parameter\". Функцію доведеться видалити й створити знову, і\nкожен інший екран, який викликає її за старою назвою, після цього падає так само.",[48,252,254],{"id":253},"причина-2-значення-було-undefined-тож-назва-так-і-не-надійшла","Причина 2: значення було undefined, тож назва так і не надійшла",[10,256,257,258,261],{},"Аргумент зі значенням ",[21,259,260],{},"undefined"," ніколи не доходить до PostgREST, і функцію тоді\nшукають без нього.",[10,263,264,265,188,267,275],{},"supabase-js надсилає ваші аргументи як JSON, а в JSON немає ",[21,266,260],{},[66,268,271,272],{"href":269,"rel":270},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FJSON\u002Fstringify",[70],"Довідка MDN про ",[21,273,274],{},"JSON.stringify","\nкаже, що такі значення \"are either omitted (when found in an object) or changed to\nnull (when found in an array)\". Тож цей виклик, зроблений до того, як завантажився\nкористувач, що увійшов:",[14,277,280],{"className":278,"code":279,"language":19},[17],"await supabase.rpc('get_orders', { user_id: user?.id })\n",[21,281,279],{"__ignoreMap":23},[10,283,284,285,288,289,292],{},"надсилає ",[21,286,287],{},"{}",", і відповідь буде\n",[21,290,291],{},"Could not find the function public.get_orders without parameters in the schema cache",".\nЯкщо аргументів два й один із них undefined, у дужках буде лише той, що дійшов.",[10,294,295],{},"Назва у вашому коді правильна, тому читання коду цього не знаходить. Повідомлення\nзнаходить: дужки порожні або в них на одну назву менше, ніж передає код.",[10,297,298,299,302],{},"Виправлення полягає в тому, щоб робити виклик, коли значення вже є. Якщо функція\nвміє обробляти відсутнє значення, передавайте ",[21,300,301],{},"null"," навмисно, бо JSON його\nзберігає.",[10,304,305,306,309,310,312,313,142],{},"Фільтр робить із тим самим значенням протилежне. ",[21,307,308],{},".eq('user_id', user?.id)","\nвставляє його в запит словом ",[21,311,260],{},", і колонка uuid відповідає\n",[66,314,316],{"href":315},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","invalid input syntax for type uuid",[103,318],{"alt":319,"caption":320,"src":321},"Заповнена копія get_orders, де user_id містить undefined бурштиновим, а limit містить 10. Стрілка з підписом JSON.stringify веде до копії, яку насправді надіслано: там на місці поля user_id пунктирне порожнє місце й лишився тільки limit 10. Друга стрілка веде до таблички з PGRST202 і 404.","JSON пропускає значення undefined, тож аргумент зникає дорогою, і PostgREST шукає функцію без нього.","\u002Fblog\u002Fsupabase-function-not-found\u002Fundefined-is-never-sent-1600x560.png",[48,323,325],{"id":324},"причина-3-функція-в-іншій-схемі","Причина 3: функція в іншій схемі",[10,327,328,330,331,334,335,340],{},[21,329,29],{}," шукає в схемі ",[21,332,333],{},"public",", яку й називає повідомлення, якщо ви не\nвкажете інше. Функції, створеної деінде, у списку PostgREST немає взагалі:\n",[66,336,339],{"href":337,"rel":338},"https:\u002F\u002Fgithub.com\u002FPostgREST\u002Fpostgrest\u002Fblob\u002Fmain\u002Fsrc\u002Flibrary\u002FPostgREST\u002FSchemaCache.hs",[70],"він завантажує функції","\nтільки зі схем, які ваш проєкт відкриває через свій API.",[10,342,343],{},"Це трапляється у двох формах:",[74,345,346,360],{},[77,347,348,349,352,353,356,357],{},"функцію створили у власній схемі, наприклад ",[21,350,351],{},"private"," чи ",[21,354,355],{},"billing",", а\nвикликають простим ",[21,358,359],{},".rpc('get_orders')",[77,361,362,363,366,367,369,370],{},"схему вписали в назву, як ",[21,364,365],{},".rpc('billing.get_orders')",". PostgREST читає весь\nрядок як одну назву й шукає її в ",[21,368,333],{},", тож у повідомленні буде\n",[21,371,372],{},"public.billing.get_orders",[10,374,375,376,379,380,385,386,166,389,392],{},"Функцію з іншої схеми викликають через ",[21,377,378],{},".schema('billing').rpc('get_orders', …)",",\nі ця схема має бути в списку Exposed schemas у налаштуваннях API проєкту, як\nпоказує\n",[66,381,384],{"href":382,"rel":383},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fapi\u002Fusing-custom-schemas",[70],"посібник Supabase про власні схеми",".\nДоки її там немає, відповідь змінюється на ",[21,387,388],{},"PGRST106",[21,390,391],{},"Invalid schema: billing",", з\nпідказкою, яка перелічує відкриті схеми.",[10,394,395,396,399,400,403,404,408,409,413,414,418],{},"Відкрита так, як це робить той посібник, схема відчиняє кожну свою таблицю.\nПосібник дає ",[21,397,398],{},"anon"," і ",[21,401,402],{},"authenticated"," доступ до кожної таблиці нової схеми, і\nвідтоді лише ваші правила\n",[66,405,407],{"href":406},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security"," вирішують, що\nвідвідувач може там прочитати.\n",[66,410,412],{"href":411},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Версія цієї помилки для таблиць"," має\nзапит, який показує, на яких таблицях схеми ці правила вимкнені, і його варто\nвиконати до відкриття схеми. Деякі функції тримають у приватній схемі саме для\nтого, щоб ніхто не міг викликати їх ззовні: наш\n",[66,415,417],{"href":416},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","посібник про нескінченну рекурсію в policy","\nкладе одну туди саме з цієї причини. Виклик такої функції з браузера отримує\nPGRST202 навмисно, і її схема має лишатися закритою.",[48,420,422],{"id":421},"причина-4-назва-самої-функції-або-функції-немає-взагалі","Причина 4: назва самої функції, або функції немає взагалі",[10,424,425],{},"PostgREST шукає назву точно, літера в літеру й з урахуванням регістру.",[74,427,428,438,448],{},[77,429,430,431,434,435,437],{},"одруківка, або ",[21,432,433],{},"getOrders"," у виклику проти ",[21,436,228],{}," у базі",[77,439,440,441,443,444,447],{},"функція, створена як ",[21,442,433],{}," без подвійних лапок, яка зберігається як\n",[21,445,446],{},"getorders"," за тим самим правилом, що й її аргументи",[77,449,450,451,454,455,457,458,461],{},"процедура. PostgREST перелічує лише функції, тож ",[21,452,453],{},"create procedure"," створює\nщось, до чого ",[21,456,239],{}," не дістане, і так само з функцією, що ",[21,459,460],{},"returns trigger",":\nїї запускає тригер, а ніколи не ваш застосунок",[10,463,464],{},"Підказка допомагає й тут. Коли функції з такою назвою немає, PostgREST пропонує\nнайближчу назву, яку має, якщо якась достатньо схожа.",[10,466,467,468,473,474,478],{},"Або функцію так і не створили в базі, до якої звертається ваш застосунок. Якщо ви\nбудуєте в Lovable, перегляньте чат у пошуках SQL, який вас просили схвалити.\n",[66,469,472],{"href":470,"rel":471},"https:\u002F\u002Fdocs.lovable.dev\u002Fintegrations\u002Fsupabase",[70],"Документація Lovable про Supabase","\nкаже, що він \"writes the SQL, shows it to you, and asks for your approval in the\nproject chat before running it\". Доки ви не схвалите, функція існує лише в коді,\nякий її викликає. Якщо хтось створив її вручну, перевірте, що вона потрапила в\nтой проєкт, з яким говорить ваш застосунок:\n",[66,475,477],{"href":476},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","гілка є окремим проєктом"," зі своєю\nбазою.",[48,480,482],{"id":481},"причина-5-кеш-справді-застарів","Причина 5: кеш справді застарів",[10,484,485,486,489,490,493,494,399,497,500,501,504,505,142],{},"У Supabase це рідкісний випадок. Кожна база Supabase має event trigger\n",[21,487,488],{},"pgrst_ddl_watch",", який надсилає ",[21,491,492],{},"NOTIFY pgrst, 'reload schema'"," після кожного\n",[21,495,496],{},"CREATE FUNCTION",[21,498,499],{},"ALTER FUNCTION",", а другий, ",[21,502,503],{},"pgrst_drop_watch",", надсилає те\nсаме після видалення функції. Обидва є в\n",[66,506,509],{"href":507,"rel":508},"https:\u002F\u002Fgithub.com\u002Fsupabase\u002Fpostgres\u002Fblob\u002Fdevelop\u002Fmigrations\u002Fschema-17.sql",[70],"налаштуванні бази від Supabase",[10,511,512],{},"Коли це повідомлення не доходить, перезавантажте список вручну в SQL Editor:",[14,514,517],{"className":515,"code":516,"language":214,"meta":23},[212],"NOTIFY pgrst, 'reload schema';\n",[21,518,516],{"__ignoreMap":23},[10,520,521,522,525],{},"Якщо нічого не змінилося,\n",[66,523,524],{"href":203},"версія цієї помилки для стовпців","\nописує два наступні кроки: застряглу чергу сповіщень і перезапуск проєкту. Обидва\nпрацюють для функцій так само.",[48,527,529],{"id":528},"коли-дві-функції-мають-одну-назву","Коли дві функції мають одну назву",[10,531,532,533,536],{},"PostgREST не вгадує між ними. Коли дві функції мають однакову назву й обидві\nприймають аргументи, які надіслав ваш застосунок, виклик падає з ",[21,534,535],{},"PGRST203"," і\nHTTP 300:",[14,538,541],{"className":539,"code":540,"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,542,540],{"__ignoreMap":23},[10,544,545,546,548,549,553],{},"Виправлення PGRST202 буває одним зі шляхів сюди. Ваш білдер змінює тип аргументу\nчерез ",[21,547,249],{},", і Postgres нічого не замінює. Його\n",[66,550,552],{"href":243,"rel":551},[70],"документація","\nкаже, що типи аргументів так змінити не можна: \"if you tried, you would actually\nbe creating a new, distinct function\". Тепер обидві версії існують поруч.",[10,555,556],{},"Підказка PostgREST для цього випадку звучить так: \"Try renaming the parameters or\nthe function itself in the database so function overloading can be resolved\".\nПростіше виправлення полягає в тому, щоб видалити версію, яка вам не потрібна,\nназвавши тип її аргументу, щоб Postgres знав, про яку йдеться:",[14,558,561],{"className":559,"code":560,"language":214,"meta":23},[212],"drop function public.get_orders(text);\n",[21,562,560],{"__ignoreMap":23},[10,564,565],{},"Перевірте, яку версію викликає ваш застосунок, перш ніж видаляти будь-яку з них.",[103,567],{"alt":568,"caption":569,"src":570},"Заповнена копія get_orders з user_id і два бланки get_orders на стіні: поле user_id одного приймає uuid, а другого text. Пунктирні бурштинові лінії йдуть від копії до обох бланків, а копія спускається до таблички з PGRST203 і 300.","Зміна типу аргументу через CREATE OR REPLACE додає другу функцію з тією самою назвою. Виклик, який підходить до обох, відхиляють.","\u002Fblog\u002Fsupabase-function-not-found\u002Ftwo-functions-one-name-1600x700.png",[48,572,574],{"id":573},"як-правильно-викликати-функцію-supabase","Як правильно викликати функцію Supabase",[10,576,577,578,583,584,587,588,142],{},"Передавайте один об'єкт, ключі якого збігаються з назвами аргументів функції в\nтому написанні, яке зберегла база. У\n",[66,579,582],{"href":580,"rel":581},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fdatabase\u002Ffunctions",[70],"посібнику Supabase про функції бази даних","\nфункцію, оголошену як ",[21,585,586],{},"add_planet(name text)",", викликають так:\n",[21,589,590],{},"supabase.rpc('add_planet', { name: 'Jakku' })",[10,592,593,594,596],{},"Щойно ваш застосунок може викликати функцію, це може зробити й будь-хто інший. Той\nсамий посібник каже прямо: \"By default, any role can run a database function.\"\nСюди входить ",[21,595,398],{},", роль за кожним запитом відвідувача, який не увійшов. Функцію,\nяку ваш застосунок викликає з браузера, може викликати будь-хто з вашим публічним\nключем, із будь-якими аргументами на свій вибір.",[10,598,599,600,603,604,399,606,608,609,142],{},"Для функції, яку мають запускати лише користувачі, що увійшли, зробіть як у\nпосібнику: заберіть ",[21,601,602],{},"execute"," у ",[21,605,333],{},[21,607,398],{}," та поверніть його\n",[21,610,402],{},[14,612,615],{"className":613,"code":614,"language":214,"meta":23},[212],"revoke execute on function public.get_orders from public, anon;\ngrant execute on function public.get_orders to authenticated;\n",[21,616,614],{"__ignoreMap":23},[10,618,619,620,624],{},"Ваші таблиці становлять другу половину того, до чого дістає цей публічний ключ.\nНаше ",[66,621,623],{"href":622},"\u002Fsecurity-scanner","безкоштовне сканування"," перевіряє ззовні, чи віддають\nвони рядки будь-кому, хто має цей ключ, і не потребує облікового запису.",[48,626,628],{"id":627},"зміна-функції-від-якої-залежить-ваш-застосунок","Зміна функції, від якої залежить ваш застосунок",[10,630,631],{},"Майте копію бази з моменту перед зміною й дізнавайтеся, коли змінюється щось, що\nвідкриває ваш застосунок.",[10,633,634],{},[35,635,636,640],{},[66,637,639],{"href":638},"\u002Fsupabase-backups","Reeve Care"," зберігає копію вашої бази даних Supabase:",[74,642,643,646,649,652,655,658],{},[77,644,645],{},"зашифровану копію за розкладом, у власному сховищі Reeve в ЄС, поза вашим акаунтом Supabase",[77,647,648],{},"копія з моменту перед вашою зміною містить ваші функції такими, якими їх тоді визначили, поруч із таблицями й рядками",[77,650,651],{},"кожну копію перевірено, перш ніж вона зарахується, підрахунком рядків у кожній таблиці",[77,653,654],{},"також ваші завантажені файли, щойно ви підключите обліковий доступ до Storage",[77,656,657],{},"відновлення в один клік, перед яким робиться страхова копія поточного стану",[77,659,660],{},"усе, що робить Monitor",[10,662,663],{},[35,664,665,669],{},[66,666,668],{"href":667},"\u002Fwebsite-monitoring","Reeve Monitor"," і далі перевіряє ззовні:",[74,671,672,675,678,685],{},[77,673,674],{},"чи ваш застосунок доступний, перевірка щохвилини",[77,676,677],{},"повну перевірку безпеки щогодини, до трьох застосунків",[77,679,680,681,684],{},"повідомлення, коли результат ",[35,682,683],{},"змінюється",", тож деплой, який змінює те, що відкриває ваш застосунок, дійде до вас без того, щоб ви ходили дивитися",[77,686,687],{},"щомісячний звіт простою мовою про те, що він бачив",[48,689,691],{"id":690},"що-робити-зараз","Що робити зараз",[693,694,695],"key-takeaways",{},[74,696,697,700,706,711,718,721,728],{},[77,698,699],{},"Прочитайте повідомлення: назви в дужках надіслав ваш застосунок, а підказка називає те, що є в базі.",[77,701,702,703,705],{},"Порівняйте назви аргументів літера в літеру, разом із префіксом ",[21,704,155],{},". Назва, написана в SQL без лапок, зберігається малими літерами.",[77,707,708,709,142],{},"Якщо дужки порожні або в них бракує назви, шукайте значення, яке під час виклику було ",[21,710,260],{},[77,712,713,714,717],{},"Перевірте схему в повідомленні. Функції з іншої схеми потрібні ",[21,715,716],{},".schema('назва').rpc(…)"," і відкрита схема, а відкрита схема робить доступними й свої таблиці.",[77,719,720],{},"Якщо дві функції мають одну назву, видаліть версію, яку ваш застосунок не викликає.",[77,722,723,724,727],{},"Запускайте ",[21,725,726],{},"NOTIFY pgrst, 'reload schema';"," лише тоді, коли назви вже збігаються.",[77,729,730,731,733,734,736],{},"Заберіть ",[21,732,602],{}," в ",[21,735,398],{}," для кожної функції, яку відвідувач без входу не повинен запускати.",[10,738,739,740,743],{},"Почніть із дужок, бо в них саме те, що надіслав ваш застосунок. Перш ніж видаляти\nабо замінювати функцію, від якої залежить ваш застосунок,\n",[66,741,742],{"href":638},"збережіть копію бази"," з моменту перед зміною.",{"title":23,"searchDepth":745,"depth":745,"links":746},3,[747,749,750,751,752,753,754,755,756,757],{"id":50,"depth":748,"text":51},2,{"id":110,"depth":748,"text":111},{"id":253,"depth":748,"text":254},{"id":324,"depth":748,"text":325},{"id":421,"depth":748,"text":422},{"id":481,"depth":748,"text":482},{"id":528,"depth":748,"text":529},{"id":573,"depth":748,"text":574},{"id":627,"depth":748,"text":628},{"id":690,"depth":748,"text":691},"Основи безпеки","\u002Fblog\u002Fsupabase-function-not-found\u002Fcover-1200x630.png","Надрукований бланк на стіні з рядом підписаних полів, а перед ним заповнена копія, одне поле якої підсвічене бурштиновим.","Supabase \"Could not find the function in the schema cache\" показує назви аргументів, які надіслав ваш застосунок. Порівняйте їх із функцією.",false,"md",[765,768,771,774,777],{"q":766,"a":767},"Що означає PGRST202?","PGRST202 це код, який повертає PostgREST, частина Supabase, що відповідає на виклики supabase.rpc(), коли жодна функція не підходить до виклику. Він приходить із HTTP 404 і повідомленням \"Could not find the function public.name(arguments) in the schema cache\". Назви в дужках означають аргументи, які надіслав ваш застосунок, а public означає схему, у якій ішов пошук.",{"q":769,"a":770},"Функція існує. Чому мій RPC-виклик каже, що її немає?","PostgREST розпізнає функцію за її назвою та назвами її аргументів разом. Надсилайте кожен аргумент без значення за замовчуванням саме під тією назвою, яку зберегла база, і нічого, чого функція не оголошує. Назва, написана в SQL без подвійних лапок, зберігається малими літерами, тож userId у create function стає userid.",{"q":772,"a":773},"Чому в помилці написано \"without parameters\"?","Ваш застосунок не надіслав жодного аргументу. З supabase-js звична причина в значенні, яке під час виклику було undefined: аргументи передаються як JSON, а JSON пропускає значення undefined, тож { user_id: undefined } приходить як {}. Робіть виклик, коли значення вже є, або передавайте null, якщо функція вміє обробляти відсутнє значення.",{"q":775,"a":776},"Чи має функція бути в схемі public?","supabase.rpc() шукає в public, якщо ви не вибрали іншу схему через .schema('назва'), і ця схема має бути в списку Exposed schemas у налаштуваннях API проєкту. Відкрита схема робить свій вміст доступним через API, тож це варто вирішувати свідомо.",{"q":778,"a":779},"Як перезавантажити schema cache у Supabase?","Виконайте NOTIFY pgrst, 'reload schema'; у SQL Editor. Supabase і так надсилає це повідомлення сам щоразу, коли функцію створюють, змінюють або видаляють, тож перезавантаження допомагає лише тоді, коли повідомлення не дійшло. Спершу перевірте назви.","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",[782,783,784,785,786,787,788,789],"could not find the function in the schema cache","pgrst202","supabase rpc функцію не знайдено","supabase rpc 404","supabase параметри функції не збігаються","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":761},"blog\u002Fsupabase-function-not-found",[797,798,799],"Supabase \"Could not find the function in the schema cache\" (PGRST202) означає, що жодна функція не має такої назви й не приймає саме ті назви аргументів, які надіслав ваш застосунок. Назви в дужках у повідомленні належать тому, що надіслав ваш застосунок.","Спершу перевірте назви аргументів: userId, надісланий у функцію, яка оголошує user_id, пропущений префікс p_ або значення, яке було undefined і тому так і не надійшло.","Supabase сам оновлює свій список функцій щоразу, коли функцію створюють, змінюють або видаляють, тож перевірте назви та схему, перш ніж щось перезавантажувати.","YCxWdY9Wkn3MlGB9OZI2Si_0MkMfbJ1INBmLuceg9_4",[802,808,814,820,826,832,838,844,850,856,862,869,875,881,887,893,898,904,909,910,915,921,927,933,939,945,951,957,963,969,975,981,987,992,998,1004,1010,1016,1022,1028,1034,1040,1046,1052,1058,1064,1069,1075,1081,1087,1093,1099,1105,1111,1117,1123,1129,1135,1141,1147,1153,1159,1164,1170,1176,1182,1188,1194,1200,1206,1212,1218,1224,1230,1236,1242,1248,1254,1259,1265,1271,1277,1283,1289,1294,1300,1306,1312,1317,1323],{"path":803,"title":804,"description":805,"published":806,"category":758,"image":807,"draft":762},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\": пояснення","Supabase \"max client connections reached\": у пулера немає місця ще для одного клієнта. Ліміт визначає порт у вашому рядку підключення.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":809,"title":810,"description":811,"published":812,"category":758,"image":813,"draft":762},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Помилка Supabase: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\": вхід через Google вимкнено у вашому проєкті Supabase. Як увімкнути та виправити redirect_uri_mismatch.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":815,"title":816,"description":817,"published":818,"category":758,"image":819,"draft":762},"\u002Fblog\u002Fviolates-foreign-key-constraint","Помилка Supabase \"violates foreign key constraint\" під час вставки","Supabase \"insert or update on table violates foreign key constraint\": ваш рядок посилається на рядок, якого немає. Який, чому і як це виправити.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":821,"title":822,"description":823,"published":824,"category":758,"image":825,"draft":762},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Помилка Supabase \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": обовʼязковий стовпець прийшов порожнім. Звідки взявся null і як це виправити.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":827,"title":828,"description":829,"published":830,"category":758,"image":831,"draft":762},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": куди поділася сесія","\"Auth session missing!\" означає, що supabase-js не знайшла жодної сесії й навіть не спитала Supabase. Куди поділася сесія і як це виправити.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":833,"title":834,"description":835,"published":836,"category":758,"image":837,"draft":762},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","Supabase \"invalid claim: missing sub claim\": ніхто не ввійшов","\"invalid claim: missing sub claim\": Supabase Auth отримав справжній токен без жодного користувача, ключ проєкту замість сесії.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":839,"title":840,"description":841,"published":842,"category":758,"image":843,"draft":762},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": справжня причина","\"Failed to send a request to the Edge Function\": браузер не отримав відповіді, яку можна прочитати. Його консоль каже, чому, і чи ваша функція запускалася.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":845,"title":846,"description":847,"published":848,"category":758,"image":849,"draft":762},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Чому Supabase перенаправляє посилання з листів на localhost:3000","Якщо Supabase перенаправляє на localhost:3000, Site URL так і не змінили або вашої адреси немає в Redirect URLs. Як виправити і якої маски уникати.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":851,"title":852,"description":853,"published":854,"category":758,"image":855,"draft":762},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Supabase \"Email link is invalid or has expired\" на новому посиланні","На посиланні, надісланому хвилину тому, \"Email link is invalid or has expired\" у Supabase зазвичай означає, що поштовий фільтр використав його першим.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":857,"title":858,"description":859,"published":860,"category":758,"image":861,"draft":762},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\": пояснення","Supabase \"canceling statement due to statement timeout\": запит перевищив ліміт своєї ролі, 3 секунди для відвідувача. Спершу перевірте політику RLS.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":863,"title":864,"description":865,"published":866,"category":867,"image":868,"draft":762},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" у Supabase і що зникає разом","\"Database error deleting user\" у Supabase: ваша база відмовилася видаляти. Причина в логах, а виправлення вирішує, що ще буде видалено.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":870,"title":871,"description":872,"published":873,"category":758,"image":874,"draft":762},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" у Supabase","Вебхук Stripe в Edge Function Supabase пише \"No signatures found matching the expected signature\"? Причин дві. Не вимикайте перевірку.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":876,"title":877,"description":878,"published":879,"category":758,"image":880,"draft":762},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" у Supabase: три причини","Supabase відповідає \"Invalid login credentials\" на неправильний пароль, невідому пошту й акаунт Google. Як зрозуміти, що саме.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":882,"title":883,"description":884,"published":885,"category":758,"image":886,"draft":762},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\": справжня помилка","\"Edge Function returned a non-2xx status code\" означає, що ваша функція Supabase відповіла помилкою. Ось де прочитати справжню.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":888,"title":889,"description":890,"published":891,"category":758,"image":892,"draft":762},"\u002Fblog\u002Fcertificate-not-trusted","Сертифікат не довірений: три причини, крім закінчення строку","Сертифікат не довірений, хоча дата в порядку? Він називає іншу адресу, підписав сам себе або в його ланцюжку бракує ланки. Як зрозуміти, що саме.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":315,"title":894,"description":895,"published":896,"category":758,"image":897,"draft":762},"Supabase \"invalid input syntax for type uuid\": що в лапках","Supabase \"invalid input syntax for type uuid\" означає, що застосунок надіслав щось, що не є id. Прочитайте лапки, притримайте запит, залиште колонку.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":899,"title":900,"description":901,"published":902,"category":758,"image":903,"draft":762},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\": пояснення","Supabase \"duplicate key value violates unique constraint\": значення вже зайняте. Знайдіть стовпець, оберіть виправлення й сховайте значення від очей.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":411,"title":905,"description":906,"published":907,"category":758,"image":908,"draft":762},"Supabase \"relation does not exist\", хоча таблиця на місці","Supabase \"relation does not exist\" або PGRST205: жодна таблиця не має такої назви в цій схемі. Чотири перевірки, і на що зважити, відкриваючи схему.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":792,"title":5,"description":761,"published":793,"category":758,"image":780,"draft":762},{"path":203,"title":911,"description":912,"published":913,"category":758,"image":914,"draft":762},"Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" зазвичай означає, що назва не збігається. Чотири перевірки і рядок для перезавантаження.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":916,"title":917,"description":918,"published":919,"category":758,"image":920,"draft":762},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": два ліміти, один код помилки","Supabase \"Email Rate Limit Exceeded\" обмежує кожен лист вашого проєкту: 2 на годину з вбудованим відправником. Що враховується і як підняти ліміт.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":922,"title":923,"description":924,"published":925,"category":758,"image":926,"draft":762},"\u002Fblog\u002Fsupabase-users-logged-out","Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 причини","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" виводить ваших користувачів із системи. Три причини і як лог Auth їх розрізняє.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":928,"title":929,"description":930,"published":931,"category":758,"image":932,"draft":762},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": три причини","Supabase \"permission denied for schema public\" означає, що бракує GRANT на схему. Що його прибрало і який рядок його повертає.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":934,"title":935,"description":936,"published":937,"category":758,"image":938,"draft":762},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": три речі, які це може означати","Supabase \"Bucket not found\" означає одне з трьох: публічне посилання на приватний бакет, неточну назву або не той проєкт.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":940,"title":941,"description":942,"published":943,"category":758,"image":944,"draft":762},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: який ключ перестав працювати?","Помилка Supabase invalid JWT — це PGRST301: підписаний токен не пройшов перевірку. У новому проєкті йдеться про сесію, а не про ключ API.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":946,"title":947,"description":948,"published":949,"category":758,"image":950,"draft":762},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" майже завжди означає нуль","Supabase повертає PGRST116, \"JSON object requested, multiple (or no) rows returned\", коли запит нічого не знайшов. Прихований рядок має вигляд відсутнього.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":952,"title":953,"description":954,"published":955,"category":758,"image":956,"draft":762},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" у Supabase: де шукати","\"Database error saving new user\" означає, що щось причеплене до вашої реєстрації в Supabase впало. Справжня помилка лежить у ваших логах.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":958,"title":959,"description":960,"published":961,"category":758,"image":962,"draft":762},"\u002Fblog\u002Fwhat-is-supabase","Що таке Supabase? База даних, яку обрав ваш білдер","Що таке Supabase: база даних, вхід і сховище файлів за вашим застосунком. Supabase тримає сервери, а правила про те, хто читає ваші рядки, ваші.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":964,"title":965,"description":966,"published":967,"category":758,"image":968,"draft":762},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Відкритий у фронтенді ключ AWS це не те саме, що ключ OpenAI","Ключ доступу AWS, відкритий у вашому фронтенді, читає і пише ваше сховище. Рішення зазвичай presigned URL, а не новий ключ.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":970,"title":971,"description":972,"published":973,"category":758,"image":974,"draft":762},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" при вивантаженні","\"New row violates row-level security policy for table objects\" означає, що вашому вивантаженню бракує правила insert. Публічний бакет його не додає.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":976,"title":977,"description":978,"published":979,"category":758,"image":980,"draft":762},"\u002Fblog\u002Fbase44-security-scan","Сканування безпеки Base44: те, що бачить лише воно","Сканування безпеки Base44 перевіряє сім видів проблем зсередини. Ось половина, яку читає тільки воно, і половина, на яку воно ніколи не дивиться.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":982,"title":983,"description":984,"published":985,"category":758,"image":986,"draft":762},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Ваш API-ключ витік. Порядок дій","API-ключ витік, і ви не знаєте, що робити першим. Не кожен ключ у вашому фронтенді є витоком, а порядок важить більше за швидкість.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":416,"title":988,"description":989,"published":990,"category":758,"image":991,"draft":762},"\"Infinite recursion detected in policy\" без вимкнення RLS","\"Infinite recursion detected in policy for relation\" означає, що ваша policy запитала таблицю, яку вона захищає. Ось як розірвати коло.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":993,"title":994,"description":995,"published":996,"category":758,"image":997,"draft":762},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" у Supabase, і хибне виправлення","\"No API key found in request\" означає, що запит дійшов до Supabase без ключа. Більшість відповідей натомість вказують на правила вашої бази.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":999,"title":1000,"description":1001,"published":1002,"category":758,"image":1003,"draft":762},"\u002Fblog\u002Fis-base44-safe","Чи безпечний Base44? Дані 5 442 застосунків","Чи безпечний Base44? Ми прогнали дев’ять перевірок на 5 442 робочих застосунках Base44. Майже всі отримали B з причин, яких власник ніколи не обирав.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":1005,"title":1006,"description":1007,"published":1008,"category":758,"image":1009,"draft":762},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Сховати ключ API: перенесіть його в Supabase Edge Function","Сховати ключ API означає прибрати його з браузера, а Supabase Edge Function це найменше місце, куди його покласти. Два кроки поруч важать більше.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":1011,"title":1012,"description":1013,"published":1014,"category":758,"image":1015,"draft":762},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Чи відкритий ваш файл .env? Дванадцять шляхів для перевірки","Чи відкритий ваш файл .env на вашому власному вебсервері? Дванадцять адрес скажуть це за хвилину, а влучання означає, що все в ньому вже публічне.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":1017,"title":1018,"description":1019,"published":1020,"category":758,"image":1021,"draft":762},"\u002Fblog\u002Fis-v0-safe","Безпека v0: усі 1 790 просканованих застосунків v0 отримали A","Безпека v0 на 1 790 живих застосунках v0: усі отримали A. Лише 17 згадували базу даних, і саме це здебільшого вимірює оцінка A.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":1023,"title":1024,"description":1025,"published":1026,"category":758,"image":1027,"draft":762},"\u002Fblog\u002Fis-bolt-safe","Чи безпечний Bolt? Що показали 1 123 застосунки Bolt","Чи безпечний Bolt? Ми прогнали 1 123 живі застосунки Bolt через дев’ять перевірок. Хостинг був чистим. Знахідки: ключі й відкриті таблиці в самих застосунках.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":1029,"title":1030,"description":1031,"published":1032,"category":758,"image":1033,"draft":762},"\u002Fblog\u002Fis-supabase-down-or-your-app","Supabase не працює чи проблема у вашому застосунку? Як розрізнити","Supabase не працює чи зламався ваш застосунок? Пауза, повна база й ваша власна помилка виглядають однаково. Чотири перевірки їх розрізняють.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":1035,"title":1036,"description":1037,"published":1038,"category":758,"image":1039,"draft":762},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Чи шифрує Supabase мої дані? Так. Ось від чого це захищає","Чи шифрує Supabase дані? Так: AES-256 у стані спокою, TLS під час передавання, SOC 2 та ISO 27001. Що покриває кожне і який витік не зупиняє жодне.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":1041,"title":1042,"description":1043,"published":1044,"category":758,"image":1045,"draft":762},"\u002Fblog\u002Fsupabase-free-plan-limits","Ліміти безкоштовного тарифу Supabase і що стається на кожному","Ліміти безкоштовного тарифу Supabase: 500 МБ бази, 5 ГБ egress і жодних резервних копій. Що стається на кожній межі і що змінює Pro за $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":1047,"title":1048,"description":1049,"published":1050,"category":867,"image":1051,"draft":762},"\u002Fblog\u002Ftest-your-supabase-backup","Перевірте резервну копію Supabase до того, як вона знадобиться","Як перевірити резервну копію Supabase: відновити в тестовий проєкт, порахувати рядки, увійти й знайти рядок, якого бракує обрізаному файлу.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":1053,"title":1054,"description":1055,"published":1056,"category":867,"image":1057,"draft":762},"\u002Fblog\u002Fsupabase-backup-github-action","Безкоштовна резервна копія Supabase через GitHub Action і підступ","Резервна копія Supabase через GitHub Action безкоштовна й годиться багатьом застосункам. Робочий процес, потрібний рядок підключення та egress.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":1059,"title":1060,"description":1061,"published":1062,"category":867,"image":1063,"draft":762},"\u002Fblog\u002Fdownload-your-supabase-backup","Чому ви не можете завантажити резервну копію Supabase","Завантажити резервну копію Supabase на сучасному проєкті не вийде: щоденна копія там фізична. Як це перевірити і як тримати власну копію.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":1065,"title":1066,"description":1067,"published":1062,"category":758,"image":1068,"draft":762},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": бракує GRANT","З 30 жовтня нова таблиця в Supabase відповідає \"permission denied for table\", доки ви не дасте доступ. Лист показує лише половину виправлення.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":1070,"title":1071,"description":1072,"published":1073,"category":758,"image":1074,"draft":762},"\u002Fblog\u002Fopen-api-endpoint-exposed","Чи є відкритий API-ендпоінт проблемою безпеки? Читайте JSON","Ваше сканування позначило відкритий API-ендпоінт. Чи це важливо, залежить від того, що повернулося, і більшість знайдених належали платформі.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":1076,"title":1077,"description":1078,"published":1079,"category":758,"image":1080,"draft":762},"\u002Fblog\u002Flovable-security-scan","Сканування безпеки Lovable: чого воно не доведе","Сканування безпеки Lovable: що перевіряють Quick scan і Deep scan, коли запускається кожне, і єдине, чого не доведе жодне сканування зсередини.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":1082,"title":1083,"description":1084,"published":1085,"category":867,"image":1086,"draft":762},"\u002Fblog\u002Fsupabase-backup-auth-users","Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":1088,"title":1089,"description":1090,"published":1091,"category":758,"image":1092,"draft":762},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":1094,"title":1095,"description":1096,"published":1097,"category":758,"image":1098,"draft":762},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":1100,"title":1101,"description":1102,"published":1103,"category":758,"image":1104,"draft":762},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":1106,"title":1107,"description":1108,"published":1109,"category":758,"image":1110,"draft":762},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":1112,"title":1113,"description":1114,"published":1115,"category":758,"image":1116,"draft":762},"\u002Fblog\u002Fvite-and-next-public-env-vars","Змінні оточення Vite відкриті: префікс означає опублікувати це","Змінні оточення Vite відкриті у вашому застосунку, бо так просив префікс. VITE_ і NEXT_PUBLIC_ означають опублікувати це, а ШІ, який їх додав, не знав ціни.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":1118,"title":1119,"description":1120,"published":1121,"category":758,"image":1122,"draft":762},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":1124,"title":1125,"description":1126,"published":1127,"category":758,"image":1128,"draft":762},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":1130,"title":1131,"description":1132,"published":1133,"category":758,"image":1134,"draft":762},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":1136,"title":1137,"description":1138,"published":1139,"category":867,"image":1140,"draft":762},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":1142,"title":1143,"description":1144,"published":1145,"category":867,"image":1146,"draft":762},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Point-in-time recovery у Supabase: ціна та межі","Point-in-time recovery у Supabase відмотує базу на будь-яку секунду за останній тиждень. Коштує $100 на місяць понад Pro і покриває лише базу даних.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":1148,"title":1149,"description":1150,"published":1151,"category":867,"image":1152,"draft":762},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":1154,"title":1155,"description":1156,"published":1157,"category":758,"image":1158,"draft":762},"\u002Fblog\u002Fsafest-ai-app-builder","Який білдер застосунків з ШІ найбезпечніший? 30 998 тестів","Який білдер застосунків з ШІ найбезпечніший? Ми просканували 30 998 живих застосунків з Lovable, Base44, Replit, v0 і Bolt. Оцінку вирішує не білдер.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":406,"title":1160,"description":1161,"published":1162,"category":758,"image":1163,"draft":762},"Увімкніть Row Level Security на кожній таблиці Supabase і перевірте","Row Level Security у Supabase без політики закриває таблицю повністю. Політика без увімкненого перемикача не робить нічого. Ось SQL, і ось перевірка.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":1165,"title":1166,"description":1167,"published":1168,"category":758,"image":1169,"draft":762},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": чого не бачить попередження","Supabase позначає \"RLS disabled in public\" як помилку. Про політику читання, яка лишає вашу таблицю так само відкритою, він не каже нічого.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":1171,"title":1172,"description":1173,"published":1174,"category":758,"image":1175,"draft":762},"\u002Fblog\u002Frotate-supabase-service-role-key","Як замінити злитий ключ service_role у Supabase","Supabase каже спершу закрити витік. Інші посібники кажуть міняти негайно. Що правильно, залежить від того, куди саме потрапив ваш ключ service_role.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1177,"title":1178,"description":1179,"published":1180,"category":758,"image":1181,"draft":762},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Вісім інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1183,"title":1184,"description":1185,"published":1186,"category":758,"image":1187,"draft":762},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: п’ять перевірок, які зробите самі","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1189,"title":1190,"description":1191,"published":1192,"category":758,"image":1193,"draft":762},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1195,"title":1196,"description":1197,"published":1198,"category":758,"image":1199,"draft":762},"\u002Fblog\u002Fmissing-security-headers","Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1201,"title":1202,"description":1203,"published":1204,"category":758,"image":1205,"draft":762},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Ваш ключ API OpenAI відкритий у фронтенді. Замініть його.","Ключ API OpenAI, відкритий у фронтенді, не можна прив'язати до домену. Замініть його сьогодні, перенесіть виклик на свій сервер і обмежте витрати.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1207,"title":1208,"description":1209,"published":1210,"category":758,"image":1211,"draft":762},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","Ключ API у фронтенді: що насправді віддають 30 998 застосунків","Ключ API, відкритий у вашому фронтенді, зазвичай є ключем Google Maps. Ми просканували 30 998 vibe-coded застосунків і порахували, що витікає насправді.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1213,"title":1214,"description":1215,"published":1216,"category":867,"image":1217,"draft":762},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1219,"title":1220,"description":1221,"published":1222,"category":758,"image":1223,"draft":762},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1225,"title":1226,"description":1227,"published":1228,"category":867,"image":1229,"draft":762},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1231,"title":1232,"description":1233,"published":1234,"category":758,"image":1235,"draft":762},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1237,"title":1238,"description":1239,"published":1240,"category":758,"image":1241,"draft":762},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Де знайти API-ключі Supabase: anon, service_role і URL","URL проєкту, ключ anon і ключ service_role лежать на одній сторінці панелі. Ось де вона, і яке з чотирьох значень має бути у вашому застосунку.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1243,"title":1244,"description":1245,"published":1246,"category":758,"image":1247,"draft":762},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy в Supabase. Що далі?","\"New row violates row-level security policy\" означає, що Supabase відмовив у записі. Швидке виправлення знову відкриває таблицю для всіх.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1249,"title":1250,"description":1251,"published":1252,"category":758,"image":1253,"draft":762},"\u002Fblog\u002Fcors-wildcard-security-risk","Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":476,"title":1255,"description":1256,"published":1257,"category":867,"image":1258,"draft":762},"Branching у Supabase це не бекап. Він іде тільки вперед.","Чому branching у Supabase це не бекап: гілка стартує без ваших даних, а мердж переносить саму лише схему. Для чого він потрібен і що брати замість нього.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":1260,"title":1261,"description":1262,"published":1263,"category":867,"image":1264,"draft":762},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1266,"title":1267,"description":1268,"published":1269,"category":758,"image":1270,"draft":762},"\u002Fblog\u002Fsupabase-storage-bucket-public","Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1272,"title":1273,"description":1274,"published":1275,"category":758,"image":1276,"draft":762},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Чи є проблемою ключ API Google у вашому браузері?","Ключ API Google у відкритому коді сторінки наш сканер знаходить найчастіше, і зазвичай усе гаразд. Вирішує це одне безкоштовне налаштування.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1278,"title":1279,"description":1280,"published":1281,"category":867,"image":1282,"draft":762},"\u002Fblog\u002Fai-agent-deleted-my-database","ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1284,"title":1285,"description":1286,"published":1287,"category":758,"image":1288,"draft":762},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Чи може будь-хто прочитати вашу базу Supabase? 3 680 застосунків","Чи може будь-хто прочитати вашу базу даних Supabase без входу? Ми просканували 30 998 живих застосунків, зроблених ШІ-білдерами, і виміряли, як часто так.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1290,"title":1291,"description":1292,"published":1287,"category":758,"image":1293,"draft":762},"\u002Fblog\u002Fsource-maps-exposed-in-production","Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1295,"title":1296,"description":1297,"published":1298,"category":758,"image":1299,"draft":762},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: це той самий anon key?","Supabase замінив anon і service_role публічними та секретними ключами. Який із них має бути у вашому застосунку, а який не має бути ніколи?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1301,"title":1302,"description":1303,"published":1304,"category":867,"image":1305,"draft":762},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1307,"title":1308,"description":1309,"published":1310,"category":758,"image":1311,"draft":762},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security увімкнено. Таблиця досі публічна.","Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1313,"title":1314,"description":1315,"published":1310,"category":867,"image":1316,"draft":762},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1318,"title":1319,"description":1320,"published":1321,"category":867,"image":1322,"draft":762},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Три способи зробити резервну копію бази Supabase, і чого бракує","Панель, pg_dump і керований сервіс. Що насправді зберігає кожен спосіб, що тихо лишає осторонь і який із них переживе втрату акаунта.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1324,"title":1325,"description":1326,"published":1321,"category":758,"image":1327,"draft":762},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Які API-ключі безпечні у браузері, а які ні","Ваш ключ anon у Supabase створений, щоб бути публічним. Ключ service_role для цього не створений, і він ігнорує всі правила, які ви задали. Як їх розрізнити.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213654347]