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