[{"data":1,"prerenderedAt":1144},["ShallowReactive",2],{"blog-uk-database-error-deleting-user":3,"blog-index-uk":618},{"id":4,"title":5,"body":6,"category":576,"cover":577,"coverAlt":578,"description":579,"draft":580,"extension":581,"faq":582,"image":597,"keywords":598,"meta":606,"navigation":607,"ogTitle":608,"path":609,"published":610,"seo":611,"stem":612,"tldr":613,"updated":610,"__hash__":617},"blog_uk\u002Fblog\u002Fdatabase-error-deleting-user.md","\"Database error deleting user\" у Supabase і що зникає разом",{"type":7,"value":8,"toc":562},"minimark",[9,13,24,27,34,39,42,59,65,69,72,75,98,101,120,124,131,134,140,155,166,181,184,192,206,210,213,219,222,225,231,234,238,241,305,321,324,330,333,347,352,356,365,378,392,397,401,404,432,443,450,454,457,473,476,484,488,494,502,524,528,554],[10,11,12],"p",{},"Ви відкриваєте Authentication → Users у панелі Supabase і видаляєте обліковий\nзапис. Можливо, людина сама попросила її видалити, можливо, це тестовий запис,\nякий ви створили минулого тижня. Панель відповідає:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Failed to delete user: Database error deleting user\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Запис досі в списку. Застосунок, який ви зробили в Lovable, Bolt, v0, Cursor,\nClaude Code чи Replit, весь цей час працював, а речення не називає ні таблиці,\nні причини.",[10,28,29,30,33],{},"Перша відповідь, яку ви знайдете, це один рядок SQL: допишіть\n",[21,31,32],{},"on delete cascade"," до того, що заважає. Це працює. А ще це вирішує, для кожного\nзапису, видаленого відтоді, які інші рядки зникнуть разом із ним, і більше вас\nпро це ніхто не спитає. Тож спершу прочитайте справжню помилку, а потім ухваліть\nце рішення окремо для кожної таблиці.",[35,36,38],"h2",{"id":37},"що-означає-database-error-deleting-user-у-supabase","Що означає \"Database error deleting user\" у Supabase?",[10,40,41],{},"Ваша база відмовилася видаляти, і Supabase усе скасував, тож обліковий запис\nтакий самий, як був.",[10,43,44,45,48,49,52,53,58],{},"Видалення користувача це робота Supabase Auth, сервісу, що стоїть за входом у\nваш застосунок. У вихідному коді Auth видалення відбувається в одній транзакції,\nгрупі змін, які проходять або всі, або жодна, і її головний крок прибирає рядок\nлюдини з ",[21,46,47],{},"auth.users",". Якщо щось у вашій базі проти, транзакцію відкочують, і\nAuth відповідає цим одним реченням. Supabase наводить його як HTTP 500 з кодом\n",[21,50,51],{},"unexpected_failure",", поруч із близнюком з реєстрації,\n",[54,55,57],"a",{"href":56},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\"",".",[10,60,61,62,64],{},"Уявіть свою базу як клуб. ",[21,63,47],{}," це список членів, і в кожного члена є\nномер: його id користувача. Ваші інші книги переписують цей номер у свої рядки,\nчи то профіль, замовлення, допис або коментар. Викреслити когось зі списку\nсправа одного рядка. Але кожна інша книга досі тримає номер, і поки ніхто не\nзаписав, що робити з тими рядками, секретар клубу відмовляє.",[35,66,68],{"id":67},"де-лежить-справжня-помилка","Де лежить справжня помилка?",[10,70,71],{},"У логах Postgres вашого проєкту, у ту мить, коли видалення не вдалося.",[10,73,74],{},"Нотатка Supabase з troubleshooting про помилки керування користувачами показує\nдорогу. Спробуйте видалити один раз і запишіть час. Потім у панелі:",[76,77,78,91],"ol",{},[79,80,81,82,86,87,90],"li",{},"Відкрийте ",[83,84,85],"strong",{},"Logs"," і прочитайте логи ",[83,88,89],{},"Auth"," на цей час. Запис там це власний\nзвіт Auth про невдале видалення.",[79,92,93,94,97],{},"Відкрийте логи ",[83,95,96],{},"Postgres"," на той самий час. Цей рядок і є справжня помилка,\nі він називає таблицю, правило або дозвіл.",[10,99,100],{},"Та сама нотатка називає три причини, і рядок логу скаже, яка у вас:",[102,103,104,110,115],"ul",{},[79,105,106,107,109],{},"тригер на таблиці ",[21,108,47],{},", що падає",[79,111,112,113],{},"обмеження, яке не виконується, а при видаленні це означає foreign key в іншій\nтаблиці, що вказує на ",[21,114,47],{},[79,116,117,118],{},"Prisma, який, за нотаткою, може зламати дозволи на ",[21,119,47],{},[35,121,123],{"id":122},"таблиця-що-досі-вказує-на-користувача","Таблиця, що досі вказує на користувача",[10,125,126,127,130],{},"Якщо в рядку Postgres написано ",[21,128,129],{},"violates foreign key constraint",", то рядок в\nодній із ваших таблиць досі тримає id цього користувача, і Postgres не видаляє\nлюдину, на яку ще щось вказує.",[10,132,133],{},"Нотатка Supabase показує, як це виглядає:",[14,135,138],{"className":136,"code":137,"language":19},[17],"ERROR:  23503: update or delete on table \"users\" violates foreign key constraint \"profiles_id_fkey\" on table \"profiles\"\nDETAIL:  Key (id)=(7428a53c-75b7-4531-9ae9-1567d9c4ac0a) is still referenced from table \"profiles\".\n",[21,139,137],{"__ignoreMap":23},[10,141,142,143,146,147,150,151,154],{},"Foreign key це правило на колонці, яке каже, що кожне значення в ній мусить\nіснувати в іншій таблиці. Тут правило зветься ",[21,144,145],{},"profiles_id_fkey",", воно стоїть на\nвашій таблиці ",[21,148,149],{},"profiles",", а рядок ",[21,152,153],{},"Key"," це id користувача, якого ви намагалися\nвидалити. У клубі це рядок у книзі профілів із номером члена, і секретар, який\nне викреслює його, поки той рядок на місці.",[10,156,157,158,161,162,58],{},"Те саме правило відмовляє й з іншого боку. Новий рядок, що називає користувача,\nякого не існує, повертається як\n",[21,159,160],{},"insert or update on table … violates foreign key constraint",", і\n",[54,163,165],{"href":164},"\u002Fblog\u002Fviolates-foreign-key-constraint","цьому повідомленню присвячена окрема стаття",[10,167,168,169,172,173,176,177,180],{},"Відмова і є поведінкою за замовчуванням. Foreign key, створений без нічого після\n",[21,170,171],{},"references auth.users",", отримує поведінку, яку Postgres називає ",[21,174,175],{},"no action",", і\nпосібник Supabase про каскадні видалення каже це прямо: ",[21,178,179],{},"NO ACTION"," діє за\nзамовчуванням, якщо ви нічого не вказали. Таблиця, яку ваш білдер створив саме\nтак, працює бездоганно до першого разу, коли когось видаляють.",[10,182,183],{},"Щоб побачити кожну таблицю, що вказує на ваших користувачів, і що кожна робить\nпри видаленні, виконайте це в SQL Editor:",[14,185,190],{"className":186,"code":188,"language":189,"meta":23},[187],"language-sql","select conrelid::regclass as table_name,\n       conname as rule,\n       case confdeltype\n         when 'c' then 'cascade'\n         when 'n' then 'set null'\n         when 'd' then 'set default'\n         when 'r' then 'restrict'\n         else 'no action'\n       end as on_delete\nfrom pg_constraint\nwhere contype = 'f'\n  and confrelid = 'auth.users'::regclass\n  and connamespace \u003C> 'auth'::regnamespace;\n","sql",[21,191,188],{"__ignoreMap":23},[10,193,194,195,198,199,201,202,205],{},"Запит лише читає власний каталог Postgres і нічого не змінює. Останній рядок\nвідкидає службові таблиці Supabase у схемі ",[21,196,197],{},"auth",". Кожен рядок із ",[21,200,175],{},"\nабо ",[21,203,204],{},"restrict"," це таблиця, яка відмовить у видаленні щоразу, коли в ній є рядок\nцього користувача.",[35,207,209],{"id":208},"що-видаляє-on-delete-cascade","Що видаляє on delete cascade?",[10,211,212],{},"Кожен рядок, що вказує на користувача, потім кожен рядок, що вказує на ті, при\nкожному видаленні відтоді.",[10,214,215,216,218],{},"Це виправлення, яке вам дають першим, і посібник Supabase з керування\nкористувачами застосовує його до таблиці профілів: там радять вказати\n",[21,217,32],{}," у посиланні. Для профілю це правильно. Профіль описує людину\nй більше нічого, тож він має піти, коли йде вона.",[10,220,221],{},"Клопіт починається, коли ті самі слова потрапляють на кожну таблицю. Посібник\nSupabase про каскад описує поведінку прямо: коли з батьківської таблиці\nвидаляють рядок, усі повʼязані рядки в дочірніх таблицях теж видаляються. І це\nйде далі вниз. У власному прикладі посібника одне видалення у верхній таблиці\nспорожнює дві таблиці під нею.",[10,223,224],{},"У клубі каскад велить секретареві вирвати кожен рядок із номером члена, а потім\nкожен рядок у будь-якій іншій книзі, що вказував на вирваний рядок. Уявіть\nкористувача, який писав дописи, а на ці дописи вказують коментарі інших людей. З\nкаскадом на обох таблицях видалення цього одного користувача прибирає його\nдописи й коментарі всіх інших під ними.",[226,227],"diagram",{"alt":228,"caption":229,"src":230},"Три книги в ряд, зʼєднані стрілками. У списку членів ліворуч один рядок закреслено. У середній книзі вирвано два рядки з жетоном цього члена. У правій книзі вирвано й рядки, що вказували на ті два, і більшість із них має жетони інших членів інших кольорів.","Каскад іде за кожним правилом, що вказує на видалений рядок, а потім за кожним правилом, що вказує на ті. Остання книга втрачає рядки, які належали іншим людям.","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fthe-chain-1600x700.png",[10,232,233],{},"Ніщо не скаже вам, що зникло разом із ним. Auth відповідає на успішне видалення\nпорожньою відповіддю, панель показує на один запис менше, а рядки, що зникли в\nту саму мить, просто бракуватиме наступного разу, коли їх хтось шукатиме.",[35,235,237],{"id":236},"що-зберігає-кожна-таблиця","Що зберігає кожна таблиця",[10,239,240],{},"Вирішуйте для кожної таблиці окремо, бо кожна тримає щось своє про людину, яка\nпішла.",[242,243,244,262],"table",{},[245,246,247],"thead",{},[248,249,250,254,259],"tr",{},[251,252,253],"th",{},"Що тримає таблиця",[251,255,256],{},[21,257,258],{},"on delete",[251,260,261],{},"Коли користувача видалено",[263,264,265,279,292],"tbody",{},[248,266,267,271,276],{},[268,269,270],"td",{},"Лише саму людину: профіль, її налаштування",[268,272,273],{},[21,274,275],{},"cascade",[268,277,278],{},"Рядки йдуть разом із нею",[248,280,281,284,289],{},[268,282,283],{},"Те, що досі потрібне іншим: коментар у чужій гілці, запис про оплату",[268,285,286],{},[21,287,288],{},"set null",[268,290,291],{},"Рядки лишаються, колонка власника порожня",[248,293,294,297,302],{},[268,295,296],{},"Усе, чим ви хочете спершу зайнятися власноруч",[268,298,299,301],{},[21,300,175],{}," (за замовчуванням)",[268,303,304],{},"Видалення відхиляють, поки ці рядки є",[10,306,307,309,310,316,317,320],{},[21,308,288],{}," має дві умови. Колонка мусить приймати порожні значення, інакше\nвидалення знову впаде з власним повідомленням,\n",[54,311,313],{"href":312},"\u002Fblog\u002Fnull-value-violates-not-null-constraint",[21,314,315],{},"null value in column … violates not-null constraint",". А політика виду\n",[21,318,319],{},"user_id = auth.uid()"," більше ніколи нікому не покаже цей рядок, бо в SQL ніщо\nне дорівнює порожньому значенню. Рядок зберігається, а ваш застосунок перестає\nйого будь-кому показувати.",[10,322,323],{},"Змінити правило означає прибрати його й додати знову з новою поведінкою, як і\nрадить нотатка Supabase:",[14,325,328],{"className":326,"code":327,"language":189,"meta":23},[187],"alter table public.profiles\n  drop constraint profiles_id_fkey,\n  add constraint profiles_id_fkey\n    foreign key (id) references auth.users (id) on delete cascade;\n",[21,329,327],{"__ignoreMap":23},[10,331,332],{},"Візьміть назву правила, яку вивів запит вище, і свої таблицю та колонку.",[10,334,335,336,339,340,343,344,346],{},"Є ще один шлях, і він зберігає всі рядки. Supabase Auth уміє мʼяко видалити\nобліковий запис: ",[21,337,338],{},"auth.admin.deleteUser()"," приймає опцію ",[21,341,342],{},"shouldSoftDelete",", і з\nнею Auth залишає рядок в ",[21,345,47],{},", позначає його видаленим, перемішує email і\nтелефон, стирає пароль і метадані та завершує сесії. Нічого не прибрано, тож\nжоден foreign key не спрацьовує. Це виконується на сервері з вашим секретним\nключем, ніколи в браузері.",[226,348],{"alt":349,"caption":350,"src":351},"Той самий видалений член клубу, намальований тричі, по смузі для no action, cascade і set null. У першій барʼєр зупиняє видалення, і лишаються обидва рядки: член клубу й той, що на нього вказує. У другій рядок, що вказує на члена, вирвано разом із ним. У третій цей рядок лишається, з порожнім пунктирним місцем там, де був жетон члена.","Те саме видалення за трьох правил. Перше відмовляє й нічого не змінює, друге забирає рядок, що вказує на члена, а третє лишає цей рядок із порожнім місцем.","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fthree-outcomes-1600x760.png",[35,353,355],{"id":354},"тригер-що-не-дістає-до-вашої-таблиці","Тригер, що не дістає до вашої таблиці",[10,357,126,358,361,362,364],{},[21,359,360],{},"permission denied for table",", то під час\nвидалення спрацював тригер на ",[21,363,47],{}," і спробував торкнутися таблиці, куди\nйому не можна.",[10,366,367,368,371,372,374,375,58],{},"Роль, від імені якої працює Supabase Auth, ",[21,369,370],{},"supabase_auth_admin",", має лише ті\nдозволи, яких потребує її власна робота. Нотатка Supabase пояснює це так: коли\nтригер, який виконує ",[21,373,370],{},", діє поза схемою auth, виникає\nпомилка дозволів. Тригер, що прибирає після видаленого запису, скажімо пише у\nвашу власну таблицю журналу, падає саме так, якщо його функцію не створено з\n",[21,376,377],{},"security definer",[10,379,380,381,383,384,387,388,391],{},"Виправлення те саме, що й для реєстрації: функція з ",[21,382,377],{},", створена\nроллю ",[21,385,386],{},"postgres",", яка робить одну вузьку річ.\n",[54,389,390],{"href":56},"Версія цієї помилки для реєстрації","\nрозбирає її рядок за рядком, разом із порожнім search path, який робить її\nбезпечною.",[10,393,394,395,58],{},"Якщо ваш застосунок використовує Prisma, спершу прочитайте третю причину в\nнотатці Supabase, бо вона називає Prisma одним зі способів зламати дозволи на\n",[21,396,47],{},[35,398,400],{"id":399},"що-стається-з-файлами-які-людина-завантажила","Що стається з файлами, які людина завантажила?",[10,402,403],{},"У сучасному проєкті видалення проходить, а файли лишаються там, де були.",[10,405,406,407,410,411,414,415,417,418,421,422,425,426,428,429,431],{},"Посібник Supabase з керування користувачами досі попереджає, що не можна\nвидалити користувача, якому належать обʼєкти в Supabase Storage. Це було\nправдою, поки ",[21,408,409],{},"storage.objects",", таблиця, де Storage тримає рядок для кожного\nфайла, мала foreign key під назвою ",[21,412,413],{},"objects_owner_fkey"," на ",[21,416,47],{},". Storage\nвідтоді прибрав цей ключ у власних міграціях схеми\n(",[21,419,420],{},"0017-drop-owner-foreign-key.sql","), і його посібник про власність файлів тепер\nкаже, що власник записаний у колонці ",[21,423,424],{},"owner_id",". Якщо запит вище показує\n",[21,427,409],{}," з ",[21,430,413],{},", у вашому проєкті ще стоїть старе\nправило, і попередження посібника стосується вас.",[10,433,434,435,438,439,58],{},"Інакше кожен файл, який людина завантажила, лишається у своєму бакеті після її\nвідходу. У клубі пальта висять на гачках із жетоном, якого вже ні в кого немає.\nПолітика виду ",[21,436,437],{},"owner_id = auth.uid()::text"," більше ніколи їх не знайде, а файл у\nпублічному бакеті й далі віддається кожному, хто має посилання. Чи може стороння\nлюдина побачити список файлів у вашому бакеті, це одна з перевірок\n",[54,440,442],{"href":441},"\u002Fsecurity-scanner","безкоштовного сканування Reeve",[10,444,445,446,58],{},"Щоб прибрати їх, ідіть через сам Storage, зі сторінки Storage у панелі або через\nAPI Storage. Пряме видалення через SQL з його таблиць відхиляється, і Storage\nпояснює чому: \"Direct deletion from storage tables is not allowed. Use the\nStorage API instead.\" Що копія бази тримає з цих файлів, а що лишає поза собою,\nописано в ",[54,447,449],{"href":448},"\u002Fblog\u002Fsupabase-storage-backup","резервній копії Supabase Storage",[35,451,453],{"id":452},"зробіть-копію-перш-ніж-міняти-foreign-key","Зробіть копію, перш ніж міняти foreign key",[10,455,456],{},"У Postgres немає кошика, а каскад прибирає рядки з таблиць, на які ви навіть не\nдивилися.",[10,458,459,460,462,463,467,468,472],{},"Те, що змінює каскад чи ",[21,461,288],{},", остаточне, щойно видалення вдалося, і\nєдиний шлях назад це копія, зроблена раніше. Безкоштовний план Supabase не\nтримає жодних бекапів. Pro тримає 7 днів щоденних копій, Team 14, а Enterprise до\n30, і кожна з них живе в тому самому проєкті Supabase.\n",[54,464,466],{"href":465},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Скопіювати базу самостійно","\nможна кількома командами, а\n",[54,469,471],{"href":470},"\u002Fblog\u002Fsupabase-backup-auth-users","копія, що містить ваших користувачів",",\nпотребує третьої з трьох команд, які публікує Supabase.",[10,474,475],{},"Потім перевірте нові правила на тестовому записі, перш ніж на справжньому.\nСтворіть запис, дайте йому по рядку в кожній таблиці зі списку запиту, видаліть\nйого й подивіться, що лишилося в кожній таблиці.",[10,477,478,479,483],{},"Якщо вам спокійніше, коли ця копія вже існує до того, як хтось натисне видалити,\nсаме для цього є ",[54,480,482],{"href":481},"\u002Fsupabase-backups","бекапи Supabase"," від Reeve.",[35,485,487],{"id":486},"шлях-назад-коли-видалення-забрало-більше-ніж-ви-хотіли","Шлях назад, коли видалення забрало більше, ніж ви хотіли",[10,489,490,493],{},[83,491,492],{},"Каскад нічого не повідомляє про те, що прибрав."," Ви дізнаєтеся, коли хтось\nспитає, куди поділися його коментарі.",[10,495,496],{},[83,497,498,501],{},[54,499,500],{"href":481},"Reeve Care"," тримає копію вашої бази Supabase з часу до\nвидалення:",[102,503,504,507,510,513,516],{},[79,505,506],{},"зашифрована копія за розкладом, у власному сховищі Reeve в ЄС, поза вашим обліковим записом Supabase",[79,508,509],{},"кожна копія перевірена, перш ніж її зарахують, підрахунком рядків у кожній таблиці",[79,511,512],{},"відновлення в один клік, яке зберігає те, що є зараз, перш ніж замінити",[79,514,515],{},"ваші завантажені файли теж, щойно ви приєднаєте доступ до Storage",[79,517,518,519,523],{},"усе, що робить ",[54,520,522],{"href":521},"\u002Fwebsite-monitoring","Reeve Monitor",": усі девʼять перевірок вашого робочого застосунку щогодини й перевірка доступності кожні 60 секунд",[35,525,527],{"id":526},"що-зробити-сьогодні","Що зробити сьогодні",[529,530,531],"key-takeaways",{},[102,532,533,536,539,548,551],{},[79,534,535],{},"Спробуйте видалити один раз, запишіть час і прочитайте рядок логу Postgres з тієї миті, перш ніж щось міняти.",[79,537,538],{},"Якщо він називає foreign key, виконайте запит вище, щоб побачити кожну таблицю, що вказує на ваших користувачів, і що кожна робить при видаленні.",[79,540,541,542,544,545,547],{},"Вирішуйте для кожної таблиці: ",[21,543,275],{}," для рядків, що описують лише саму людину, ",[21,546,288],{}," для рядків, потрібних іншим, поведінка за замовчуванням для всього, що ви хочете прибрати власноруч.",[79,549,550],{},"Зробіть копію бази, перш ніж міняти будь-яке з цих правил, і спершу перевірте нові правила на тестовому записі.",[79,552,553],{},"Приберіть і файли людини через Storage. У сучасному проєкті обліковий запис іде, а файли лишаються.",[10,555,556,557,561],{},"Якщо рядки вже зникли далі, ніж ви хотіли,\n",[54,558,560],{"href":559},"\u002Fblog\u002Fai-agent-deleted-my-database","що можна повернути після видалення","\nпояснює, де шукати й у якому порядку.",{"title":23,"searchDepth":563,"depth":563,"links":564},3,[565,567,568,569,570,571,572,573,574,575],{"id":37,"depth":566,"text":38},2,{"id":67,"depth":566,"text":68},{"id":122,"depth":566,"text":123},{"id":208,"depth":566,"text":209},{"id":236,"depth":566,"text":237},{"id":354,"depth":566,"text":355},{"id":399,"depth":566,"text":400},{"id":452,"depth":566,"text":453},{"id":486,"depth":566,"text":487},{"id":526,"depth":566,"text":527},"Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcover-1200x630.png","Список членів клубу з одним закресленим рядком, а за ним ще дві книги, з яких вирвано рядки з тим самим жетоном.","\"Database error deleting user\" у Supabase: ваша база відмовилася видаляти. Причина в логах, а виправлення вирішує, що ще буде видалено.",false,"md",[583,585,588,591,594],{"q":38,"a":584},"Це означає, що Supabase Auth спробував прибрати рядок людини з auth.users, щось у вашій базі відмовило, і все видалення скасовано. Обліковий запис такий самий, як був. Повідомлення не називає жодної таблиці, а рядок, який її називає, лежить у логах Postgres вашого проєкту в ту саму мить.",{"q":586,"a":587},"Чи варто додати on delete cascade, щоб це виправити?","На таблиці, яка описує лише саму людину, як таблиця профілів, так, і власний посібник Supabase робить саме це. На таблиці з тим, що досі потрібне іншим, як коментарі чи замовлення, спершу вирішіть. Cascade видаляє кожен рядок, що вказує на користувача, і кожен рядок, що вказує на ті, при кожному видаленні відтоді, і ніщо не повідомляє, що саме зникло.",{"q":589,"a":590},"Чи можна видалити користувача й зберегти його рядки?","Так, двома способами. Поставте foreign key на on delete set null, і рядки залишаться з порожньою колонкою власника, для чого ця колонка має приймати порожні значення. Або викличте auth.admin.deleteUser() із сервера з опцією shouldSoftDelete: Supabase Auth залишає рядок, позначає його видаленим, перемішує email і телефон та стирає пароль, тож нічого з того, що на нього вказує, не зачеплено.",{"q":592,"a":593},"Чому Supabase каже, що не можна видалити користувача, який завантажував файли?","Його посібник з керування користувачами досі так каже, і це було правдою, поки storage.objects мала foreign key під назвою objects_owner_fkey на auth.users. Supabase Storage відтоді прибрав цей ключ у власних міграціях схеми. У сучасному проєкті видалення проходить, а файли лишаються у своєму бакеті з owner_id, якого вже немає в жодного користувача.",{"q":595,"a":596},"Чи видалення користувача виводить його з системи?","Не одразу. За посібником Supabase, уже виданий токен доступу лишається дійсним, доки не спливе, навіть після видалення облікового запису. Видалення користувача прибирає його сесії, тож застосунок не отримає нового токена, але той, що вже на руках, працює до свого часу спливу.","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",[599,600,601,602,603,604,605],"database error deleting user supabase","database error deleting user","failed to delete user database error deleting user","supabase видалити користувача foreign key","supabase on delete cascade auth users","supabase не видаляється користувач storage","update or delete on table users violates foreign key constraint",{},true,"\"Database error deleting user\" у Supabase","\u002Fblog\u002Fdatabase-error-deleting-user","2026-10-30",{"title":5,"description":579},"blog\u002Fdatabase-error-deleting-user",[614,615,616],"\"Database error deleting user\" у Supabase означає, що видалення дійшло до вашої бази й отримало відмову, тож нічого не видалено. Рядок із причиною лежить у ваших логах Postgres, і сама нотатка Supabase з troubleshooting відправляє вас саме туди.","Якщо в цьому рядку сказано, що порушено foreign key, то рядок в одній із ваших таблиць досі тримає id користувача. Postgres не видаляє людину, поки на неї ще щось вказує, хіба що ви сказали йому, що робити з тими рядками.","Перша відповідь, яку ви знайдете, це on delete cascade. Вона видаляє кожен рядок, що вказує на користувача, і кожен рядок, що вказує на ті, при кожному видаленні відтоді. Вирішуйте для кожної таблиці окремо й зробіть копію, перш ніж міняти правило.","a3cufDuqvVmwTCDvY4e4RHcLjcq6ohZ8TaXJlobKrjI",[619,626,632,637,642,648,654,660,666,672,678,679,685,691,697,703,709,715,721,727,733,739,745,751,757,763,769,774,780,786,792,798,804,810,816,822,828,834,840,846,852,858,864,870,876,882,887,893,899,904,910,916,922,928,934,940,946,952,957,963,969,975,981,987,993,999,1005,1011,1017,1023,1029,1035,1041,1047,1053,1059,1065,1071,1077,1083,1089,1095,1100,1106,1111,1117,1123,1129,1134,1139],{"path":620,"title":621,"description":622,"published":623,"category":624,"image":625,"draft":580},"\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":627,"title":628,"description":629,"published":630,"category":624,"image":631,"draft":580},"\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":164,"title":633,"description":634,"published":635,"category":624,"image":636,"draft":580},"Помилка 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":312,"title":638,"description":639,"published":640,"category":624,"image":641,"draft":580},"Помилка 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":643,"title":644,"description":645,"published":646,"category":624,"image":647,"draft":580},"\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":649,"title":650,"description":651,"published":652,"category":624,"image":653,"draft":580},"\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":655,"title":656,"description":657,"published":658,"category":624,"image":659,"draft":580},"\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":661,"title":662,"description":663,"published":664,"category":624,"image":665,"draft":580},"\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":667,"title":668,"description":669,"published":670,"category":624,"image":671,"draft":580},"\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":673,"title":674,"description":675,"published":676,"category":624,"image":677,"draft":580},"\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":609,"title":5,"description":579,"published":610,"category":576,"image":597,"draft":580},{"path":680,"title":681,"description":682,"published":683,"category":624,"image":684,"draft":580},"\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":686,"title":687,"description":688,"published":689,"category":624,"image":690,"draft":580},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" у Supabase: три причини","Supabase відповідає \"Invalid login credentials\" на неправильний пароль, невідому пошту й акаунт Google. Як зрозуміти, що саме.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":692,"title":693,"description":694,"published":695,"category":624,"image":696,"draft":580},"\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":698,"title":699,"description":700,"published":701,"category":624,"image":702,"draft":580},"\u002Fblog\u002Fcertificate-not-trusted","Сертифікат не довірений: три причини, крім закінчення строку","Сертифікат не довірений, хоча дата в порядку? Він називає іншу адресу, підписав сам себе або в його ланцюжку бракує ланки. Як зрозуміти, що саме.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":704,"title":705,"description":706,"published":707,"category":624,"image":708,"draft":580},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","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":710,"title":711,"description":712,"published":713,"category":624,"image":714,"draft":580},"\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":716,"title":717,"description":718,"published":719,"category":624,"image":720,"draft":580},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", хоча таблиця на місці","Supabase \"relation does not exist\" або PGRST205: жодна таблиця не має такої назви в цій схемі. Чотири перевірки, і на що зважити, відкриваючи схему.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":722,"title":723,"description":724,"published":725,"category":624,"image":726,"draft":580},"\u002Fblog\u002Fsupabase-function-not-found","Supabase PGRST202: \"Could not find the function in the schema cache\"","Supabase \"Could not find the function in the schema cache\" показує назви аргументів, які надіслав ваш застосунок. Порівняйте їх із функцією.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":728,"title":729,"description":730,"published":731,"category":624,"image":732,"draft":580},"\u002Fblog\u002Fsupabase-schema-cache-column-error","Supabase PGRST204: \"Could not find the column in the schema cache\"","Supabase \"Could not find the column in the schema cache\" зазвичай означає, що назва не збігається. Чотири перевірки і рядок для перезавантаження.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":734,"title":735,"description":736,"published":737,"category":624,"image":738,"draft":580},"\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":740,"title":741,"description":742,"published":743,"category":624,"image":744,"draft":580},"\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":746,"title":747,"description":748,"published":749,"category":624,"image":750,"draft":580},"\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":752,"title":753,"description":754,"published":755,"category":624,"image":756,"draft":580},"\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":758,"title":759,"description":760,"published":761,"category":624,"image":762,"draft":580},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: який ключ перестав працювати?","Помилка Supabase invalid JWT — це PGRST301: підписаний токен не пройшов перевірку. У новому проєкті йдеться про сесію, а не про ключ API.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":764,"title":765,"description":766,"published":767,"category":624,"image":768,"draft":580},"\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":56,"title":770,"description":771,"published":772,"category":624,"image":773,"draft":580},"\"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":775,"title":776,"description":777,"published":778,"category":624,"image":779,"draft":580},"\u002Fblog\u002Fwhat-is-supabase","Що таке Supabase? База даних, яку обрав ваш білдер","Що таке Supabase: база даних, вхід і сховище файлів за вашим застосунком. Supabase тримає сервери, а правила про те, хто читає ваші рядки, ваші.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":781,"title":782,"description":783,"published":784,"category":624,"image":785,"draft":580},"\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":787,"title":788,"description":789,"published":790,"category":624,"image":791,"draft":580},"\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":793,"title":794,"description":795,"published":796,"category":624,"image":797,"draft":580},"\u002Fblog\u002Fbase44-security-scan","Сканування безпеки Base44: те, що бачить лише воно","Сканування безпеки Base44 перевіряє сім видів проблем зсередини. Ось половина, яку читає тільки воно, і половина, на яку воно ніколи не дивиться.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":799,"title":800,"description":801,"published":802,"category":624,"image":803,"draft":580},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Ваш API-ключ витік. Порядок дій","API-ключ витік, і ви не знаєте, що робити першим. Не кожен ключ у вашому фронтенді є витоком, а порядок важить більше за швидкість.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":805,"title":806,"description":807,"published":808,"category":624,"image":809,"draft":580},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"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":811,"title":812,"description":813,"published":814,"category":624,"image":815,"draft":580},"\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":817,"title":818,"description":819,"published":820,"category":624,"image":821,"draft":580},"\u002Fblog\u002Fis-base44-safe","Чи безпечний Base44? Дані 5 442 застосунків","Чи безпечний Base44? Ми прогнали дев’ять перевірок на 5 442 робочих застосунках Base44. Майже всі отримали B з причин, яких власник ніколи не обирав.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":823,"title":824,"description":825,"published":826,"category":624,"image":827,"draft":580},"\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":829,"title":830,"description":831,"published":832,"category":624,"image":833,"draft":580},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Чи відкритий ваш файл .env? Дванадцять шляхів для перевірки","Чи відкритий ваш файл .env на вашому власному вебсервері? Дванадцять адрес скажуть це за хвилину, а влучання означає, що все в ньому вже публічне.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":835,"title":836,"description":837,"published":838,"category":624,"image":839,"draft":580},"\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":841,"title":842,"description":843,"published":844,"category":624,"image":845,"draft":580},"\u002Fblog\u002Fis-bolt-safe","Чи безпечний Bolt? Що показали 1 123 застосунки Bolt","Чи безпечний Bolt? Ми прогнали 1 123 живі застосунки Bolt через дев’ять перевірок. Хостинг був чистим. Знахідки: ключі й відкриті таблиці в самих застосунках.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":847,"title":848,"description":849,"published":850,"category":624,"image":851,"draft":580},"\u002Fblog\u002Fis-supabase-down-or-your-app","Supabase не працює чи проблема у вашому застосунку? Як розрізнити","Supabase не працює чи зламався ваш застосунок? Пауза, повна база й ваша власна помилка виглядають однаково. Чотири перевірки їх розрізняють.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":853,"title":854,"description":855,"published":856,"category":624,"image":857,"draft":580},"\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":859,"title":860,"description":861,"published":862,"category":624,"image":863,"draft":580},"\u002Fblog\u002Fsupabase-free-plan-limits","Ліміти безкоштовного тарифу Supabase і що стається на кожному","Ліміти безкоштовного тарифу Supabase: 500 МБ бази, 5 ГБ egress і жодних резервних копій. Що стається на кожній межі і що змінює Pro за $25.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":865,"title":866,"description":867,"published":868,"category":576,"image":869,"draft":580},"\u002Fblog\u002Ftest-your-supabase-backup","Перевірте резервну копію Supabase до того, як вона знадобиться","Як перевірити резервну копію Supabase: відновити в тестовий проєкт, порахувати рядки, увійти й знайти рядок, якого бракує обрізаному файлу.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":871,"title":872,"description":873,"published":874,"category":576,"image":875,"draft":580},"\u002Fblog\u002Fsupabase-backup-github-action","Безкоштовна резервна копія Supabase через GitHub Action і підступ","Резервна копія Supabase через GitHub Action безкоштовна й годиться багатьом застосункам. Робочий процес, потрібний рядок підключення та egress.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":877,"title":878,"description":879,"published":880,"category":576,"image":881,"draft":580},"\u002Fblog\u002Fdownload-your-supabase-backup","Чому ви не можете завантажити резервну копію Supabase","Завантажити резервну копію Supabase на сучасному проєкті не вийде: щоденна копія там фізична. Як це перевірити і як тримати власну копію.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":883,"title":884,"description":885,"published":880,"category":624,"image":886,"draft":580},"\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":888,"title":889,"description":890,"published":891,"category":624,"image":892,"draft":580},"\u002Fblog\u002Fopen-api-endpoint-exposed","Чи є відкритий API-ендпоінт проблемою безпеки? Читайте JSON","Ваше сканування позначило відкритий API-ендпоінт. Чи це важливо, залежить від того, що повернулося, і більшість знайдених належали платформі.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":894,"title":895,"description":896,"published":897,"category":624,"image":898,"draft":580},"\u002Fblog\u002Flovable-security-scan","Сканування безпеки Lovable: чого воно не доведе","Сканування безпеки Lovable: що перевіряють Quick scan і Deep scan, коли запускається кожне, і єдине, чого не доведе жодне сканування зсередини.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":470,"title":900,"description":901,"published":902,"category":576,"image":903,"draft":580},"Чому у вашому дампі Supabase немає користувачів","Запустіть supabase db dump окремо і отримаєте форму вашої бази та жодного її рядка, без схеми auth, у якій живуть ваші користувачі.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":905,"title":906,"description":907,"published":908,"category":624,"image":909,"draft":580},"\u002Fblog\u002Fdomain-and-certificate-expiry","Домен закінчився, сайт лежить: що буде далі","Ваш домен закінчився і сайт лежить. Ось який годинник уже пішов, чому прострочений сертифікат це менша з двох бід, і як перевірити обидва.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":911,"title":912,"description":913,"published":914,"category":624,"image":915,"draft":580},"\u002Fblog\u002Fis-lovable-safe","Чи безпечний Lovable? Що показали 18 554 застосунки Lovable","Чи безпечний Lovable? Ми прогнали 18 554 живі застосунки Lovable через дев’ять перевірок. Платформа виявилася найчистішою з п’яти. Знахідки були в застосунках.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":917,"title":918,"description":919,"published":920,"category":624,"image":921,"draft":580},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Чек-лист безпеки для vibe coding, у девʼяти перевірках","Чек-лист безпеки для vibe coding із девʼяти пунктів, кожен з яких будь-хто може перевірити у вашому живому застосунку ззовні, і кожен має тест на один рядок.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":923,"title":924,"description":925,"published":926,"category":624,"image":927,"draft":580},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Секретний ключ Stripe у фронтенді може рухати гроші","Секретний ключ Stripe, відкритий у вашому фронтенді, може повертати кошти, списувати й читати кожну картку клієнта. А ключ pk_live_ там і має бути.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":929,"title":930,"description":931,"published":932,"category":624,"image":933,"draft":580},"\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":935,"title":936,"description":937,"published":938,"category":624,"image":939,"draft":580},"\u002Fblog\u002Fbase44-source-maps","Безпека Base44: що позначає скан і що з цього виправляти вам","Безпека Base44 на 5 438 просканованих застосунках: три знахідки майже на кожному належать платформі, source map є бейджем Base44, а ваша частина коротка.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":941,"title":942,"description":943,"published":944,"category":624,"image":945,"draft":580},"\u002Fblog\u002Fis-cursor-ai-safe","Чи безпечний Cursor AI? Редактор, код і опублікований застосунок","Чи безпечний Cursor AI? Три запитання в одному пошуку: що Cursor зберігає, у чому помиляється його код і чи відкритий застосунок, який ви опублікували.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":947,"title":948,"description":949,"published":950,"category":624,"image":951,"draft":580},"\u002Fblog\u002Fis-replit-safe","Чи безпечний Replit? Що ми знайшли в 3 042 живих застосунках Replit","Чи безпечний Replit? Ми прогнали 3 042 живі застосунки Replit через дев’ять зовнішніх перевірок. Знахідки були в опублікованому застосунку, а не в хостингу.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":448,"title":953,"description":954,"published":955,"category":576,"image":956,"draft":580},"Supabase storage backup: у копії бази даних немає жодного файлу","Supabase storage backup це окрема робота. Копії бази даних зберігають список ваших файлів і жодного з них, тож після відновлення кожне завантаження зламане.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":958,"title":959,"description":960,"published":961,"category":576,"image":962,"draft":580},"\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":964,"title":965,"description":966,"published":967,"category":576,"image":968,"draft":580},"\u002Fblog\u002Fsupabase-project-paused-recover","Проєкт Supabase на паузі? Ваші дані нікуди не зникли","Supabase поставив ваш проєкт на паузу після тижня без активності. Нічого не видалено, кнопка Restore стоїть поруч із назвою, і у вас є рік, щоб натиснути.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":970,"title":971,"description":972,"published":973,"category":624,"image":974,"draft":580},"\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":976,"title":977,"description":978,"published":979,"category":624,"image":980,"draft":580},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Увімкніть Row Level Security на кожній таблиці Supabase і перевірте","Row Level Security у Supabase без політики закриває таблицю повністю. Політика без увімкненого перемикача не робить нічого. Ось SQL, і ось перевірка.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":982,"title":983,"description":984,"published":985,"category":624,"image":986,"draft":580},"\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":988,"title":989,"description":990,"published":991,"category":624,"image":992,"draft":580},"\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":994,"title":995,"description":996,"published":997,"category":624,"image":998,"draft":580},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Сканери безпеки для vibe coding у порівнянні, наш теж","Найкращий сканер безпеки для vibe coding залежить від трьох питань, на які не відповідає жоден перелік функцій. Вісім інструментів і ціни.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1000,"title":1001,"description":1002,"published":1003,"category":624,"image":1004,"draft":580},"\u002Fblog\u002Fsupabase-security-checker","Supabase security checker: п’ять перевірок, які зробите самі","Supabase security checker читає ваш опублікований застосунок, а не налаштування проєкту. Ось п’ять перевірок і як виконати кожну самостійно.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1006,"title":1007,"description":1008,"published":1009,"category":624,"image":1010,"draft":580},"\u002Fblog\u002Fvibe-coding-security-scanner","Сканер безпеки для vibe coding: чого не бачить скан URL","Сканер безпеки для vibe coding читає ваш робочий застосунок ззовні. Що це охоплює, чотири речі, яких він не бачить, і як читати результат.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1012,"title":1013,"description":1014,"published":1015,"category":624,"image":1016,"draft":580},"\u002Fblog\u002Fmissing-security-headers","Відсутні заголовки безпеки: коли це справді важливо","Відсутні заголовки безпеки трапляються в наших звітах найчастіше. Від чого вони захищають і коли це найменш терміновий рядок вашого звіту.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1018,"title":1019,"description":1020,"published":1021,"category":624,"image":1022,"draft":580},"\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":1024,"title":1025,"description":1026,"published":1027,"category":624,"image":1028,"draft":580},"\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":1030,"title":1031,"description":1032,"published":1033,"category":576,"image":1034,"draft":580},"\u002Fblog\u002Fsupabase-backup-tools-compared","Інструменти резервного копіювання Supabase, і наш серед них","Чотири види інструментів резервного копіювання Supabase, що копіює кожен і коли безкоштовна GitHub Action виграє в будь-якої оплати, нашої теж.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1036,"title":1037,"description":1038,"published":1039,"category":624,"image":1040,"draft":580},"\u002Fblog\u002Freplit-secrets-explained","Як користуватися секретами в Replit і що все одно публікується","Як користуватися секретами в Replit: додати, прочитати і усунути дві причини undefined. А ще ключі, які цей інструмент не здатен зберегти в таємниці.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1042,"title":1043,"description":1044,"published":1045,"category":576,"image":1046,"draft":580},"\u002Fblog\u002Fback-up-supabase-free-tier","Резервні копії на безкоштовному тарифі Supabase без терміналу","На безкоштовному тарифі Supabase резервних копій немає: копію робите ви. Як зробити її з панелі та що втрачає шлях через CSV.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1048,"title":1049,"description":1050,"published":1051,"category":624,"image":1052,"draft":580},"\u002Fblog\u002Fis-supabase-secure","Чи безпечний Supabase? Так. Ваш проєкт це інше питання","Чи безпечний Supabase? Платформа проходить аудити, шифрує дані й тримає пентести. Їхня документація каже, де це закінчується і починаються ваші налаштування.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1054,"title":1055,"description":1056,"published":1057,"category":624,"image":1058,"draft":580},"\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":1060,"title":1061,"description":1062,"published":1063,"category":624,"image":1064,"draft":580},"\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":1066,"title":1067,"description":1068,"published":1069,"category":624,"image":1070,"draft":580},"\u002Fblog\u002Fcors-wildcard-security-risk","Чи є вайлдкард CORS ризиком для безпеки? Майже ніколи.","Чи є вайлдкард CORS ризиком для безпеки? Зазвичай це типове налаштування вашого білдера, і воно не видає нічого, що ваш сервер і так віддавав кожному.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1072,"title":1073,"description":1074,"published":1075,"category":576,"image":1076,"draft":580},"\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":1078,"title":1079,"description":1080,"published":1081,"category":576,"image":1082,"draft":580},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Як відновити резервну копію Supabase, і що ламається потім","Як відновити резервну копію Supabase з панелі або з файлу дампа, що саме замінює відновлення і чому ваш застосунок може лишитися зламаним після нього.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1084,"title":1085,"description":1086,"published":1087,"category":624,"image":1088,"draft":580},"\u002Fblog\u002Fsupabase-storage-bucket-public","Ваш бакет Supabase Storage публічний. Чи це проблема?","Публічний бакет Supabase Storage означає, що той, хто має URL файлу, може його відкрити. Він не означає, що хтось може переглянути список вмісту.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1090,"title":1091,"description":1092,"published":1093,"category":624,"image":1094,"draft":580},"\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":559,"title":1096,"description":1097,"published":1098,"category":576,"image":1099,"draft":580},"ШІ-агент видалив мої дані в Supabase. Що можна відновити?","ШІ-агент видалив дані з вашої бази. Те, що ви зможете відновити, вирішилося раніше, а наступні хвилини вирішують, скільки з цього вціліє.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1101,"title":1102,"description":1103,"published":1104,"category":624,"image":1105,"draft":580},"\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":1107,"title":1108,"description":1109,"published":1104,"category":624,"image":1110,"draft":580},"\u002Fblog\u002Fsource-maps-exposed-in-production","Відкриті source maps: ваш застосунок публікує свій вихідний код","Відкрита source map дає будь-кому прочитати оригінальний код вашого застосунку, разом із коментарями. Перевірка за 30 секунд, і що важить насправді.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1112,"title":1113,"description":1114,"published":1115,"category":624,"image":1116,"draft":580},"\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":1118,"title":1119,"description":1120,"published":1121,"category":576,"image":1122,"draft":580},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Чи робить Supabase резервні копії моєї бази? Залежить від тарифу.","Чи робить Supabase резервні копії вашої бази даних? На платних тарифах щодня, на безкоштовному жодної. Як дізнатися, що у вас насправді є.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1124,"title":1125,"description":1126,"published":1127,"category":624,"image":1128,"draft":580},"\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":1130,"title":1131,"description":1132,"published":1127,"category":576,"image":1133,"draft":580},"\u002Fblog\u002Fversion-history-is-not-a-backup","Історія версій не є резервною копією. Вона не поверне таблицю.","Lovable і Bolt ведуть історію версій вашого коду. Ваша база даних працює як окремий сервіс, тож відкат назад не поверне ваші дані.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":465,"title":1135,"description":1136,"published":1137,"category":576,"image":1138,"draft":580},"Три способи зробити резервну копію бази Supabase, і чого бракує","Панель, pg_dump і керований сервіс. Що насправді зберігає кожен спосіб, що тихо лишає осторонь і який із них переживе втрату акаунта.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1140,"title":1141,"description":1142,"published":1137,"category":624,"image":1143,"draft":580},"\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",1794213654274]