[{"data":1,"prerenderedAt":1154},["ShallowReactive",2],{"blog-de-auth-session-missing":3,"blog-index-de":628},{"id":4,"title":5,"body":6,"category":586,"cover":587,"coverAlt":588,"description":589,"draft":590,"extension":591,"faq":592,"image":607,"keywords":608,"meta":616,"navigation":617,"ogTitle":618,"path":619,"published":620,"seo":621,"stem":622,"tldr":623,"updated":620,"__hash__":627},"blog_de\u002Fblog\u002Fauth-session-missing.md","Supabase \"Auth session missing!\": wo die Sitzung geblieben ist",{"type":7,"value":8,"toc":574},"minimark",[9,13,24,27,43,48,51,54,72,75,81,85,90,108,116,123,150,153,159,170,174,177,186,212,237,246,258,263,267,270,296,302,319,335,339,342,351,361,367,370,376,382,400,410,414,417,434,452,459,463,469,478,492,502,519,523,561],[10,11,12],"p",{},"Deine Lovable- oder Bolt-App meldet Leute mit Supabase an. Eines Morgens\nöffnest du die Browserkonsole und findest das hier in Rot, auf einer Seite, an\nder nichts falsch aussieht:",[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],{},"Oder eine Kundin schreibt dir, dass die Seite \"Neues Passwort festlegen\" sie mit\ngenau diesen Worten abweist, jedes Mal.",[10,28,29,30,33,34,37,38,42],{},"Such nach \"auth session missing supabase\", und du findest Threads voller\nLösungen: ",[21,31,32],{},"getUser()"," gegen ",[21,35,36],{},"getSession()"," tauschen, die Bibliothek\nherunterstufen, eine Wartezeit einbauen, das Projekt neu starten. Sie gehen\ndavon aus, dass zwischen deiner App und Supabase etwas kaputtgegangen ist. ",[39,40,41],"strong",{},"Es\nwurde keine Anfrage gestellt."," Der Fehler entsteht in deiner App, geschrieben\nvon der Supabase-Bibliothek, bevor irgendetwas den Browser verlässt.",[44,45,47],"h2",{"id":46},"was-bedeutet-auth-session-missing-in-supabase","Was bedeutet \"Auth session missing!\" in Supabase?",[10,49,50],{},"supabase-js wurde gefragt, wer angemeldet ist, suchte eine Sitzung, fand keine\nund antwortete selbst.",[10,52,53],{},"Eine Sitzung ist das, was Supabase Auth einer Person bei der Anmeldung gibt:\nein Paar Tokens, die sagen, wer sie ist, im Browser aufbewahrt, damit auch der\nnächste Seitenaufruf sie noch kennt. supabase-js ist die Bibliothek, mit der\ndeine App mit Supabase spricht, und jeder Aufruf, der eine Person braucht,\nbeginnt damit, diese Sitzung hervorzuholen.",[10,55,56,57,60,61,64,65,68,69,71],{},"Die Meldung steht in supabase-js selbst, in der Datei ",[21,58,59],{},"errors.ts"," der\nAuth-Bibliothek: ein ",[21,62,63],{},"AuthSessionMissingError"," mit dem Text\n",[21,66,67],{},"Auth session missing!"," und dem Status 400. Die 400 ist ein Etikett, das sich\ndie Bibliothek selbst gibt. Kein Server hat damit geantwortet, und die Logs von\nSupabase zeigen nichts, weil ",[21,70,32],{}," vor allem anderen nach einer Sitzung\nsieht. Ein Kommentar in seinem Quellcode sagt es so: Es gibt einen Fehler\nzurück, wenn es weder ein Zugriffstoken noch einen eigenen\nAuthorization-Header gibt.",[10,73,74],{},"Stell dir einen Empfang vor, der dir sagen kann, welcher Besucher jemand ist.\nWer sich anmeldet, bekommt an der Tür einen Ausweis, und supabase-js bewahrt\ndiesen Ausweis in der Tasche des Browsers auf. Wenn dein Code fragt \"Wer ist\ndas?\", greift supabase-js zuerst in die Tasche. Ist ein Ausweis darin, trägt es\nihn zum Empfang und bringt einen Namen zurück. Ist die Tasche leer, geht es gar\nnicht erst zum Empfang. Es kommt sofort zurück und sagt dir, dass kein Ausweis\nda ist.",[76,77],"diagram",{"alt":78,"caption":79,"src":80},"Zwei Bahnen beginnen an einem Browserfenster. In der oberen geht ein Ausweis zu einem Empfang, und der Empfang antwortet mit einer Person und einem Haken. In der unteren ist die Ausweishülle leer und gelb umrissen, und die Bahn endet an einem Kreuz mit 400 daneben, weit vor dem Empfang, der blass und gestrichelt bleibt.","Mit einer Sitzung fragt supabase-js bei Supabase Auth nach. Ohne eine bleibt es in deiner App stehen, und der Fehler kommt von dort.","\u002Fblog\u002Fauth-session-missing\u002Fthe-empty-pocket-1600x720.png",[44,82,84],{"id":83},"er-wird-zurückgegeben-nicht-geworfen","Er wird zurückgegeben, nicht geworfen",[10,86,87,89],{},[21,88,32],{}," gibt den Fehler neben einem leeren Nutzer zurück, und dein Code\nentscheidet, was als Nächstes passiert.",[10,91,92,93,96,97,100,101,104,105,107],{},"Der Aufruf sieht so aus, und ohne Sitzung ist ",[21,94,95],{},"user"," danach ",[21,98,99],{},"null"," und ",[21,102,103],{},"error","\nder ",[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],{},"Es wird nichts geworfen, also fängt ein ",[21,120,121],{},"try … catch"," um den Aufruf nichts. Von\ndort kommt der sichtbare Schaden, in einer von zwei Formen:",[124,125,126,136],"ul",{},[127,128,129,135],"li",{},[39,130,131,132,134],{},"Der Code zeigt jeden ",[21,133,103],{}," an, den er bekommt."," Ein Besucher, der sich\nnoch nicht angemeldet hat, sieht \"Auth session missing!\" in einer Meldung oder\neinem roten Kasten, auf einer Seite, die er sehen durfte.",[127,137,138,141,142,145,146,149],{},[39,139,140],{},"Der Code benutzt den Nutzer, ohne nachzusehen."," Er liest ",[21,143,144],{},"user.id",", und die\nSeite bricht mit ",[21,147,148],{},"Cannot read properties of null"," ab, was nach einem ganz\nanderen Fehler aussieht.",[10,151,152],{},"Beides ist derselbe Fehler: \"Niemand ist angemeldet\" wird als Störung behandelt.\nSieh zuerst nach dem Nutzer und zeig einem abgemeldeten Besucher die Seite, die\nfür ihn gedacht ist:",[14,154,157],{"className":155,"code":156,"language":113,"meta":23},[111],"const { data: { user } } = await supabase.auth.getUser()\nif (!user) {\n  \u002F\u002F niemand ist angemeldet: Anmeldeseite oder öffentliche Seite zeigen\n  return\n}\n",[21,158,156],{"__ignoreMap":23},[10,160,161,162,165,166,169],{},"Wenn du das von einer echten Störung unterscheiden willst, nennt die Bibliothek\nden Fall beim Namen: ",[21,163,164],{},"error.name"," ist ",[21,167,168],{},"'AuthSessionMissingError'",".",[44,171,173],{"id":172},"wo-die-sitzung-verloren-geht","Wo die Sitzung verloren geht",[10,175,176],{},"An drei Stellen, und nur die erste ist harmlos.",[10,178,179,182,183,185],{},[39,180,181],{},"1. In diesem Browser hat sich niemand angemeldet."," Deine App ruft ",[21,184,32],{},"\nauf einer Seite auf, die jeder öffnen kann, etwa um zu entscheiden, ob\n\"Anmelden\" oder \"Mein Konto\" erscheint. Für einen Besucher ist die leere Tasche\ndie zutreffende Antwort. Hier begegnen die meisten der Meldung, und die\nCode-Lösung oben ist alles, was es braucht.",[10,187,188,191,192,195,196,203,204,207,208,211],{},[39,189,190],{},"2. Eine Seite für das Zurücksetzen des Passworts oder einen Magic Link."," Ein\nneues Passwort setzt ",[21,193,194],{},"updateUser({ password })",", und der\n",[197,198,202],"a",{"href":199,"rel":200},"https:\u002F\u002Fsupabase.com\u002Fdocs\u002Fguides\u002Fauth\u002Fpasswords",[201],"nofollow","Passwort-Leitfaden von Supabase","\nist bei der Reihenfolge eindeutig: Erst wenn eine Sitzung besteht, sammelt man\ndas neue Passwort ein und ruft ",[21,205,206],{},"updateUser"," auf. Auf dieser Seite soll die\nSitzung aus dem Link in der E-Mail kommen, der die Person beim Öffnen anmeldet.\nTut er das nicht, ist die Tasche leer, und ",[21,209,210],{},"updateUser()"," antwortet mit \"Auth\nsession missing!\". Die üblichen Gründe:",[124,213,214,222,225],{},[127,215,216,217,221],{},"Der Link war schon benutzt oder abgelaufen, bevor er geöffnet wurde.\n",[197,218,220],{"href":219},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","Warum Supabase sagt, der E-Mail-Link sei ungültig oder abgelaufen","\ngeht jeden Grund durch.",[127,223,224],{},"Er wurde in einem anderen Browser oder einer anderen App geöffnet als dem, der\nihn angefordert hat. Nutzt eine App die PKCE-Anmeldung von Supabase, bleibt ein\nTeil des Austauschs in dem Browser, der ihn begonnen hat, und laut der\nDokumentation von Supabase muss der Austausch des Codes im selben Browser und\nauf demselben Gerät angestoßen werden, auf dem der Ablauf begann.",[127,226,227,228,231,232,236],{},"Er schickte die Person woandershin, etwa nach ",[21,229,230],{},"localhost",", sodass die Sitzung\nan einer Adresse landete, die nicht deine App ist.\n",[197,233,235],{"href":234},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","Warum Supabase auf localhost umleitet","\nbehandelt diesen Fall.",[10,238,239,242,243,245],{},[39,240,241],{},"3. Dein Server oder eine Edge Function hat die Sitzung nie bekommen."," Der\nAusweis liegt im Browser deines Besuchers. Code, der woanders läuft, eine\nSupabase Edge Function oder die Serverhälfte einer Next.js-App aus v0 oder\nCursor, erzeugt seinen eigenen Supabase-Client, und ein neuer Client beginnt mit\nleerer Tasche. Solange die Sitzung des Besuchers nicht hineingereicht wird,\nfindet ",[21,244,32],{}," dort nichts und antwortet mit \"Auth session missing!\", ohne\nSupabase zu fragen.",[10,247,248,249,252,253,257],{},"In einer Edge Function reist die Sitzung im Header ",[21,250,251],{},"Authorization"," der Anfrage\nmit, und supabase-js nutzt sie nur, wenn du sie beim Erzeugen des Clients\nübergibst. In einer Next.js-App reist sie in Cookies, und der Server-Helfer von\nSupabase liest sie nur, wenn du ihm die Cookies der Anfrage gibst. Reicht eine\nEdge Function diesen Fehler als Fehler zurück, zeigt deine App\n",[197,254,256],{"href":255},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"Edge Function returned a non-2xx status code\"",",\nund im Log der Funktion wartet diese Meldung.",[76,259],{"alt":260,"caption":261,"src":262},"Eine Person an einem Browserfenster, mit Ausweis, schickt zwei Anfragen an eine Edge Function. In der oberen Bahn kommt die Anfrage ohne den Ausweis an, die eigene Hülle der Funktion ist leer und gelb umrissen, und die Bahn endet an einem Kreuz. In der unteren Bahn reist der Ausweis mit der Anfrage unter der Bezeichnung Authorization, die Hülle der Funktion ist gefüllt, und der Empfang antwortet mit einem Haken.","Die Sitzung gehört dem Browser. Eine Funktion oder ein Server hat sie nur, wenn die Anfrage sie mitbringt und der Code sie an seinen Client weitergibt.","\u002Fblog\u002Fauth-session-missing\u002Fthe-badge-stays-behind-1600x760.png",[44,264,266],{"id":265},"woran-du-erkennst-welcher-fall-es-ist","Woran du erkennst, welcher Fall es ist",[10,268,269],{},"Sieh, wo die Meldung erscheint, und dann, was der Browser tatsächlich geschickt\nhat.",[10,271,272,275,276,279,280,283,284,287,288,291,292,295],{},[39,273,274],{},"In der Browserkonsole, auf einer Seite, die jeder öffnen kann."," Fall 1. Öffne\ndie Entwicklerwerkzeuge deines Browsers (F12), wähle ",[39,277,278],{},"Application",", dann\n",[39,281,282],{},"Local Storage"," und die Adresse deiner App. supabase-js bewahrt die Sitzung\nunter einem Schlüssel auf, der aus ",[21,285,286],{},"sb-",", der ID deines Projekts und\n",[21,289,290],{},"-auth-token"," besteht. Gibt es keinen solchen Eintrag, hat dieser Browser keine\nSitzung, und die Meldung sagt die Wahrheit. Eine Next.js-App mit den\nServer-Helfern von Supabase bewahrt die Sitzung stattdessen in Cookies auf, also\nsieh unter ",[39,293,294],{},"Cookies"," nach demselben Namen.",[10,297,298,301],{},[39,299,300],{},"Auf einer Seite zum Zurücksetzen oder für einen Magic Link."," Fall 2. Sieh dir\ndie Adresse an, unter der sich der Link geöffnet hat. Ist es nicht deine App,\noder ist es ein Link, den du oder ein Mail-Scanner schon geöffnet hatte, hatte\ndie Sitzung nie eine Chance anzukommen.",[10,303,304,307,308,311,312,314,315,318],{},[39,305,306],{},"Im Log einer Edge Function oder deines Servers."," Fall 3. Öffne den Tab\n",[39,309,310],{},"Network",", wiederhole die Aktion und klick auf die Anfrage an deine Funktion.\nEnthält ihr Header ",[21,313,251],{}," eine lange Zeichenkette, die mit ",[21,316,317],{},"eyJ","\nbeginnt, hat der Browser das Token einer Person geschickt, und deine Funktion\nhat es nicht an ihren Client weitergegeben.",[10,320,321,322,325,326,329,330,334],{},"Was du auf keinem Weg findest, ist eine Anfrage an ",[21,323,324],{},"\u002Fauth\u002Fv1\u002Fuser",", die mit\ndieser Meldung zurückkam. Siehst du doch eine, die fehlgeschlagen ist, ist es\nein anderer Fehler. Eine Antwort mit ",[21,327,328],{},"invalid claim: missing sub claim"," heißt,\ndass der Schlüssel deines Projekts dorthin geschickt wurde, wo eine Person\nhingehört, und ",[197,331,333],{"href":332},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","dieser Beitrag"," ist sein\nZwilling.",[44,336,338],{"id":337},"die-lösung-für-jeden-fall","Die Lösung für jeden Fall",[10,340,341],{},"Gib jedem Fall die Sitzung, die ihm fehlt, oder eine Antwort, die keine braucht.",[10,343,344,347,348,350],{},[39,345,346],{},"Fall 1, der abgemeldete Besucher:"," Sieh nach ",[21,349,95],{},", bevor du ihn benutzt,\nwie im Code oben, und zeig die Seite, die für jemanden gedacht ist, der sich\nnicht angemeldet hat.",[10,352,353,356,357,360],{},[39,354,355],{},"Fall 2, die Seite zum Zurücksetzen:"," Warte, bis der Link die Person\nangemeldet hat, bevor du das Formular zeigst. Supabase sendet das Ereignis\n",[21,358,359],{},"PASSWORD_RECOVERY",", wenn jemand über einen Wiederherstellungslink ankommt, und\nseine Referenz zeigt die Seite, wie sie darauf wartet:",[14,362,365],{"className":363,"code":364,"language":113,"meta":23},[111],"supabase.auth.onAuthStateChange((event) => {\n  if (event === 'PASSWORD_RECOVERY') {\n    \u002F\u002F der Link hat die Person angemeldet: jetzt das Formular für das neue Passwort zeigen\n  }\n})\n",[21,366,364],{"__ignoreMap":23},[10,368,369],{},"Kommt das Ereignis nie, hat der Link nicht funktioniert. Sag das und biete an,\neinen neuen zu schicken, statt ein Formular zu zeigen, das sicher scheitern\nwird.",[10,371,372,375],{},[39,373,374],{},"Fall 3, die Funktion oder der Server:"," Gib die Sitzung des Besuchers an den\nClient weiter, den du erzeugst. In einer Edge Function erzeugst du ihn mit dem\neingehenden Header:",[14,377,380],{"className":378,"code":379,"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,381,379],{"__ignoreMap":23},[10,383,384,385,388,389,393,394,396,397,399],{},"Der neuere Wrapper ",[21,386,387],{},"withSupabase({ auth: 'user' })"," von Supabase erledigt\ndasselbe, bevor dein Handler läuft, und der\n",[197,390,392],{"href":391},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","Beitrag zur Edge Function"," zeigt die\nEinrichtung. Behalte die 401 für einen Aufrufer ohne Sitzung, damit eine Anfrage\nvon einer abgemeldeten Seite eine klare Ablehnung bekommt. Mit weitergereichtem\nHeader kann ",[21,395,32],{}," für einen abgemeldeten Aufrufer dort stattdessen\n",[21,398,328],{}," zurückgeben: derselbe Besucher, von der\nanderen Seite gesehen, und die 401 deckt beides ab.",[10,401,402,403,406,407,409],{},"In einer Next.js-App erzeugst du den Server-Client mit dem Helfer\n",[21,404,405],{},"@supabase\u002Fssr"," von Supabase und den Cookies der Anfrage, wie es seine\nServer-Einrichtung zeigt, und rufst ",[21,408,32],{}," auf diesem Client auf.",[44,411,413],{"id":412},"zwei-lösungen-nach-denen-du-schlechter-dastehst","Zwei Lösungen, nach denen du schlechter dastehst",[10,415,416],{},"Beide werden für diese Meldung vorgeschlagen, und jede stoppt den Fehler, indem\nsie die Prüfung dahinter entfernt.",[10,418,419,426,427,430,431,433],{},[39,420,421,33,423,425],{},[21,422,32],{},[21,424,36],{}," tauschen."," Im Browser ändert das nichts, was\nzählt: Der Speicher ist immer noch leer, also bekommst du keine Sitzung und\nkeinen Nutzer, nur ohne die Meldung. Auf einem Server ist es gefährlich. Der\nLeitfaden von Supabase für die Serverseite sagt, man solle\n",[21,428,429],{},"supabase.auth.getSession()"," in Servercode nie trauen, weil es die Sitzung aus\ndem Cookie liest, ohne sie neu zu prüfen. Ein Cookie ist etwas, das dir der\nBesucher schickt, und jeder kann dir jedes Cookie schicken, das er will.\n",[21,432,32],{}," ist die Methode, von der supabase-js dokumentiert, dass sie eine\nAnfrage an den Server von Supabase Auth stellt, sodass ihr Ergebnis echt ist.\nBehalte sie überall, wo die Antwort entscheidet, was jemand darf.",[10,435,436,439,440,443,444,447,448,169],{},[39,437,438],{},"Den geheimen Schlüssel in den Client setzen, damit der Aufruf nicht mehr\nscheitert."," Ein Client mit dem Schlüssel ",[21,441,442],{},"service_role"," oder ",[21,445,446],{},"sb_secret_","\nbraucht keine Sitzung zum Lesen und Schreiben, weil er die Regeln deiner\nDatenbank ganz übergeht. Die Funktion läuft wieder, für jeden Aufrufer,\nangemeldet oder nicht. Macht ein Builder diese Änderung in Code, der an den\nBrowser geht, reist der Schlüssel mit zu jedem Besucher. Ist das schon passiert,\n",[197,449,451],{"href":450},"\u002Fblog\u002Frotate-supabase-service-role-key","rotiere ihn zuerst",[10,453,454,455,169],{},"Das lässt sich von außen prüfen. Unser kostenloser Scan liest das JavaScript\ndeiner Live-App so, wie ein Fremder es täte, und nennt jeden Schlüssel, den er\nfindet, samt der Frage, ob er dorthin gehört. Das dauert etwa 20 Sekunden und\nbraucht kein Konto: ",[197,456,458],{"href":457},"\u002Fsecurity-scanner","scanne deine App",[44,460,462],{"id":461},"damit-die-prüfung-nach-der-nächsten-änderung-bleibt","Damit die Prüfung nach der nächsten Änderung bleibt",[10,464,465,468],{},[39,466,467],{},"Die Prüfung, wer angemeldet ist, ist der Teil einer Seite, der am ehesten\nverschwindet, wenn du deinen Builder bittest, einen Fehler wegzumachen",", und\nbeide schnellen Lösungen oben entfernen sie.",[10,470,471],{},[39,472,473,477],{},[197,474,476],{"href":475},"\u002Fwebsite-monitoring","Reeve Monitor"," scannt deine Live-App jede Stunde neu:",[124,479,480,483,486,489],{},[127,481,482],{},"alle neun Checks jede Stunde, für bis zu drei Apps",[127,484,485],{},"eine E-Mail an dem Tag, an dem ein erneuter Scan deine App schlechter benotet als der vorige; ein geheimer Schlüssel in deinem JavaScript deckelt die Note allein schon bei D",[127,487,488],{},"ob die App erreichbar ist, alle 60 Sekunden",[127,490,491],{},"ein monatlicher Bericht darüber, was gesehen wurde",[10,493,494],{},[39,495,496,497,501],{},"Ein Server, der jedem Cookie glaubt, oder eine Funktion, die mit dem geheimen\nSchlüssel läuft, lässt einen Fremden die Zeilen deiner Nutzer ändern.\n",[197,498,500],{"href":499},"\u002Fsupabase-backups","Reeve Care"," hält eine Kopie deiner Supabase-Datenbank von\ndavor.",[124,503,504,507,510,513,516],{},[127,505,506],{},"eine verschlüsselte Kopie nach Zeitplan, auf Reeves eigenem Speicher in der EU, außerhalb deines Supabase-Kontos",[127,508,509],{},"jede Kopie wird geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[127,511,512],{},"eine Wiederherstellung per Klick, die sichert, was jetzt da ist, bevor sie es ersetzt",[127,514,515],{},"deine hochgeladenen Dateien ebenfalls, sobald du eine Storage-Zugangsberechtigung verbindest",[127,517,518],{},"alles, was Monitor tut",[44,520,522],{"id":521},"was-jetzt-zu-tun-ist","Was jetzt zu tun ist",[524,525,526],"key-takeaways",{},[124,527,528,531,540,546,552],{},[127,529,530],{},"Lies \"Auth session missing!\" als \"hier ist niemand angemeldet\". Die Anfrage hat deine App nie verlassen.",[127,532,533,534,536,537,539],{},"Sieh nach, ob ",[21,535,95],{}," gleich ",[21,538,99],{}," ist, bevor du ihn benutzt, und zeig einem abgemeldeten Besucher die Seite, die für ihn gedacht ist, statt des Fehlers.",[127,541,542,543,545],{},"Warte auf einer Seite zum Zurücksetzen auf das Ereignis ",[21,544,359],{},", bevor du das Formular zeigst, und biete einen neuen Link an, wenn es nie ankommt.",[127,547,548,549,551],{},"Gib in einer Edge Function oder auf einem Server den Header ",[21,550,251],{}," oder die Cookies des Besuchers an den Client weiter, den du erzeugst, und antworte mit 401, wenn es trotzdem keinen Nutzer gibt.",[127,553,554,555,557,558,560],{},"Behalte ",[21,556,32],{}," auf dem Server. ",[21,559,36],{}," glaubt dort jedem Cookie, das es geschickt bekommt.",[10,562,563,564,568,569,573],{},"Gibt es deine Sitzungen und verschwinden sie dann, sodass Leute, die angemeldet\nwaren, plötzlich abgemeldet sind, ist das ein anderes Problem mit eigenen\nUrsachen, und\n",[197,565,567],{"href":566},"\u002Fblog\u002Fsupabase-users-logged-out","warum Supabase-Nutzer abgemeldet werden","\nbehandelt es. Die ",[197,570,572],{"href":571},"\u002Fchecklist","10-Minuten-Sicherheitscheckliste"," behandelt, was\neine frisch gestartete App sonst noch oft offen lässt.",{"title":23,"searchDepth":575,"depth":575,"links":576},3,[577,579,580,581,582,583,584,585],{"id":46,"depth":578,"text":47},2,{"id":83,"depth":578,"text":84},{"id":172,"depth":578,"text":173},{"id":265,"depth":578,"text":266},{"id":337,"depth":578,"text":338},{"id":412,"depth":578,"text":413},{"id":461,"depth":578,"text":462},{"id":521,"depth":578,"text":522},"Sicherheitsgrundlagen","\u002Fblog\u002Fauth-session-missing\u002Fcover-1200x630.png","Eine leere Ausweishülle an einem Band, der Platz für den Ausweis gelb umrissen, vor zwei Ausweisen mit Gesicht.","\"Auth session missing!\" heißt: supabase-js fand keine angemeldete Sitzung und fragte Supabase gar nicht erst. Wo die Sitzung blieb, und die Lösung je Fall.",false,"md",[593,595,598,601,604],{"q":47,"a":594},"Es bedeutet, dass supabase-js, die Supabase-Bibliothek in deiner App, nach dem angemeldeten Nutzer gefragt wurde und keine Sitzung hatte, mit der sie fragen konnte. Eine Sitzung ist das, was Supabase Auth einer Person bei der Anmeldung gibt, und die Bibliothek bewahrt sie im Browser auf. Ist keine da, wendet sie sich gar nicht an Supabase. Sie gibt AuthSessionMissingError mit dem Status 400 zurück und als Nutzer null.",{"q":596,"a":597},"Warum sehe ich \"Auth session missing!\", wenn niemand angemeldet ist?","Weil das die Antwort für einen Besucher ist, der sich nicht angemeldet hat. Deine App hat getUser() auf einer Seite aufgerufen, die jeder öffnen kann, und supabase-js hat gemeldet, dass niemand angemeldet war. Nichts ist kaputt. Dein Code muss den Nutzer nur als null lesen und die Anmeldeseite zeigen, statt den Fehler anzuzeigen.",{"q":599,"a":600},"Warum zeigt meine Seite zum Zurücksetzen des Passworts \"Auth session missing!\"?","Ein Passwort mit updateUser() zu ändern braucht eine Sitzung, und auf dieser Seite soll die Sitzung aus dem Link in der E-Mail kommen. War der Link schon benutzt oder abgelaufen, wurde er in einem anderen Browser geöffnet als dem, der ihn angefordert hat, oder schickte er die Person an eine andere Adresse, dann kam keine Sitzung an, und updateUser() hat niemanden, den es ändern könnte. Warte auf das Ereignis PASSWORD_RECOVERY, bevor du das Formular zeigst, und biete einen neuen Link an, wenn es nie kommt.",{"q":602,"a":603},"Ist \"Auth session missing!\" dasselbe wie \"invalid claim: missing sub claim\"?","Nein. \"Auth session missing!\" wird in deiner App entschieden, bevor irgendeine Anfrage sie verlässt. \"invalid claim: missing sub claim\" kommt von Supabase Auth zurück, das eine Anfrage bekommen und dort, wo das Token einer Person hingehört, den Schlüssel deines Projekts gefunden hat. Das Erste heißt, es gab nichts zu schicken. Das Zweite heißt, es wurde das Falsche geschickt.",{"q":605,"a":606},"Soll ich getSession() statt getUser() verwenden?","Nicht, um diesen Fehler loszuwerden. Im Browser findet getSession() denselben leeren Speicher und gibt keine Sitzung zurück, also ändert sich nichts, außer dass die Fehlermeldung verschwindet. Auf einem Server ist es schlimmer: supabase-js dokumentiert, dass getSession() die Sitzung direkt aus dem Speicher liest, etwa aus Cookies der Anfrage, die nicht echt sein müssen, und empfiehlt stattdessen getUser(), weil es bei Supabase Auth nachfragt.","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",[609,610,611,612,613,614,615],"auth session missing supabase","AuthSessionMissingError: Auth session missing!","supabase getuser auth session missing","supabase updateuser auth session missing","supabase passwort zurücksetzen auth session missing","supabase edge function auth session missing","supabase ssr auth session missing",{},true,"\"Auth session missing!\" in Supabase","\u002Fblog\u002Fauth-session-missing","2026-11-05",{"title":5,"description":589},"blog\u002Fauth-session-missing",[624,625,626],"\"Auth session missing!\" (AuthSessionMissingError, Status 400) kommt aus supabase-js in deiner App. Die Bibliothek suchte eine angemeldete Sitzung, fand keine und schickte die Anfrage nie an Supabase.","Auf einer Seite, auf der sich niemand angemeldet hat, ist das die richtige Antwort, und dein Code muss sie nur behandeln. Auf einer Seite zum Zurücksetzen des Passworts heißt es, dass der Link hier niemanden angemeldet hat. In einer Edge Function oder auf einem Server wurde die Sitzung des Besuchers nie weitergereicht.","Lass getUser() stehen. Wer auf einem Server stattdessen getSession() einsetzt, lässt den Fehler verschwinden, indem er glaubt, was immer im Cookie steht.","R4JbEdE4DmdSlBOtdqnJOonmRyDtW0CzqBd3NuGxC0o",[629,635,641,647,653,654,659,665,670,675,681,688,694,700,705,711,717,723,729,735,741,747,752,758,764,770,776,782,788,794,800,806,812,818,824,830,835,841,847,853,859,865,871,877,883,889,894,900,906,912,918,924,930,936,942,948,954,960,966,972,978,984,990,996,1001,1007,1013,1019,1025,1031,1037,1043,1049,1055,1061,1067,1073,1079,1085,1091,1097,1103,1109,1115,1120,1126,1132,1138,1143,1149],{"path":630,"title":631,"description":632,"published":633,"category":586,"image":634,"draft":590},"\u002Fblog\u002Fmax-client-connections-reached","Supabase \"max client connections reached\" erklärt","Supabase \"max client connections reached\": Der Pooler hat keinen Platz für noch einen Client. Der Port in deinem Connection String setzt das Limit.","2026-11-09","\u002Fblog\u002Fmax-client-connections-reached\u002Fcard-800x500.png",{"path":636,"title":637,"description":638,"published":639,"category":586,"image":640,"draft":590},"\u002Fblog\u002Funsupported-provider-provider-is-not-enabled","Supabase-Fehler: \"Unsupported provider: provider is not enabled\"","\"Unsupported provider: provider is not enabled\" heißt: Google-Login ist in deinem Supabase-Projekt aus. Die Lösung, und was bei redirect_uri_mismatch hilft.","2026-11-08","\u002Fblog\u002Funsupported-provider-provider-is-not-enabled\u002Fcard-800x500.png",{"path":642,"title":643,"description":644,"published":645,"category":586,"image":646,"draft":590},"\u002Fblog\u002Fviolates-foreign-key-constraint","Supabase-Fehler \"violates foreign key constraint\" beim Einfügen","Supabase \"insert or update on table violates foreign key constraint\": Deine Zeile zeigt auf eine, die es nicht gibt. Welche, warum, und die Lösung.","2026-11-07","\u002Fblog\u002Fviolates-foreign-key-constraint\u002Fcard-800x500.png",{"path":648,"title":649,"description":650,"published":651,"category":586,"image":652,"draft":590},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","Supabase-Fehler \"null value in column violates not-null constraint\"","Supabase \"null value in column violates not-null constraint\": Eine Pflichtspalte kam leer an. Woher die Null kommt, und die Lösung.","2026-11-06","\u002Fblog\u002Fnull-value-violates-not-null-constraint\u002Fcard-800x500.png",{"path":619,"title":5,"description":589,"published":620,"category":586,"image":607,"draft":590},{"path":332,"title":655,"description":656,"published":657,"category":586,"image":658,"draft":590},"Supabase \"invalid claim: missing sub claim\": niemand ist angemeldet","\"invalid claim: missing sub claim\" heißt: Supabase Auth bekam ein echtes Token ohne Nutzer darin, deinen Projektschlüssel statt einer Sitzung.","2026-11-04","\u002Fblog\u002Finvalid-claim-missing-sub-claim\u002Fcard-800x500.png",{"path":660,"title":661,"description":662,"published":663,"category":586,"image":664,"draft":590},"\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function","\"Failed to send a request to the Edge Function\": der echte Grund","\"Failed to send a request to the Edge Function\" heißt: Der Browser hat keine lesbare Antwort bekommen. Seine Konsole sagt, warum, und ob deine Funktion lief.","2026-11-03","\u002Fblog\u002Ffailed-to-send-a-request-to-the-edge-function\u002Fcard-800x500.png",{"path":234,"title":666,"description":667,"published":668,"category":586,"image":669,"draft":590},"Warum Supabase-E-Mail-Links auf localhost:3000 weiterleiten","Leitet Supabase auf localhost:3000 um, ist die Site URL unverändert, oder deine Adresse fehlt in Redirect URLs. Die Lösung und der Platzhalter, den du meidest.","2026-11-02","\u002Fblog\u002Fsupabase-auth-redirects-to-localhost\u002Fcard-800x500.png",{"path":219,"title":671,"description":672,"published":673,"category":586,"image":674,"draft":590},"Supabase \"Email link is invalid or has expired\" bei einem neuen Link","Bei einem Link von vor einer Minute heißt Supabases \"Email link is invalid or has expired\" meist: Ein Mailfilter hat ihn zuerst benutzt. Prüfen und beheben.","2026-11-01","\u002Fblog\u002Femail-link-is-invalid-or-has-expired\u002Fcard-800x500.png",{"path":676,"title":677,"description":678,"published":679,"category":586,"image":680,"draft":590},"\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout","Supabase \"canceling statement due to statement timeout\" erklärt","Supabase \"canceling statement due to statement timeout\": Eine Abfrage lief länger als ihre Rolle darf, 3 Sekunden für Besucher. Prüf zuerst die RLS-Regel.","2026-10-31","\u002Fblog\u002Fcanceling-statement-due-to-statement-timeout\u002Fcard-800x500.png",{"path":682,"title":683,"description":684,"published":685,"category":686,"image":687,"draft":590},"\u002Fblog\u002Fdatabase-error-deleting-user","\"Database error deleting user\" in Supabase und was mitgelöscht wird","\"Database error deleting user\" in Supabase heißt: Deine Datenbank hat das Löschen abgelehnt. Der Grund steht im Log, die Lösung entscheidet, was mitgeht.","2026-10-30","Backups","\u002Fblog\u002Fdatabase-error-deleting-user\u002Fcard-800x500.png",{"path":689,"title":690,"description":691,"published":692,"category":586,"image":693,"draft":590},"\u002Fblog\u002Fstripe-webhook-no-signatures-found","\"No signatures found matching the expected signature\" bei Supabase","Ein Stripe-Webhook in einer Supabase Edge Function meldet \"No signatures found matching the expected signature\"? Zwei Ursachen. Prüfe weiter.","2026-10-29","\u002Fblog\u002Fstripe-webhook-no-signatures-found\u002Fcard-800x500.png",{"path":695,"title":696,"description":697,"published":698,"category":586,"image":699,"draft":590},"\u002Fblog\u002Fsupabase-invalid-login","\"Invalid login credentials\" in Supabase: die drei Ursachen","Supabase sagt \"Invalid login credentials\" bei falschem Passwort, unbekannter E-Mail und Google-Konto. So erkennst du, welcher Fall es ist.","2026-10-28","\u002Fblog\u002Fsupabase-invalid-login\u002Fcard-800x500.png",{"path":255,"title":701,"description":702,"published":703,"category":586,"image":704,"draft":590},"\"Edge Function returned a non-2xx status code\": der echte Fehler","\"Edge Function returned a non-2xx status code\" heißt: Deine Supabase-Funktion hat mit einem Fehler geantwortet. So liest du den echten.","2026-10-27","\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code\u002Fcard-800x500.png",{"path":706,"title":707,"description":708,"published":709,"category":586,"image":710,"draft":590},"\u002Fblog\u002Fcertificate-not-trusted","Zertifikat nicht vertrauenswürdig: drei Ursachen außer Ablauf","Zertifikat nicht vertrauenswürdig, obwohl das Datum stimmt? Es nennt eine andere Adresse, hat sich selbst signiert oder seiner Kette fehlt ein Glied.","2026-10-26","\u002Fblog\u002Fcertificate-not-trusted\u002Fcard-800x500.png",{"path":712,"title":713,"description":714,"published":715,"category":586,"image":716,"draft":590},"\u002Fblog\u002Finvalid-input-syntax-for-type-uuid","Supabase \"invalid input syntax for type uuid\": was im Zitat steht","Supabase \"invalid input syntax for type uuid\" heißt: Deine App hat etwas geschickt, das keine ID ist. Zitat lesen, Abfrage zurückhalten, Spalte behalten.","2026-10-25","\u002Fblog\u002Finvalid-input-syntax-for-type-uuid\u002Fcard-800x500.png",{"path":718,"title":719,"description":720,"published":721,"category":586,"image":722,"draft":590},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","Supabase \"duplicate key value violates unique constraint\" erklärt","Supabase \"duplicate key value violates unique constraint\" heißt: Der Wert ist schon vergeben. Spalte finden, Lösung wählen, Wert vom Bildschirm fernhalten.","2026-10-24","\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint\u002Fcard-800x500.png",{"path":724,"title":725,"description":726,"published":727,"category":586,"image":728,"draft":590},"\u002Fblog\u002Fsupabase-relation-does-not-exist","Supabase \"relation does not exist\", obwohl die Tabelle da ist","Supabase \"relation does not exist\" oder PGRST205: Keine Tabelle passt zu Name und Schema deiner Abfrage. Vier Prüfungen, und was eine Freigabe öffnet.","2026-10-23","\u002Fblog\u002Fsupabase-relation-does-not-exist\u002Fcard-800x500.png",{"path":730,"title":731,"description":732,"published":733,"category":586,"image":734,"draft":590},"\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\" nennt die Argumente, die deine App geschickt hat. Vergleich sie mit der Funktion.","2026-10-22","\u002Fblog\u002Fsupabase-function-not-found\u002Fcard-800x500.png",{"path":736,"title":737,"description":738,"published":739,"category":586,"image":740,"draft":590},"\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\" heißt meist: Der Name passt nicht. Vier Prüfungen und der Einzeiler zum Neuladen.","2026-10-21","\u002Fblog\u002Fsupabase-schema-cache-column-error\u002Fcard-800x500.png",{"path":742,"title":743,"description":744,"published":745,"category":586,"image":746,"draft":590},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","Supabase \"Email Rate Limit Exceeded\": zwei Limits, ein Fehlercode","Supabase \"Email Rate Limit Exceeded\" begrenzt jede E-Mail deines Projekts: 2 pro Stunde beim eingebauten Absender. Was zählt und wie du es anhebst.","2026-10-20","\u002Fblog\u002Fsupabase-email-rate-limit-exceeded\u002Fcard-800x500.png",{"path":566,"title":748,"description":749,"published":750,"category":586,"image":751,"draft":590},"Supabase \"Invalid Refresh Token: Refresh Token Not Found\": 3 Ursachen","Supabase \"Invalid Refresh Token: Refresh Token Not Found\" meldet deine Nutzer ab. Drei Ursachen, und wie das Auth-Log sie trennt.","2026-10-19","\u002Fblog\u002Fsupabase-users-logged-out\u002Fcard-800x500.png",{"path":753,"title":754,"description":755,"published":756,"category":586,"image":757,"draft":590},"\u002Fblog\u002Fpermission-denied-for-schema-public","Supabase \"permission denied for schema public\": drei Ursachen","Supabase \"permission denied for schema public\" heißt: Ein Grant auf das Schema fehlt. Was ihn entfernt hat und welche Zeile ihn zurückbringt.","2026-10-18","\u002Fblog\u002Fpermission-denied-for-schema-public\u002Fcard-800x500.png",{"path":759,"title":760,"description":761,"published":762,"category":586,"image":763,"draft":590},"\u002Fblog\u002Fsupabase-bucket-not-found","Supabase \"Bucket not found\": die drei Dinge, die es bedeutet","Supabase \"Bucket not found\" ist eins von drei Dingen: ein öffentlicher Link zu einem privaten Bucket, ein ungenauer Name oder das falsche Projekt.","2026-10-17","\u002Fblog\u002Fsupabase-bucket-not-found\u002Fcard-800x500.png",{"path":765,"title":766,"description":767,"published":768,"category":586,"image":769,"draft":590},"\u002Fblog\u002Fsupabase-invalid-jwt","Supabase invalid JWT: Welcher Schlüssel streikt hier?","Ein Supabase invalid JWT ist PGRST301: ein signiertes Token hat die Prüfung nicht bestanden. In neueren Projekten ist das die Sitzung, nicht der API-Schlüssel.","2026-10-16","\u002Fblog\u002Fsupabase-invalid-jwt\u002Fcard-800x500.png",{"path":771,"title":772,"description":773,"published":774,"category":586,"image":775,"draft":590},"\u002Fblog\u002Fsupabase-single-row-error","Supabase \"multiple (or no) rows returned\" heißt meist: keine Zeilen","Supabase gibt PGRST116 zurück, \"JSON object requested, multiple (or no) rows returned\", wenn die Abfrage nichts fand. Versteckte Zeilen wirken fehlend.","2026-10-15","\u002Fblog\u002Fsupabase-single-row-error\u002Fcard-800x500.png",{"path":777,"title":778,"description":779,"published":780,"category":586,"image":781,"draft":590},"\u002Fblog\u002Fdatabase-error-saving-new-user","\"Database error saving new user\" in Supabase: wo du nachsiehst","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.","2026-10-14","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",{"path":783,"title":784,"description":785,"published":786,"category":586,"image":787,"draft":590},"\u002Fblog\u002Fwhat-is-supabase","Was ist Supabase? Die Datenbank, die dein Builder ausgesucht hat","Was ist Supabase: die Datenbank, der Login und der Dateispeicher hinter deiner App. Supabase betreibt die Server, die Regeln zu deinen Zeilen gehören dir.","2026-10-13","\u002Fblog\u002Fwhat-is-supabase\u002Fcard-800x500.png",{"path":789,"title":790,"description":791,"published":792,"category":586,"image":793,"draft":590},"\u002Fblog\u002Faws-access-key-exposed-in-frontend","Ein offengelegter AWS-Schlüssel im Frontend ist kein OpenAI-Key","Ein im Frontend offengelegter AWS-Zugriffsschlüssel liest und schreibt deinen Speicher. Die Lösung ist meist eine presigned URL, kein neuer Schlüssel.","2026-10-12","\u002Fblog\u002Faws-access-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":795,"title":796,"description":797,"published":798,"category":586,"image":799,"draft":590},"\u002Fblog\u002Fstorage-upload-violates-row-level-security","\"Row-level security policy for table objects\" beim Upload","\"New row violates row-level security policy for table objects\" heißt: Deinem Upload fehlt eine insert-Regel. Ein öffentlicher Bucket fügt keine hinzu.","2026-10-11","\u002Fblog\u002Fstorage-upload-violates-row-level-security\u002Fcard-800x500.png",{"path":801,"title":802,"description":803,"published":804,"category":586,"image":805,"draft":590},"\u002Fblog\u002Fbase44-security-scan","Base44 Security Scan: das, was nur er sehen kann","Der Base44 Security Scan prüft sieben Arten von Problemen von innen. Hier ist die Hälfte, die er liest und sonst niemand, und die Hälfte, die er nie ansieht.","2026-10-10","\u002Fblog\u002Fbase44-security-scan\u002Fcard-800x500.png",{"path":807,"title":808,"description":809,"published":810,"category":586,"image":811,"draft":590},"\u002Fblog\u002Fapi-key-leaked-what-to-do","Dein API-Key wurde geleakt. Die richtige Reihenfolge","Ein API-Key wurde geleakt und du weißt nicht, was zuerst zu tun ist. Nicht jeder Key im Frontend ist ein Leck, und die Reihenfolge zählt mehr als das Tempo.","2026-10-09","\u002Fblog\u002Fapi-key-leaked-what-to-do\u002Fcard-800x500.png",{"path":813,"title":814,"description":815,"published":816,"category":586,"image":817,"draft":590},"\u002Fblog\u002Finfinite-recursion-in-policy-for-relation","\"Infinite recursion detected in policy\" ohne RLS abzuschalten","\"Infinite recursion detected in policy for relation\" heißt: Deine Policy hat die Tabelle gefragt, die sie schützt. So brichst du den Kreis.","2026-10-08","\u002Fblog\u002Finfinite-recursion-in-policy-for-relation\u002Fcard-800x500.png",{"path":819,"title":820,"description":821,"published":822,"category":586,"image":823,"draft":590},"\u002Fblog\u002Fno-api-key-found-in-request","\"No API key found in request\" in Supabase, und die falsche Lösung","\"No API key found in request\" heißt, deine Supabase-Anfrage kam ohne Schlüssel an. Die meisten Antworten zeigen stattdessen auf deine Datenbankregeln.","2026-10-07","\u002Fblog\u002Fno-api-key-found-in-request\u002Fcard-800x500.png",{"path":825,"title":826,"description":827,"published":828,"category":586,"image":829,"draft":590},"\u002Fblog\u002Fis-base44-safe","Ist Base44 sicher? Was 5.442 echte Base44-Apps zeigten","Ist Base44 sicher? Wir haben 5.442 laufende Base44-Apps mit neun Checks geprüft. Fast alle bekamen ein B, aus Gründen, die der Inhaber nie gewählt hat.","2026-10-06","\u002Fblog\u002Fis-base44-safe\u002Fcard-800x500.png",{"path":391,"title":831,"description":832,"published":833,"category":586,"image":834,"draft":590},"API-Schlüssel verstecken: ab in eine Supabase Edge Function","Einen API-Schlüssel verstecken heißt, ihn aus dem Browser zu nehmen. Eine Supabase Edge Function ist der kleinste Ort dafür, und zwei Schritte zählen mehr.","2026-10-05","\u002Fblog\u002Fmove-a-secret-to-an-edge-function\u002Fcard-800x500.png",{"path":836,"title":837,"description":838,"published":839,"category":586,"image":840,"draft":590},"\u002Fblog\u002Fenv-file-exposed-on-your-server","Ist deine .env-Datei öffentlich? Zwölf Pfade zum Prüfen","Ist deine .env-Datei auf deinem eigenen Webserver öffentlich? Zwölf Adressen sagen es dir, und ein Treffer heißt: alles darin ist längst öffentlich.","2026-10-04","\u002Fblog\u002Fenv-file-exposed-on-your-server\u002Fcard-800x500.png",{"path":842,"title":843,"description":844,"published":845,"category":586,"image":846,"draft":590},"\u002Fblog\u002Fis-v0-safe","v0-Sicherheit: alle 1.790 gescannten v0-Apps bekamen ein A","v0-Sicherheit, gemessen an 1.790 laufenden v0-Apps: Jede bekam ein A. Nur 17 nannten eine Datenbank, und genau das misst das A vor allem.","2026-10-03","\u002Fblog\u002Fis-v0-safe\u002Fcard-800x500.png",{"path":848,"title":849,"description":850,"published":851,"category":586,"image":852,"draft":590},"\u002Fblog\u002Fis-bolt-safe","Ist Bolt sicher? Was 1.123 echte Bolt-Apps zeigten","Ist Bolt sicher? Wir haben 1.123 laufende Bolt-Apps mit neun Checks geprüft. Das Hosting war sauber. Die Funde waren Schlüssel und offene Tabellen in den Apps.","2026-10-02","\u002Fblog\u002Fis-bolt-safe\u002Fcard-800x500.png",{"path":854,"title":855,"description":856,"published":857,"category":586,"image":858,"draft":590},"\u002Fblog\u002Fis-supabase-down-or-your-app","Ist Supabase down oder liegt es an deiner App? So erkennst du es","Ist Supabase down oder liegt es an deiner App? Ein pausiertes Projekt, eine volle Datenbank und ein eigener Fehler sehen gleich aus. Vier Prüfungen helfen.","2026-10-01","\u002Fblog\u002Fis-supabase-down-or-your-app\u002Fcard-800x500.png",{"path":860,"title":861,"description":862,"published":863,"category":586,"image":864,"draft":590},"\u002Fblog\u002Fdoes-supabase-encrypt-my-data","Verschlüsselt Supabase meine Daten? Ja. Wovor das schützt","Verschlüsselt Supabase Daten? Ja: AES-256 im Ruhezustand, TLS bei der Übertragung, SOC 2 und ISO 27001. Was jedes abdeckt und welches Leck keines stoppt.","2026-09-30","\u002Fblog\u002Fdoes-supabase-encrypt-my-data\u002Fcard-800x500.png",{"path":866,"title":867,"description":868,"published":869,"category":586,"image":870,"draft":590},"\u002Fblog\u002Fsupabase-free-plan-limits","Supabase Gratis-Tarif: die Limits und was an jedem passiert","Die Limits des Supabase-Gratis-Tarifs: 500 MB Datenbank, 5 GB Egress und keine Backups. Was an jeder Grenze passiert und was $25 für Pro ändern.","2026-09-29","\u002Fblog\u002Fsupabase-free-plan-limits\u002Fcard-800x500.png",{"path":872,"title":873,"description":874,"published":875,"category":686,"image":876,"draft":590},"\u002Fblog\u002Ftest-your-supabase-backup","Teste dein Supabase-Backup, bevor du es brauchst","So testest du dein Supabase-Backup: in ein Übungsprojekt einspielen, Zeilen zählen, anmelden und die Zeile suchen, die einer abgeschnittenen Datei fehlt.","2026-09-28","\u002Fblog\u002Ftest-your-supabase-backup\u002Fcard-800x500.png",{"path":878,"title":879,"description":880,"published":881,"category":686,"image":882,"draft":590},"\u002Fblog\u002Fsupabase-backup-github-action","Kostenloses Supabase-Backup per GitHub Action, mit Haken","Eine Supabase-Backup-GitHub-Action kostet nichts und passt für viele Apps. Der Workflow, der richtige Connection String und das Egress pro Lauf.","2026-09-27","\u002Fblog\u002Fsupabase-backup-github-action\u002Fcard-800x500.png",{"path":884,"title":885,"description":886,"published":887,"category":686,"image":888,"draft":590},"\u002Fblog\u002Fdownload-your-supabase-backup","Warum du dein Supabase-Backup nicht herunterladen kannst","Dein Supabase-Backup kannst du auf aktuellen Projekten nicht herunterladen, weil die Tageskopie physisch ist. Wie du es prüfst und selbst eine Kopie hältst.","2026-09-26","\u002Fblog\u002Fdownload-your-supabase-backup\u002Fcard-800x500.png",{"path":890,"title":891,"description":892,"published":887,"category":586,"image":893,"draft":590},"\u002Fblog\u002Fsupabase-permission-denied-for-table","Supabase \"permission denied for table\": der fehlende Grant","Ab 30. Oktober antwortet eine neue Supabase-Tabelle mit \"permission denied for table\", bis du Zugriff erteilst. Der Grant aus der E-Mail ist die halbe Lösung.","\u002Fblog\u002Fsupabase-permission-denied-for-table\u002Fcard-800x500.png",{"path":895,"title":896,"description":897,"published":898,"category":586,"image":899,"draft":590},"\u002Fblog\u002Fopen-api-endpoint-exposed","Ist ein offener API-Endpunkt ein Sicherheitsproblem? Sieh ins JSON","Dein Scan hat einen offenen API-Endpunkt gemeldet. Ob das zählt, hängt davon ab, was zurückkam, und die meisten hier gehörten der Plattform.","2026-09-25","\u002Fblog\u002Fopen-api-endpoint-exposed\u002Fcard-800x500.png",{"path":901,"title":902,"description":903,"published":904,"category":586,"image":905,"draft":590},"\u002Fblog\u002Flovable-security-scan","Lovable Security Scan: das Eine, was er nicht beweist","Lovable Security Scan: was Quick Scan und Deep Scan prüfen, wann welcher läuft, und das Eine, was kein Scan von innen beweisen kann.","2026-09-24","\u002Fblog\u002Flovable-security-scan\u002Fcard-800x500.png",{"path":907,"title":908,"description":909,"published":910,"category":686,"image":911,"draft":590},"\u002Fblog\u002Fsupabase-backup-auth-users","Warum in deinem Supabase-Dump keine Nutzer stehen","Führe supabase db dump allein aus und du bekommst die Form deiner Datenbank und keine einzige Zeile, und das auth-Schema mit deinen Nutzern fehlt ganz.","2026-09-23","\u002Fblog\u002Fsupabase-backup-auth-users\u002Fcard-800x500.png",{"path":913,"title":914,"description":915,"published":916,"category":586,"image":917,"draft":590},"\u002Fblog\u002Fdomain-and-certificate-expiry","Domain abgelaufen, Website offline: was jetzt passiert","Deine Domain ist abgelaufen und deine Website ist offline. Welche Frist jetzt läuft, warum das Zertifikat das kleinere Problem ist, und wie du beides prüfst.","2026-09-22","\u002Fblog\u002Fdomain-and-certificate-expiry\u002Fcard-800x500.png",{"path":919,"title":920,"description":921,"published":922,"category":586,"image":923,"draft":590},"\u002Fblog\u002Fis-lovable-safe","Ist Lovable sicher? Was 18.554 echte Lovable-Apps zeigten","Ist Lovable sicher? Wir haben 18.554 laufende Lovable-Apps mit neun Checks geprüft. Die Plattform war die sauberste von fünf. Die Funde saßen in den Apps.","2026-09-21","\u002Fblog\u002Fis-lovable-safe\u002Fcard-800x500.png",{"path":925,"title":926,"description":927,"published":928,"category":586,"image":929,"draft":590},"\u002Fblog\u002Fvibe-coded-app-security-checklist","Die Sicherheits-Checkliste für Vibe-Coding, in neun Prüfungen","Eine Sicherheits-Checkliste für Vibe-Coding mit neun Punkten, die jeder von außen an deiner Live-App nachprüfen kann, jeder mit einem Test in einer Zeile.","2026-09-20","\u002Fblog\u002Fvibe-coded-app-security-checklist\u002Fcard-800x500.png",{"path":931,"title":932,"description":933,"published":934,"category":586,"image":935,"draft":590},"\u002Fblog\u002Fstripe-secret-key-in-frontend","Ein geheimer Stripe-Schlüssel im Frontend kann Geld bewegen","Ein geheimer Stripe-Schlüssel im Frontend kann erstatten, abbuchen und jeden Kundendatensatz lesen, den du hast. Dein pk_live_-Schlüssel gehört dorthin.","2026-09-19","\u002Fblog\u002Fstripe-secret-key-in-frontend\u002Fcard-800x500.png",{"path":937,"title":938,"description":939,"published":940,"category":586,"image":941,"draft":590},"\u002Fblog\u002Fvite-and-next-public-env-vars","Vite-Env-Variablen offengelegt: der Präfix heißt veröffentlichen","Vite-Env-Variablen offengelegt: Deine App hat getan, was der Präfix verlangt. VITE_ und NEXT_PUBLIC_ heißen veröffentlichen, und die KI kannte den Preis nie.","2026-09-18","\u002Fblog\u002Fvite-and-next-public-env-vars\u002Fcard-800x500.png",{"path":943,"title":944,"description":945,"published":946,"category":586,"image":947,"draft":590},"\u002Fblog\u002Fbase44-source-maps","Base44-Sicherheit: was ein Scan meldet und was du ändern kannst","Base44-Sicherheit auf 5.438 gescannten Apps: Drei Befunde auf fast jeder gehören der Plattform, die Source Map ist das Base44-Badge, und deine Liste ist kurz.","2026-09-17","\u002Fblog\u002Fbase44-source-maps\u002Fcard-800x500.png",{"path":949,"title":950,"description":951,"published":952,"category":586,"image":953,"draft":590},"\u002Fblog\u002Fis-cursor-ai-safe","Ist Cursor AI sicher? Editor, Code und die App, die du veröffentlichst","Ist Cursor AI sicher? Drei Fragen in einer Suche: was Cursor behält, was sein Code falsch macht und ob deine veröffentlichte App offen steht.","2026-09-16","\u002Fblog\u002Fis-cursor-ai-safe\u002Fcard-800x500.png",{"path":955,"title":956,"description":957,"published":958,"category":586,"image":959,"draft":590},"\u002Fblog\u002Fis-replit-safe","Ist Replit sicher? Was wir in 3.042 Replit-Apps gefunden haben","Ist Replit sicher? Wir haben 3.042 laufende Replit-Apps mit neun externen Checks geprüft. Die Funde saßen in der veröffentlichten App, nicht im Hosting.","2026-09-15","\u002Fblog\u002Fis-replit-safe\u002Fcard-800x500.png",{"path":961,"title":962,"description":963,"published":964,"category":686,"image":965,"draft":590},"\u002Fblog\u002Fsupabase-storage-backup","Supabase Storage Backup: deine Datenbankkopie hat keine Dateien","Ein Supabase Storage Backup ist eine eigene Aufgabe. Datenbank-Backups enthalten die Liste deiner Dateien und keine davon, also bleibt jeder Upload kaputt.","2026-09-14","\u002Fblog\u002Fsupabase-storage-backup\u002Fcard-800x500.png",{"path":967,"title":968,"description":969,"published":970,"category":686,"image":971,"draft":590},"\u002Fblog\u002Fsupabase-point-in-time-recovery","Supabase Point-in-Time Recovery: Kosten und Grenzen","Supabase Point-in-Time Recovery spult deine Datenbank auf jede Sekunde der letzten Woche zurück. $100 im Monat zusätzlich zu Pro, und nur die Datenbank.","2026-09-13","\u002Fblog\u002Fsupabase-point-in-time-recovery\u002Fcard-800x500.png",{"path":973,"title":974,"description":975,"published":976,"category":686,"image":977,"draft":590},"\u002Fblog\u002Fsupabase-project-paused-recover","Supabase-Projekt pausiert? Deine Daten sind noch da","Supabase hat dein Projekt nach einer Woche ohne Aktivität pausiert. Gelöscht ist nichts, Wiederherstellen steht neben dem Namen, und du hast ein Jahr.","2026-09-12","\u002Fblog\u002Fsupabase-project-paused-recover\u002Fcard-800x500.png",{"path":979,"title":980,"description":981,"published":982,"category":586,"image":983,"draft":590},"\u002Fblog\u002Fsafest-ai-app-builder","Welcher KI-App-Builder ist am sichersten? 30.998 Apps im Test","Welcher KI-App-Builder ist am sichersten? Wir haben 30.998 aktive Apps von Lovable, Base44, Replit, v0 und Bolt gescannt. Der Builder entscheidet das nicht.","2026-09-11","\u002Fblog\u002Fsafest-ai-app-builder\u002Fcard-800x500.png",{"path":985,"title":986,"description":987,"published":988,"category":586,"image":989,"draft":590},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security für jede Supabase-Tabelle aktivieren und prüfen","Row Level Security in Supabase ohne Policy sperrt eine Tabelle komplett. Eine Policy ohne den Schalter bringt gar nichts. Hier ist das SQL, und der Test.","2026-09-10","\u002Fblog\u002Fenable-rls-on-every-supabase-table\u002Fcard-800x500.png",{"path":991,"title":992,"description":993,"published":994,"category":586,"image":995,"draft":590},"\u002Fblog\u002Fsupabase-rls-disabled-in-public","Supabase \"RLS disabled in public\": was die Warnung übersieht","Supabase meldet \"RLS disabled in public\" als Fehler. Zur Lese-Policy, die deine Tabelle genauso offen lässt, sagt der Advisor gar nichts.","2026-09-09","\u002Fblog\u002Fsupabase-rls-disabled-in-public\u002Fcard-800x500.png",{"path":450,"title":997,"description":998,"published":999,"category":586,"image":1000,"draft":590},"Geleakten Supabase-service_role-Schlüssel richtig tauschen","Supabase sagt: erst das Leck schließen. Andere Anleitungen: sofort tauschen. Was richtig ist, hängt davon ab, wohin dein service_role-Schlüssel gelangt ist.","2026-09-08","\u002Fblog\u002Frotate-supabase-service-role-key\u002Fcard-800x500.png",{"path":1002,"title":1003,"description":1004,"published":1005,"category":586,"image":1006,"draft":590},"\u002Fblog\u002Fvibe-coding-security-scanners-compared","Vibe-Coding-Security-Scanner im Vergleich, unserer eingeschlossen","Der beste Vibe-Coding-Security-Scanner hängt an drei Fragen, die keine Funktionsliste beantwortet. Acht Tools im Vergleich, mit Preisen und unseren Lücken.","2026-09-07","\u002Fblog\u002Fvibe-coding-security-scanners-compared\u002Fcard-800x500.png",{"path":1008,"title":1009,"description":1010,"published":1011,"category":586,"image":1012,"draft":590},"\u002Fblog\u002Fsupabase-security-checker","Supabase Security Checker: die fünf Prüfungen selbst machen","Ein Supabase Security Checker liest deine veröffentlichte App statt deiner Projekteinstellungen. Hier sind die fünf Prüfungen und wie du jede selbst ausführst.","2026-09-06","\u002Fblog\u002Fsupabase-security-checker\u002Fcard-800x500.png",{"path":1014,"title":1015,"description":1016,"published":1017,"category":586,"image":1018,"draft":590},"\u002Fblog\u002Fvibe-coding-security-scanner","Vibe-Coding-Security-Scanner: was ein URL-Scan übersieht","Ein Vibe-Coding-Security-Scanner liest deine laufende App von außen. Was das abdeckt, die vier Dinge, die er nicht sehen kann, und wie du das Ergebnis liest.","2026-09-05","\u002Fblog\u002Fvibe-coding-security-scanner\u002Fcard-800x500.png",{"path":1020,"title":1021,"description":1022,"published":1023,"category":586,"image":1024,"draft":590},"\u002Fblog\u002Fmissing-security-headers","Fehlende Sicherheitsheader: wann sie wirklich zählen","Fehlende Sicherheitsheader ist unser häufigster Befund. Wogegen sie schützen, und wann sie die unwichtigste Zeile in deinem Bericht sind.","2026-09-04","\u002Fblog\u002Fmissing-security-headers\u002Fcard-800x500.png",{"path":1026,"title":1027,"description":1028,"published":1029,"category":586,"image":1030,"draft":590},"\u002Fblog\u002Fopenai-api-key-exposed-in-frontend","Dein OpenAI-API-Schlüssel liegt im Frontend. Tausch ihn aus.","Ein OpenAI-API-Schlüssel im Frontend lässt sich an keine Domain binden. Tausch ihn heute, leg den Aufruf hinter deinen Server und begrenze das Budget.","2026-09-03","\u002Fblog\u002Fopenai-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1032,"title":1033,"description":1034,"published":1035,"category":586,"image":1036,"draft":590},"\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps","API-Schlüssel im Frontend: was 30.998 Apps wirklich ausliefern","Ein API-Schlüssel im Frontend ist meistens ein Google-Maps-Schlüssel. Wir haben 30.998 aktive Vibe-Coding-Apps gescannt und gezählt, was wirklich austritt.","2026-09-02","\u002Fblog\u002Fwhat-secrets-leak-from-vibe-coded-apps\u002Fcard-800x500.png",{"path":1038,"title":1039,"description":1040,"published":1041,"category":686,"image":1042,"draft":590},"\u002Fblog\u002Fsupabase-backup-tools-compared","Supabase-Backup-Tools im Vergleich, unseres eingeschlossen","Vier Arten von Supabase-Backup-Tool, was jedes wirklich kopiert und wann eine kostenlose GitHub Action jeden Anbieter schlägt, uns eingeschlossen.","2026-09-01","\u002Fblog\u002Fsupabase-backup-tools-compared\u002Fcard-800x500.png",{"path":1044,"title":1045,"description":1046,"published":1047,"category":586,"image":1048,"draft":590},"\u002Fblog\u002Freplit-secrets-explained","Secrets in Replit nutzen, und was trotzdem veröffentlicht wird","Secrets in Replit nutzen: anlegen, auslesen und die zwei Gründe beheben, warum undefined zurückkommt. Dazu die Schlüssel, die das Werkzeug nicht schützt.","2026-08-31","\u002Fblog\u002Freplit-secrets-explained\u002Fcard-800x500.png",{"path":1050,"title":1051,"description":1052,"published":1053,"category":686,"image":1054,"draft":590},"\u002Fblog\u002Fback-up-supabase-free-tier","Supabase Gratis-Tarif: Backup ohne Terminal selbst machen","Im Supabase Gratis-Tarif gibt es keine Backups, die Kopie musst du selbst machen. Wie das im Dashboard geht und was der CSV-Weg auslässt.","2026-08-30","\u002Fblog\u002Fback-up-supabase-free-tier\u002Fcard-800x500.png",{"path":1056,"title":1057,"description":1058,"published":1059,"category":586,"image":1060,"draft":590},"\u002Fblog\u002Fis-supabase-secure","Ist Supabase sicher? Ja. Dein Projekt ist eine eigene Frage","Ist Supabase sicher? Die Plattform ist auditiert, verschlüsselt und pentestet. Supabase schreibt selbst auf, wo das aufhört und deine Einstellungen anfangen.","2026-08-29","\u002Fblog\u002Fis-supabase-secure\u002Fcard-800x500.png",{"path":1062,"title":1063,"description":1064,"published":1065,"category":586,"image":1066,"draft":590},"\u002Fblog\u002Fwhere-to-find-supabase-api-keys","Wo du deine Supabase API-Keys findest: anon, service_role, URL","Projekt-URL, anon-Schlüssel und service_role-Schlüssel liegen auf einer Seite im Dashboard. Wo sie ist, und welcher der vier Werte in deine App gehört.","2026-08-28","\u002Fblog\u002Fwhere-to-find-supabase-api-keys\u002Fcard-800x500.png",{"path":1068,"title":1069,"description":1070,"published":1071,"category":586,"image":1072,"draft":590},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","New row violates row-level security policy in Supabase: was jetzt?","\"New row violates row-level security policy\" heißt, Supabase hat einen Schreibvorgang abgelehnt. Die schnelle Lösung öffnet die Tabelle wieder für alle.","2026-08-27","\u002Fblog\u002Fnew-row-violates-row-level-security-policy\u002Fcard-800x500.png",{"path":1074,"title":1075,"description":1076,"published":1077,"category":586,"image":1078,"draft":590},"\u002Fblog\u002Fcors-wildcard-security-risk","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist nicht.","Ist eine CORS-Wildcard ein Sicherheitsrisiko? Meist ist sie die Voreinstellung deines Builders und gibt nichts preis, was dein Server nicht ohnehin herausgab.","2026-08-26","\u002Fblog\u002Fcors-wildcard-security-risk\u002Fcard-800x500.png",{"path":1080,"title":1081,"description":1082,"published":1083,"category":686,"image":1084,"draft":590},"\u002Fblog\u002Fsupabase-branching-is-not-a-backup","Supabase Branching ist kein Backup. Es geht nur vorwärts.","Warum Supabase Branching kein Backup ist: Ein Branch startet ohne deine Daten, und ein Merge bringt nur das Schema. Wofür es gut ist und was stattdessen hilft.","2026-08-25","\u002Fblog\u002Fsupabase-branching-is-not-a-backup\u002Fcard-800x500.png",{"path":1086,"title":1087,"description":1088,"published":1089,"category":686,"image":1090,"draft":590},"\u002Fblog\u002Fhow-to-restore-a-supabase-backup","Supabase-Backup wiederherstellen, und was danach kaputt ist","Wie du ein Supabase-Backup aus dem Dashboard oder aus einer Dump-Datei wiederherstellst, was ersetzt wird und warum die App danach kaputt sein kann.","2026-08-24","\u002Fblog\u002Fhow-to-restore-a-supabase-backup\u002Fcard-800x500.png",{"path":1092,"title":1093,"description":1094,"published":1095,"category":586,"image":1096,"draft":590},"\u002Fblog\u002Fsupabase-storage-bucket-public","Dein Supabase-Storage-Bucket ist öffentlich. Ist das ein Problem?","Ein öffentlicher Supabase-Storage-Bucket heißt: Wer die URL einer Datei hat, kann sie öffnen. Er heißt nicht, dass jemand den Inhalt auflisten darf.","2026-08-23","\u002Fblog\u002Fsupabase-storage-bucket-public\u002Fcard-800x500.png",{"path":1098,"title":1099,"description":1100,"published":1101,"category":586,"image":1102,"draft":590},"\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend","Ist ein Google-API-Schlüssel im Frontend ein Problem?","Ein Google-API-Schlüssel im Frontend ist der Fund unseres Scanners Nummer eins, und meistens unbedenklich. Eine kostenlose Einstellung entscheidet darüber.","2026-08-22","\u002Fblog\u002Fgoogle-api-key-exposed-in-frontend\u002Fcard-800x500.png",{"path":1104,"title":1105,"description":1106,"published":1107,"category":686,"image":1108,"draft":590},"\u002Fblog\u002Fai-agent-deleted-my-database","Ein KI-Agent hat meine Supabase-Daten gelöscht. Was hole ich zurück?","Ein KI-Agent hat Daten aus deiner Datenbank gelöscht. Was du zurückholst, stand schon vorher fest, und die nächsten Minuten entscheiden über den Rest.","2026-08-21","\u002Fblog\u002Fai-agent-deleted-my-database\u002Fcard-800x500.png",{"path":1110,"title":1111,"description":1112,"published":1113,"category":586,"image":1114,"draft":590},"\u002Fblog\u002Fcan-anyone-read-your-supabase-database","Kann jeder deine Supabase-Datenbank lesen? 3.680 Apps im Test","Kann jeder deine Supabase-Datenbank ohne Login lesen? Wir haben 30.998 aktive Apps aus KI-Buildern gescannt und gemessen, wie oft die Antwort ja lautet.","2026-08-18","\u002Fblog\u002Fcan-anyone-read-your-supabase-database\u002Fcard-800x500.png",{"path":1116,"title":1117,"description":1118,"published":1113,"category":586,"image":1119,"draft":590},"\u002Fblog\u002Fsource-maps-exposed-in-production","Source-Maps öffentlich: deine App veröffentlicht ihren Quellcode","Eine öffentliche Source-Map lässt jeden den Originalcode deiner App lesen, Kommentare inklusive. Der 30-Sekunden-Check, und was wirklich zählt.","\u002Fblog\u002Fsource-maps-exposed-in-production\u002Fcard-800x500.png",{"path":1121,"title":1122,"description":1123,"published":1124,"category":586,"image":1125,"draft":590},"\u002Fblog\u002Fsupabase-new-api-keys","Supabase publishable key: ist er derselbe wie der anon key?","Supabase hat anon und service_role durch öffentliche und geheime Schlüssel ersetzt. Welcher gehört in deine App, und welcher nie?","2026-08-12","\u002Fblog\u002Fsupabase-new-api-keys\u002Fcard-800x500.png",{"path":1127,"title":1128,"description":1129,"published":1130,"category":686,"image":1131,"draft":590},"\u002Fblog\u002Fdoes-supabase-back-up-my-database","Sichert Supabase meine Datenbank? Das hängt von deinem Tarif ab.","Sichert Supabase deine Datenbank? Auf bezahlten Tarifen täglich, im Gratis-Tarif gar nicht. So findest du heraus, was du hast und was es nicht abdeckt.","2026-08-11","\u002Fblog\u002Fdoes-supabase-back-up-my-database\u002Fcard-800x500.png",{"path":1133,"title":1134,"description":1135,"published":1136,"category":586,"image":1137,"draft":590},"\u002Fblog\u002Fsupabase-rls-on-but-table-still-public","Supabase Row Level Security ist an. Die Tabelle ist trotzdem offen.","Supabase Row Level Security anzuschalten schützt keine Tabelle. Erst deine Policies tun das, und die, die deine App repariert hat, lässt oft alle herein.","2026-08-10","\u002Fblog\u002Fsupabase-rls-on-but-table-still-public\u002Fcard-800x500.png",{"path":1139,"title":1140,"description":1141,"published":1136,"category":686,"image":1142,"draft":590},"\u002Fblog\u002Fversion-history-is-not-a-backup","Der Versionsverlauf ist kein Backup. Er holt keine Tabelle zurück.","Lovable und Bolt führen einen Versionsverlauf für deinen Code. Deine Datenbank ist ein eigener Dienst, und ein Rücksprung holt deine Daten nicht zurück.","\u002Fblog\u002Fversion-history-is-not-a-backup\u002Fcard-800x500.png",{"path":1144,"title":1145,"description":1146,"published":1147,"category":686,"image":1148,"draft":590},"\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database","Drei Wege, eine Supabase-Datenbank zu sichern, und was fehlt","Das Dashboard, pg_dump und ein verwalteter Dienst. Was jeder Weg wirklich sichert, was er stillschweigend auslässt und welcher den Kontoverlust übersteht.","2026-08-09","\u002Fblog\u002Fthree-ways-to-back-up-a-supabase-database\u002Fcard-800x500.png",{"path":1150,"title":1151,"description":1152,"published":1147,"category":586,"image":1153,"draft":590},"\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend","Welche API-Schlüssel im Frontend sicher sind, und welche nicht","Dein Supabase-anon-Schlüssel darf öffentlich sein. Der service_role-Schlüssel nicht. Er ignoriert jede Regel, die du setzt. So erkennst du den Unterschied.","\u002Fblog\u002Fwhich-api-keys-are-safe-in-your-frontend\u002Fcard-800x500.png",1794213638647]