[{"data":1,"prerenderedAt":920},["ShallowReactive",2],{"blog-uk-infinite-recursion-in-policy-for-relation":3,"blog-index-uk":566},{"id":4,"title":5,"body":6,"category":523,"cover":524,"coverAlt":525,"description":526,"draft":527,"extension":528,"faq":529,"image":544,"keywords":545,"meta":554,"navigation":555,"ogTitle":556,"path":557,"published":558,"seo":559,"stem":560,"tldr":561,"updated":558,"__hash__":565},"blog_uk\u002Fblog\u002Finfinite-recursion-in-policy-for-relation.md","\"Infinite recursion detected in policy\" без вимкнення RLS",{"type":7,"value":8,"toc":510},"minimark",[9,13,24,32,37,40,43,60,63,67,70,78,93,99,102,106,112,118,121,125,133,139,142,145,197,208,216,220,226,229,234,237,240,292,295,298,305,313,317,320,330,333,351,367,371,374,391,394,398,404,413,431,442,459,463,502],[10,11,12],"p",{},"Ви увімкнули Row Level Security, написали правило, щоб адміністратори бачили\nвсі профілі, а решта лише свій, і тепер жоден екран вашого застосунку не\nзавантажується. Кожне читання повертається з тим самим рядком:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","infinite recursion detected in policy for relation \"profiles\"\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26,27,31],{},"Більшість відповідей, які ви знайдете, кажуть одне й те саме, і це хибна порада:\n",[28,29,30],"strong",{},"вимкніть Row Level Security на цій таблиці, доки не розберетеся."," Помилка\nсправді зупиняється. Зупиняє її те, що таблицю тепер може прочитати будь-хто,\nхто завітає на ваш сайт.",[33,34,36],"h2",{"id":35},"що-означає-infinite-recursion-detected-in-policy-for-relation","Що означає \"infinite recursion detected in policy for relation\"",[10,38,39],{},"Правило на таблиці мусило прочитати цю саму таблицю, перш ніж змогло\nвідповісти.",[10,41,42],{},"Уявіть швейцара, який звіряє кожного відвідувача зі списком гостей, а список\nлежить усередині зали, яку він охороняє. Щоб прочитати список, треба зайти. Щоб\nзайти, треба звіритися зі списком. Першого кроку немає, тож він стоїть у\nкоридорі і ніхто нікуди не потрапляє.",[10,44,45,46,49,50,52,53,55,56,59],{},"Саме в це впоролася ваша база даних. У неї попросили кілька рядків із\n",[21,47,48],{},"profiles",", вона пішла до правила на ",[21,51,48],{},", щоб зʼясувати, які з них вам\nдозволено бачити, а правило сказало їй заглянути в ",[21,54,48],{},". Postgres\nпомічає, що ходить по колу, здається і піднімає помилку з кодом ",[21,57,58],{},"42P17",".\nSupabase передає її вашому застосунку без змін, тому вона й читається як\nмеханіка.",[10,61,62],{},"Запит падає для всіх, до кого застосовується правило, тож це зазвичай приходить\nяк цілий застосунок, що разом лишається порожнім, а не як один зламаний екран.",[33,64,66],{"id":65},"коло-намальоване","Коло, намальоване",[10,68,69],{},"Правило, яке це спричиняє, пишуть першим майже всі, бо воно каже рівно те, що\nви маєте на увазі:",[14,71,76],{"className":72,"code":74,"language":75,"meta":23},[73],"language-sql","-- Відхилити: це читає profiles, щоб вирішити, кому можна читати profiles.\ncreate policy \"admins read every profile\" on profiles for select\nto authenticated\nusing (\n  exists (\n    select 1 from profiles\n    where id = (select auth.uid()) and role = 'admin'\n  )\n);\n","sql",[21,77,74],{"__ignoreMap":23},[10,79,80,83,84,86,87,89,90,92],{},[21,81,82],{},"exists (select 1 from profiles …)"," і є вся проблема. Прочитати ",[21,85,48],{},"\nозначає застосувати правило на ",[21,88,48],{},", яке знову виконує\n",[21,91,82],{},".",[94,95],"diagram",{"alt":96,"caption":97,"src":98},"Читання відвідувача приходить до policy, намальованої як замок. Policy надсилає питання до таблиці profiles, а таблиця повертає його до policy, і ця пара стрілок утворює замкнене коло з позначкою 42P17.","Із запитом усе гаразд. Коло пролягає між правилом і таблицею, яку це правило захищає.","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fthe-circle-1600x660.png",[10,100,101],{},"Власний посібник Supabase з Row Level Security називає варіант із двома\nтаблицями: policy на двох таблицях, які читають одна одну, ніколи не\nрозвʼязуються, і запит падає для кожної ролі, до якої ці policy застосовуються.\nТаблиця, що читає саму себе, це та сама форма без гака.",[33,103,105],{"id":104},"чому-це-завжди-стається-на-таблиці-profiles","Чому це завжди стається на таблиці profiles?",[10,107,108,109,111],{},"Бо в ",[21,110,48],{}," лежить те, хто ця людина.",[10,113,114,115,117],{},"Будь-яке правило, що ставиться до одного типу людей інакше, ніж до іншого, мусить\nзʼясувати, якого типу той, хто звертається, а цей факт живе в колонці якоїсь\nтаблиці. Хоч би як та таблиця звалася, правило, що її захищає, зрештою читає\nсаме її. У застосунку з Lovable, Bolt, v0 чи Replit це зазвичай ",[21,116,48],{},", бо\nтуди потрапляє рядок про кожну людину, яка увійшла. Правило про команди,\nорганізації чи спільні документи дає те саме коло на тій таблиці, що тримає\nналежність.",[10,119,120],{},"Отже, рекурсія виходить із того, що ви написали очевидне правило про єдину\nтаблицю, яка має відповісти на питання про саму себе.",[33,122,124],{"id":123},"виправлення-помічник-що-читає-таблицю-поза-правилами","Виправлення: помічник, що читає таблицю поза правилами",[10,126,127,128,130,131,92],{},"Перенесіть питання в невелику функцію, яка виконується як власник бази даних,\nщоб читання ",[21,129,48],{}," заради відповіді не йшло через правило на ",[21,132,48],{},[14,134,137],{"className":135,"code":136,"language":75,"meta":23},[73],"create schema if not exists private;\n\ncreate function private.is_admin()\nreturns boolean\nlanguage sql\nsecurity definer      -- виконується як роль, що її створила\nset search_path = ''  -- тож кожне імʼя всередині треба писати повністю\nstable\nas $$\n  select exists (\n    select 1 from public.profiles\n    where id = (select auth.uid()) and role = 'admin'\n  );\n$$;\n\nrevoke execute on function private.is_admin() from public;\ngrant usage on schema private to authenticated;\ngrant execute on function private.is_admin() to authenticated;\n\n-- Тепер правило запитує функцію замість таблиці.\ncreate policy \"admins read every profile\" on profiles for select\nto authenticated\nusing ( (select private.is_admin()) );\n",[21,138,136],{"__ignoreMap":23},[10,140,141],{},"Тепер у швейцара список гостей лежить на столі в коридорі. Він читає його, не\nвідчиняючи дверей, а двері лишаються зачиненими для всіх, кого в списку немає.",[10,143,144],{},"Чотири рядки там роблять конкретну роботу, і три з них це різниця між\nвиправленням і новою діркою:",[146,147,148,161,177,186],"ul",{},[149,150,151,156,157,160],"li",{},[28,152,153],{},[21,154,155],{},"security definer"," це те, що розриває коло. Посібник Supabase визначає це\nяк функцію, що виконується під тією самою роллю, яка її створила, а в Supabase\nця роль ",[21,158,159],{},"postgres",", якій дозволено читати понад правилами.",[149,162,163,168,169,172,173,176],{},[28,164,165],{},[21,166,167],{},"set search_path = ''"," належить кожній із них. Supabase радить ставити це\nна кожній функції security definer і писати назви таблиць повністю, бо без\nзакріпленого ",[21,170,171],{},"search_path"," той, хто звертається, може спрямувати\nнекваліфіковане імʼя на власний обʼєкт і виконати його з правами власника\nфункції. Саме тому функція пише ",[21,174,175],{},"public.profiles"," повністю.",[149,178,179,185],{},[28,180,181,182],{},"Схема ",[21,183,184],{},"private"," важлива з тієї самої причини. Посібник Supabase\nпопереджає, що функцію security definer у відкритій схемі можна викликати\nчерез Data API з правами того, хто її створив, і каже ніколи не створювати\nтаку в схемі, що перелічена під Exposed schemas у налаштуваннях вашого API.",[149,187,188,193,194,92],{},[28,189,190],{},[21,191,192],{},"(select private.is_admin())",", загорнуте у власний select. Це дає Postgres\nпорахувати відповідь один раз на всю інструкцію замість одного разу на рядок,\nщо Supabase документує як причину так само загортати ",[21,195,196],{},"auth.uid()",[10,198,199,200,203,204,207],{},"Рядки ",[21,201,202],{},"revoke"," і ",[21,205,206],{},"grant"," лишають функцію доступною для користувачів, які\nувійшли, і більше ні для кого.",[10,209,210,211,92],{},"Ця policy охоплює читання. Якщо збереження почне падати щойно ваші екрани знову\nнаповняться, ви зустріли\n",[212,213,215],"a",{"href":214},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","інше повідомлення з іншою причиною",[33,217,219],{"id":218},"виправлення-яке-нічого-не-виправляє","Виправлення, яке нічого не виправляє",[10,221,222,223,225],{},"Вимкнення Row Level Security на ",[21,224,48],{}," теж зупиняє помилку, одним кліком, і\nвіддає кожен рядок цієї таблиці будь-кому, хто має ключ, який ваш застосунок\nвіддає браузеру.",[10,227,228],{},"Цей ключ задуманий як публічний. Він лежить у коді вашого сайту, і будь-хто\nдістане його за кілька секунд. Тим, що досі не давало йому повернути всю вашу\nтаблицю користувачів, були правила, які ви щойно вимкнули.",[94,230],{"alt":231,"caption":232,"src":233},"Два шляхи до тієї самої таблиці. На першому замок усе ще стоїть, а допоміжна функція поруч повертає два рядки з шести. На другому місце замка це лише порожній пунктирний контур, і всі шість рядків повертаються червоними.","Обидва зупиняють помилку. Лише один із них досі відповідає на питання, яке поставили правилу.","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Ftwo-ways-out-1600x700.png",[10,235,236],{},"Ваш застосунок після цього виглядає однаково в обох випадках, і саме це робить\nпроблему живучою. Ніщо на ваших екранах не каже, який із двох варіантів ви\nобрали, і помилки немає в обох.",[10,238,239],{},"А каже про це ваша база даних, запитана ззовні. Ми просканували 31 056 живих\nзастосунків, зроблених із Lovable, Bolt, v0, Replit та іншими, і побачили\nпроєкт Supabase за 8 435 із них. Ось що знайшла перевірка Row Level Security:",[241,242,243,256],"table",{},[244,245,246],"thead",{},[247,248,249,253],"tr",{},[250,251,252],"th",{},"Що ми питали",[250,254,255],{},"Застосунків",[257,258,259,268,276,284],"tbody",{},[247,260,261,265],{},[262,263,264],"td",{},"Мали видимий проєкт Supabase",[262,266,267],{},"8 435",[247,269,270,273],{},[262,271,272],{},"Їх узагалі можна було запитати",[262,274,275],{},"3 680",[247,277,278,281],{},[262,279,280],{},"Повернули рядки на запит без входу",[262,282,283],{},"2 096",[247,285,286,289],{},[262,287,288],{},"З них із таблиці про людей, замовлення чи повідомлення",[262,290,291],{},"394",[10,293,294],{},"Середній рядок найчесніший. На 4 755 цих застосунків перевірка не дістала\nвідповіді, і ми це кажемо, замість оголошувати їх чистими. А деякі з 2 096 і\nмають бути доступними для читання, бо публічна таблиця це цілком бажана річ;\nззовні меню і список учасників виглядають однаково.",[10,296,297],{},"Ми не можемо сказати вам, скільки з цих таблиць відкрив хтось, хто прибирав\nсаме цю помилку. Ми можемо сказати, що відкрита таблиця це звичайний підсумок\nпоради, яка стоїть першою у результатах пошуку.",[10,299,300,301,92],{},"Якщо ви радше не хочете про це міркувати, наше безкоштовне сканування читає ваш\nживий сайт і каже, які з ваших таблиць відповідають сторонній людині. Воно\nтриває близько 20 секунд і не потребує облікового запису:\n",[212,302,304],{"href":303},"\u002Fsecurity-scanner","просканувати застосунок",[10,306,307,308,312],{},"Коли ви це вимикаєте, стається ще одне. Власний advisor Supabase починає\nповідомляти про таблицю, це попередження\n",[212,309,311],{"href":310},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","RLS disabled in public",", і за місяць\nвоно все ще буде там.",[33,314,316],{"id":315},"як-зрозуміти-чи-коло-справді-зникло","Як зрозуміти, чи коло справді зникло",[10,318,319],{},"Те, що помилка зупинилася, не є перевіркою, бо зупиняють її дві різні речі.",[10,321,322,323,325,326,329],{},"Є ще спосіб, у який допоміжна функція виглядає правильно і далі рекурсує, і\nSupabase це документує: функція security definer обходить правила лише тоді,\nколи це дозволено її власникові. У Supabase власник це ",[21,324,159],{},", який таке\nправо має, тож наведений вище взірець працює. Функція, що належить ролі без\nцього права, або та, що читає таблицю з ",[21,327,328],{},"force row level security",", знову\nпроходить через правило і лишається в колі.",[10,331,332],{},"Дві перевірки, і зробіть обидві:",[10,334,335,338,339,342,343,346,347,350],{},[28,336,337],{},"Запишіть випадки і запустіть їх."," Процедура Supabase це файл ",[21,340,341],{},".sql"," у\n",[21,344,345],{},"supabase\u002Ftests\u002F",", який стверджує дозвіл і відмову для кожної операції, для\nкористувача з входом і для анонімного, запущений через ",[21,348,349],{},"supabase test db",".\nAdmin має бачити всі профілі, учасник свій, стороння людина нічого. Доки це не\nпроходить, ви знаєте тільки те, що помилка зупинилася.",[10,352,353,356,357,361,362,366],{},[28,354,355],{},"А потім запитайте ззовні, без входу."," Це те питання, яке ставить браузер\nвідвідувача, і єдине, що відображає те, що ваш застосунок справді видає.\n",[212,358,360],{"href":359},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Чи може стороння людина прочитати вашу базу","\nпроходить це крок за кроком, а\n",[212,363,365],{"href":364},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Row Level Security може бути увімкненим, а таблиця лишатися публічною","\nохоплює випадок, коли правила є і все одно пропускають усіх.",[33,368,370],{"id":369},"коли-рекурсія-каже-що-схема-хибна","Коли рекурсія каже, що схема хибна",[10,372,373],{},"Іноді кругового питання немає що прибирати, бо дві таблиці справді залежать одна\nвід одної.",[10,375,376,377,380,381,384,385,387,388,390],{},"Посібник Supabase бере спільний доступ за приклад: правило на ",[21,378,379],{},"lists"," звіряє\n",[21,382,383],{},"list_members",", щоб побачити, з ким поділилися списком, а правило на\n",[21,386,383],{}," звіряє ",[21,389,379],{},", щоб побачити, чий він. Правило кожної таблиці\nчитає іншу, і жодна не може піти першою. Той самий помічник це розвʼязує:\nфункція повертає id списків, до яких належить той, хто звертається, і обидва\nправила запитують цю функцію замість того, щоб питати одне одного.",[10,392,393],{},"Сигнал, який варто помітити, це коли вам потрібні три або чотири таких, щоб\nсхема працювала. На цьому етапі належність щоразу перебудовується всередині\nправил, а одна таблиця, яка прямо каже, кому що видно, зазвичай потребує менше\nдогляду, ніж правила, які ви розплутуєте.",[33,395,397],{"id":396},"як-тримати-таблицю-закритою-після-виправлення","Як тримати таблицю закритою після виправлення",[10,399,400,403],{},[28,401,402],{},"Правило, яке ви виправили сьогодні, описує сьогоднішню базу даних."," Наступна\npolicy, наступна таблиця і наступний раз, коли хтось опівночі прибирає помилку,\nстаються вже після того, як ви востаннє дивилися, і жодна з цих подій не змінює\nнічого, що видно на ваших екранах.",[10,405,406],{},[28,407,408,412],{},[212,409,411],{"href":410},"\u002Fpricing","Reeve Monitor"," ставить вашому застосунку ті самі питання знову, за\nрозкладом:",[146,414,415,418,425,428],{},[149,416,417],{},"усі девʼять перевірок щогодини, для трьох застосунків",[149,419,420,421,424],{},"повідомлення, коли результат ",[28,422,423],{},"змінюється",", щоб таблиця, яка відкрилася вночі, не чекала, доки ви помітите",[149,426,427],{},"чи застосунок відповідає, кожні 60 секунд",[149,429,430],{},"щомісячний звіт про побачене",[10,432,433,441],{},[28,434,435,436,440],{},"Якщо ваш застосунок тримає дані у вашому власному проєкті Supabase,\n",[212,437,439],{"href":438},"\u002Fsupabase-backups","Reeve Care"," ще й зберігає копію цієї бази даних."," Правило,\nяке дає сторонній людині читати, це одна проблема. Правило, яке дає їй писати,\nце інша, і жодна перевірка з цієї статті не поверне видалені рядки.",[146,443,444,447,450,453,456],{},[149,445,446],{},"зашифрована копія вашої бази Supabase щоночі, збережена там, куди ваш проєкт не дістане",[149,448,449],{},"кожна копія перевірена, перш ніж її зараховано, підрахунком рядків у кожній таблиці",[149,451,452],{},"відновлення одним кліком, коли воно знадобиться",[149,454,455],{},"ваші завантажені файли теж, щойно ви підключите облікові дані Storage",[149,457,458],{},"усе, що робить Monitor",[33,460,462],{"id":461},"що-зробити-зараз","Що зробити зараз",[464,465,466],"key-takeaways",{},[146,467,468,471,480,486,495],{},[149,469,470],{},"Лишіть Row Level Security увімкненим. Помилка стосується одного правила, а вимкнення правил це зміна всієї таблиці.",[149,472,473,474,476,477,479],{},"Перенесіть перевірку ролі у функцію ",[21,475,155],{}," у схемі, яка не відкрита, із ",[21,478,167],{}," і кожною назвою таблиці, написаною повністю.",[149,481,482,483,485],{},"Спрямуйте policy на функцію, загорнуту як ",[21,484,192],{},", щоб вона виконувалася раз на інструкцію, а не раз на рядок.",[149,487,488,489,491,492,494],{},"Запишіть дозволені та заборонені випадки у ",[21,490,345],{}," і запустіть ",[21,493,349],{},": admin бачить усі профілі, учасник свій, стороння людина нічого.",[149,496,497,498,92],{},"Якщо ви вже вимкнули Row Level Security, щоб зрушити з місця, увімкніть його сьогодні і полагодьте правило як слід. Advisor Supabase повідомлятиме про цю таблицю, доки ви цього не зробите, і ",[212,499,501],{"href":500},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","він належить кожній вашій таблиці",[10,503,504,505,509],{},"Якщо вам потрібен решта списку для щойно запущеного застосунку,\n",[212,506,508],{"href":507},"\u002Fchecklist","10-хвилинний чекліст безпеки"," охоплює це та інші речі, які варто\nзакрити, перш ніж їх хтось знайде.",{"title":23,"searchDepth":511,"depth":511,"links":512},3,[513,515,516,517,518,519,520,521,522],{"id":35,"depth":514,"text":36},2,{"id":65,"depth":514,"text":66},{"id":104,"depth":514,"text":105},{"id":123,"depth":514,"text":124},{"id":218,"depth":514,"text":219},{"id":315,"depth":514,"text":316},{"id":369,"depth":514,"text":370},{"id":396,"depth":514,"text":397},{"id":461,"depth":514,"text":462},"Основи безпеки","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcover-1200x630.png","Замкнена панель таблиці, усередині якої за склом намальовано її власний ключ, і засув упоперек дверей.","\"Infinite recursion detected in policy for relation\" означає, що ваша policy запитала таблицю, яку вона захищає. Ось як розірвати коло.",false,"md",[530,533,536,539,541],{"q":531,"a":532},"Що спричиняє \"infinite recursion detected in policy for relation\"?","Правило на таблиці, яке мусить прочитати цю саму таблицю, перш ніж зможе відповісти. Ваше правило по суті каже \"пропусти цю людину, якщо її рядок у profiles каже, що вона admin\", тож база даних іде читати той рядок у profiles, а для цього треба перевірити правило на profiles, яке відсилає її читати рядок знову. Postgres помічає, що ходить по колу, зупиняється і піднімає помилку 42P17. Те саме стається між двома таблицями, чиї правила читають одне одного.",{"q":534,"a":535},"Чи безпечно використовувати функцію security definer у policy?","Так, за двох умов, які Supabase називає у власному посібнику з Row Level Security. Поставте search_path у порожній рядок і пишіть усередині кожне імʼя таблиці повністю, тобто public.profiles, а не profiles. Без цього хтось може спрямувати некваліфіковане імʼя на власний обʼєкт і виконати його з правами власника функції. І створюйте функцію в схемі, яка не відкрита через API, бо функцію security definer у відкритій схемі можна викликати ззовні з правами того, хто її створив.",{"q":537,"a":538},"Чи варто вимкнути RLS, щоб це полагодити?","Це зупиняє помилку і відкриває таблицю. З вимкненим Row Level Security кожен рядок цієї таблиці може прочитати будь-хто, у кого є ключ, який ваш застосунок віддає браузеру, а цей ключ будь-хто дістане з вашого сайту. Ваш застосунок поводиться однаково в обох випадках, тож потім ніщо не скаже вам, який із двох варіантів ви обрали. Допоміжна функція нижче зупиняє помилку і лишає таблицю закритою.",{"q":105,"a":540},"Бо саме в profiles зазвичай лежить відповідь на питання \"хто ця людина\". Правило, яке по-іншому ставиться до адміністраторів або до учасників команди, мусить знати, ким є той, хто звертається, і цей факт збережено в profiles. Тож правило, що захищає profiles, зрештою читає profiles. Будь-яка таблиця, що тримає роль або належність того, хто звертається, здатна це спричинити, а в застосунку з Lovable, Bolt чи v0 такою таблицею зазвичай є та, що зветься profiles.",{"q":542,"a":543},"Як перевірити, що моя policy справді працює?","Помилку зупиняють дві різні речі, тож сама по собі зникла помилка каже дуже мало. Запишіть дозволені та заборонені випадки у файл .sql у supabase\u002Ftests\u002F і запустіть supabase test db, це процедура, яку Supabase публікує разом із посібником: власник із входом має пройти, а стороння людина має дістати відмову. Потім поставте те саме питання вашій базі ззовні, геть без входу, так само як це робить браузер відвідувача.","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",[546,547,548,549,550,551,552,553],"infinite recursion detected in policy for relation","supabase infinite recursion policy","infinite recursion rls supabase","помилка рекурсії policy supabase","42P17 supabase","нескінченний цикл policy rls","supabase profiles policy рекурсія","помилка policy роль supabase",{},true,"Infinite recursion detected in policy","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","2026-10-08",{"title":5,"description":526},"blog\u002Finfinite-recursion-in-policy-for-relation",[562,563,564],"\"Infinite recursion detected in policy for relation\" це помилка Postgres 42P17. Правило Row Level Security на таблиці пішло поставити питання цій самій таблиці, і це питання не має кінця.","Це не ознака того, що Row Level Security не підходив вашому застосунку. Це ознака того, що одне правило запитало по колу.","Невелика допоміжна функція читає таблицю поза правилами і розриває коло. Вимкнення Row Level Security на цій таблиці теж зупиняє помилку, віддаючи кожен її рядок усім, хто має ключ, що їде всередині вашого застосунку.","BUP0OslUb0FIWBz7yv3ghp45vMetKPZebzWIqkd9kDE",[567,573,579,585,586,592,598,604,610,616,622,628,634,640,647,653,659,664,670,676,682,688,694,700,706,712,718,724,730,736,742,748,754,759,764,770,776,782,788,794,800,806,812,818,824,830,836,841,847,853,859,865,871,877,882,887,893,899,904,909,915],{"path":568,"title":569,"description":570,"published":571,"category":523,"image":572,"draft":527},"\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":574,"title":575,"description":576,"published":577,"category":523,"image":578,"draft":527},"\u002Fblog\u002Fbase44-security-scan","Сканування безпеки Base44: те, що бачить лише воно","Сканування безпеки Base44 перевіряє сім видів проблем зсередини. Ось половина, яку читає тільки воно, і половина, на яку воно ніколи не дивиться.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":580,"title":581,"description":582,"published":583,"category":523,"image":584,"draft":527},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Ваш API-ключ витік. Порядок дій","API-ключ витік, і ви не знаєте, що робити першим. Не кожен ключ у вашому фронтенді є витоком, а порядок важить більше за швидкість.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":557,"title":5,"description":526,"published":558,"category":523,"image":544,"draft":527},{"path":587,"title":588,"description":589,"published":590,"category":523,"image":591,"draft":527},"\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":593,"title":594,"description":595,"published":596,"category":523,"image":597,"draft":527},"\u002Fblog\u002Fis-base44-safe","Чи безпечний Base44? Дані 5 442 застосунків","Чи безпечний Base44? Ми прогнали дев’ять перевірок на 5 442 робочих застосунках Base44. Майже всі отримали B з причин, яких власник ніколи не обирав.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":599,"title":600,"description":601,"published":602,"category":523,"image":603,"draft":527},"\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":605,"title":606,"description":607,"published":608,"category":523,"image":609,"draft":527},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Чи відкритий ваш файл .env? Дванадцять шляхів для перевірки","Чи відкритий ваш файл .env на вашому власному вебсервері? Дванадцять адрес скажуть це за хвилину, а влучання означає, що все в ньому вже публічне.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":611,"title":612,"description":613,"published":614,"category":523,"image":615,"draft":527},"\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":617,"title":618,"description":619,"published":620,"category":523,"image":621,"draft":527},"\u002Fblog\u002Fis-bolt-safe","Чи безпечний Bolt? Що показали 1 123 застосунки Bolt","Чи безпечний Bolt? Ми прогнали 1 123 живі застосунки Bolt через дев’ять перевірок. Хостинг був чистим. Знахідки: ключі й відкриті таблиці в самих застосунках.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":623,"title":624,"description":625,"published":626,"category":523,"image":627,"draft":527},"\u002Fblog\u002Fis-supabase-down-or-your-app","Supabase не працює чи проблема у вашому застосунку? Як розрізнити","Supabase не працює чи зламався ваш застосунок? Пауза, повна база й ваша власна помилка виглядають однаково. Чотири перевірки їх розрізняють.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":629,"title":630,"description":631,"published":632,"category":523,"image":633,"draft":527},"\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":635,"title":636,"description":637,"published":638,"category":523,"image":639,"draft":527},"\u002Fblog\u002Fsupabase-free-plan-limits","Ліміти безкоштовного тарифу Supabase і що стається на кожному","Ліміти безкоштовного тарифу Supabase: 500 МБ бази, 5 ГБ egress і жодних резервних копій. Що стається на кожній межі і що змінює Pro за $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":641,"title":642,"description":643,"published":644,"category":645,"image":646,"draft":527},"\u002Fblog\u002Ftest-your-supabase-backup","Перевірте резервну копію Supabase до того, як вона знадобиться","Як перевірити резервну копію Supabase: відновити в тестовий проєкт, порахувати рядки, увійти й знайти рядок, якого бракує обрізаному файлу.","2026-09-28","Backups","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":648,"title":649,"description":650,"published":651,"category":645,"image":652,"draft":527},"\u002Fblog\u002Fsupabase-backup-github-action","Безкоштовна резервна копія Supabase через GitHub Action і підступ","Резервна копія Supabase через GitHub Action безкоштовна й годиться багатьом застосункам. Робочий процес, потрібний рядок підключення та egress.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":654,"title":655,"description":656,"published":657,"category":645,"image":658,"draft":527},"\u002Fblog\u002Fdownload-your-supabase-backup","Чому ви не можете завантажити резервну копію Supabase","Завантажити резервну копію Supabase на сучасному проєкті не вийде: щоденна копія там фізична. Як це перевірити і як тримати власну копію.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":660,"title":661,"description":662,"published":657,"category":523,"image":663,"draft":527},"\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":665,"title":666,"description":667,"published":668,"category":523,"image":669,"draft":527},"\u002Fblog\u002Fopen-api-endpoint-exposed","Чи є відкритий API-ендпоінт проблемою безпеки? Читайте JSON","Ваше сканування позначило відкритий API-ендпоінт. Чи це важливо, залежить від того, що повернулося, і більшість знайдених належали платформі.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":671,"title":672,"description":673,"published":674,"category":523,"image":675,"draft":527},"\u002Fblog\u002Flovable-security-scan","Сканування безпеки Lovable: чого воно не доведе","Сканування безпеки Lovable: що перевіряють Quick scan і Deep scan, коли запускається кожне, і єдине, чого не доведе жодне сканування зсередини.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":677,"title":678,"description":679,"published":680,"category":645,"image":681,"draft":527},"\u002Fblog\u002Fsupabase-backup-auth-users","Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":683,"title":684,"description":685,"published":686,"category":523,"image":687,"draft":527},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":689,"title":690,"description":691,"published":692,"category":523,"image":693,"draft":527},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":695,"title":696,"description":697,"published":698,"category":523,"image":699,"draft":527},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":701,"title":702,"description":703,"published":704,"category":523,"image":705,"draft":527},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":707,"title":708,"description":709,"published":710,"category":523,"image":711,"draft":527},"\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":713,"title":714,"description":715,"published":716,"category":523,"image":717,"draft":527},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":719,"title":720,"description":721,"published":722,"category":523,"image":723,"draft":527},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":725,"title":726,"description":727,"published":728,"category":523,"image":729,"draft":527},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":731,"title":732,"description":733,"published":734,"category":645,"image":735,"draft":527},"\u002Fblog\u002Fsupabase-storage-backup","Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":737,"title":738,"description":739,"published":740,"category":645,"image":741,"draft":527},"\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":743,"title":744,"description":745,"published":746,"category":645,"image":747,"draft":527},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":749,"title":750,"description":751,"published":752,"category":523,"image":753,"draft":527},"\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":500,"title":755,"description":756,"published":757,"category":523,"image":758,"draft":527},"Увімкніть Row Level Security на кожній таблиці Supabase і перевірте","Row Level Security у Supabase без політики закриває таблицю повністю. Політика без увімкненого перемикача не робить нічого. Ось SQL, і ось перевірка.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":310,"title":760,"description":761,"published":762,"category":523,"image":763,"draft":527},"Supabase \"RLS disabled in public\": чого не бачить попередження","Supabase позначає \"RLS disabled in public\" як помилку. Про політику читання, яка лишає вашу таблицю так само відкритою, він не каже нічого.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":765,"title":766,"description":767,"published":768,"category":523,"image":769,"draft":527},"\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":771,"title":772,"description":773,"published":774,"category":523,"image":775,"draft":527},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Десять інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":777,"title":778,"description":779,"published":780,"category":523,"image":781,"draft":527},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: п’ять перевірок, які зробите самі","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":783,"title":784,"description":785,"published":786,"category":523,"image":787,"draft":527},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":789,"title":790,"description":791,"published":792,"category":523,"image":793,"draft":527},"\u002Fblog\u002Fmissing-security-headers","Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":795,"title":796,"description":797,"published":798,"category":523,"image":799,"draft":527},"\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":801,"title":802,"description":803,"published":804,"category":523,"image":805,"draft":527},"\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":807,"title":808,"description":809,"published":810,"category":645,"image":811,"draft":527},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":813,"title":814,"description":815,"published":816,"category":523,"image":817,"draft":527},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":819,"title":820,"description":821,"published":822,"category":645,"image":823,"draft":527},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":825,"title":826,"description":827,"published":828,"category":523,"image":829,"draft":527},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":831,"title":832,"description":833,"published":834,"category":523,"image":835,"draft":527},"\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":214,"title":837,"description":838,"published":839,"category":523,"image":840,"draft":527},"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":842,"title":843,"description":844,"published":845,"category":523,"image":846,"draft":527},"\u002Fblog\u002Fcors-wildcard-security-risk","Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":848,"title":849,"description":850,"published":851,"category":645,"image":852,"draft":527},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Branching у Supabase це не бекап. Він іде тільки вперед.","Чому branching у Supabase це не бекап: гілка стартує без ваших даних, а мердж переносить саму лише схему. Для чого він потрібен і що брати замість нього.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":854,"title":855,"description":856,"published":857,"category":645,"image":858,"draft":527},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":860,"title":861,"description":862,"published":863,"category":523,"image":864,"draft":527},"\u002Fblog\u002Fsupabase-storage-bucket-public","Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":866,"title":867,"description":868,"published":869,"category":523,"image":870,"draft":527},"\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":872,"title":873,"description":874,"published":875,"category":645,"image":876,"draft":527},"\u002Fblog\u002Fai-agent-deleted-my-database","ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":359,"title":878,"description":879,"published":880,"category":523,"image":881,"draft":527},"Чи може будь-хто прочитати вашу базу Supabase? 3 680 застосунків","Чи може будь-хто прочитати вашу базу даних Supabase без входу? Ми просканували 30 998 живих застосунків, зроблених ШІ-білдерами, і виміряли, як часто так.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":883,"title":884,"description":885,"published":880,"category":523,"image":886,"draft":527},"\u002Fblog\u002Fsource-maps-exposed-in-production","Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":888,"title":889,"description":890,"published":891,"category":523,"image":892,"draft":527},"\u002Fblog\u002Fsupabase-new-api-keys","Нові API-ключі Supabase: який із них безпечний у застосунку?","Supabase замінив anon і service_role публічними та секретними ключами. Який із них має бути у вашому застосунку, а який не має бути ніколи?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":894,"title":895,"description":896,"published":897,"category":645,"image":898,"draft":527},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":364,"title":900,"description":901,"published":902,"category":523,"image":903,"draft":527},"Supabase Row Level Security увімкнено. Таблиця досі публічна.","Увімкнути Supabase Row Level Security не означає захистити таблицю. Захищають політики, а та, що полагодила застосунок, часто впускає всіх.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":905,"title":906,"description":907,"published":902,"category":645,"image":908,"draft":527},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":910,"title":911,"description":912,"published":913,"category":645,"image":914,"draft":527},"\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":916,"title":917,"description":918,"published":913,"category":523,"image":919,"draft":527},"\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",1791705965419]