[{"data":1,"prerenderedAt":1090},["ShallowReactive",2],{"blog-de-database-error-saving-new-user":3,"blog-index-de":564},{"id":4,"title":5,"body":6,"category":521,"cover":522,"coverAlt":523,"description":524,"draft":525,"extension":526,"faq":527,"image":543,"keywords":544,"meta":552,"navigation":553,"ogTitle":554,"path":555,"published":556,"seo":557,"stem":558,"tldr":559,"updated":556,"__hash__":563},"blog_de\u002Fblog\u002Fdatabase-error-saving-new-user.md","\"Database error saving new user\" in Supabase: wo du nachsiehst",{"type":7,"value":8,"toc":508},"minimark",[9,13,24,27,35,40,43,57,60,63,76,82,86,89,92,95,120,132,138,142,149,159,162,165,169,175,182,196,201,207,211,217,220,226,237,244,257,261,264,273,285,310,316,326,337,348,366,370,373,379,399,402,406,412,421,436,446,463,467,495],[10,11,12],"p",{},"Jemand will ein Konto in deiner App anlegen und bekommt eine Antwort, in der es\ngar nicht um ihn geht:",[14,15,20],"pre",{"className":16,"code":18,"language":19},[17],"language-text","Database error saving new user\n","text",[21,22,18],"code",{"__ignoreMap":23},"",[10,25,26],{},"Niemand kann sich registrieren. Das Formular lief, als du es gebaut hast, dein\nProjekt ist oben, und das Einzige, was du hast, ist ein Satz ohne Tabelle, ohne\nSpalte und ohne Grund.",[10,28,29,30,34],{},"Hier ist der Punkt, den ein Guide nach dem anderen falsch macht: ",[31,32,33],"strong",{},"diese Meldung\nwurde gebaut, um dir nichts zu sagen, und dein echter Fehler steht längst\nwoanders geschrieben."," Such den Satz, und man reicht dir einen Block SQL zum\nEinsetzen, meistens irgendwessen Version einer Funktion, die in eine Tabelle mit\nfremden Spaltennamen schreibt. Das klappt entweder, oder du hast jetzt zwei\nProbleme statt einem. Die Zeile, die sagt, was schiefging, liegt in den Logs\ndeines eigenen Projekts, und sie nennt die Tabelle.",[36,37,39],"h2",{"id":38},"was-database-error-saving-new-user-bedeutet","Was \"Database error saving new user\" bedeutet",[10,41,42],{},"Supabase hat das neue Konto angenommen und dann wieder zurückgenommen, weil\netwas, das an der Registrierung hängt, fehlgeschlagen ist.",[10,44,45,46,49,50,53,54,56],{},"Eine Registrierung schreibt eine Zeile, in eine Tabelle namens ",[21,47,48],{},"auth.users",", die\nSupabase für dich verwaltet. In den meisten Projekten hängt an diesem\nSchreibvorgang noch etwas: ein Trigger, der die neue Person in eine eigene\n",[21,51,52],{},"profiles","-Tabelle kopiert, ein Constraint, ein Fremdschlüssel. Wirft dieses\nangehängte Etwas einen Fehler, rollt die Datenbank den gesamten Vorgang zurück,\nund dazu gehört die Zeile in ",[21,55,48],{},". Es bleibt kein halbfertiges Konto\nübrig. Es steht aber auch nichts in der Antwort, was dir sagt, welches angehängte\nEtwas es war.",[10,58,59],{},"Stell dir einen Tresen mit einem Hinterzimmer vor. Jemand trägt sich vorn in das\nBuch ein, und ein Angestellter nimmt den neuen Namen mit nach hinten, um ihn in\nein zweites Buch zu übertragen. Kommt der Angestellte nicht in den Raum, in dem\ndieses zweite Buch liegt, dann gilt die Anmeldung nicht: die Zeile vorn wird\ndurchgestrichen, und der Person wird gesagt, es habe ein Problem gegeben. Was ihr\nniemand sagt, ist, dass das Problem eine verschlossene Tür zwölf Meter weiter\nwar.",[10,61,62],{},"Die Unschärfe ist Absicht, und sie ist richtig so. Dein Registrierungsformular\nsteht offen im Internet. Eine Meldung, die deine Tabellen benennt, würde jedem\ndeine Datenbank beschreiben, der bereit ist, eine E-Mail-Adresse einzutippen.",[10,64,65,66,69,70,75],{},"Lautet die Antwort stattdessen ",[21,67,68],{},"email rate limit exceeded",", liegt es nicht an\ndeiner Datenbank: Supabase hat sich geweigert, die Bestätigungsmail zu\nverschicken, und\n",[71,72,74],"a",{"href":73},"\u002Fblog\u002Fsupabase-email-rate-limit-exceeded","dieser Fehler hat eine eigene Seite",".",[77,78],"diagram",{"alt":79,"caption":80,"src":81},"Links ein Buch mit Zeilen, dessen neueste Zeile durchgestrichen ist, daneben ein Pfeil nach rechts zu einer Figur, deren Weg in ein zweites Buch von einem orangen Riegel versperrt wird. Ein kleines eigenes Feld daneben zeigt drei Zeilen Aufgeschriebenes, davon eine hervorgehoben.","Die Zeile in auth.users wird geschrieben und wieder herausgenommen, sodass von dem Fehlschlag nichts übrig bleibt außer einer Zeile in einem Log, das die Antwort nie erwähnt.","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fthe-rollback-1600x660.png",[36,83,85],{"id":84},"wo-steht-der-echte-fehler","Wo steht der echte Fehler?",[10,87,88],{},"In den Logs deines Projekts, in zwei Schritten, und Supabase gibt in der eigenen\nFehlerhilfe die Reihenfolge vor.",[10,90,91],{},"Reproduzier ihn einmal, bevor du suchst, damit du eine Uhrzeit zum Abgleichen\nhast. Versuch eine Registrierung in deiner Live-App, lass sie scheitern und merk\ndir den Zeitpunkt.",[10,93,94],{},"Dann im Supabase-Dashboard:",[96,97,98,110],"ol",{},[99,100,101,102,105,106,109],"li",{},"Öffne ",[31,103,104],{},"Logs"," und lies die ",[31,107,108],{},"Auth","-Logs. Such den Eintrag zu dieser Uhrzeit.\nEr trägt den Fehler, den Auth selbst aufgeschrieben hat, und der ist genauer\nals der Satz, den deine App bekommen hat.",[99,111,112,113,115,116,119],{},"Zeigt dieser Eintrag auf die Datenbank, geh zurück zu ",[31,114,104],{}," und öffne die\n",[31,117,118],{},"Postgres","-Logs. Die Zeile zum selben Zeitpunkt ist dein echter Fehler,\ngeschrieben im gewöhnlichen Vokabular von Postgres: eine Spalte, eine\nRelation, ein Typ, eine Berechtigung.",[10,121,122,123,125,126,128,129,131],{},"Supabase nennt in der Fehlerhilfe zu dieser Meldung drei Ursachen. Du hast einen\nTrigger oder eine Trigger-Funktion auf der Tabelle ",[21,124,48],{},", die einen Fehler\nhat. Du hast auf ",[21,127,48],{}," ein Constraint gelegt, das nicht erfüllt wird. Oder\ndu benutzt Prisma, und es hat die Berechtigungen auf ",[21,130,48],{}," kaputt gemacht.\nAus derselben Notiz stammt auch der zweistufige Weg durch die Logs oben.",[10,133,134,135,137],{},"Bei einer App aus Lovable, Bolt, Replit oder v0 deckt die erste Ursache die\nmeisten Fälle ab, denn eine neue Registrierung in eine ",[21,136,52],{},"-Tabelle zu\nkopieren ist das Muster, zu dem jeder Builder greift, und ein Trigger ist, wie es\ngemacht wird.",[36,139,141],{"id":140},"ursache-1-der-trigger-erreicht-deine-tabelle-nicht","Ursache 1: Der Trigger erreicht deine Tabelle nicht",[10,143,144,145,148],{},"Die Datenbankrolle, die deinen Trigger ausführt, darf nicht aus dem\n",[21,146,147],{},"auth","-Schema heraus, und dein Trigger schreibt genau dorthin.",[10,150,151,152,155,156,158],{},"Supabase erklärt das auf dem eigenen Diskussionsboard, und die Formulierung lohnt\nsich genau. Die Datenbankrolle, die die Authentifizierung verwaltet,\n",[21,153,154],{},"supabase_auth_admin",", hat nur die Berechtigungen, die sie für ihre eigenen\nAufgaben braucht, und wenn ein von ",[21,157,154],{}," ausgeführter Trigger mit\netwas außerhalb des auth-Schemas umgeht, gibt das einen Berechtigungsfehler.",[10,160,161],{},"Das ist der Ausweis des Angestellten. Er öffnet das vordere Büro, weil dort seine\nArbeit liegt. Das zweite Buch liegt in einem Raum, für den der Ausweis nie\nausgestellt wurde, und eine verschlossene Tür sagt nichts darüber, warum sie\nverschlossen ist.",[10,163,164],{},"Im Postgres-Log kommt das als Berechtigungsfehler an, der die Tabelle nennt, in\ndie dein Trigger schreiben wollte.",[36,166,168],{"id":167},"die-lösung-und-was-du-damit-abgibst","Die Lösung, und was du damit abgibst",[10,170,171,174],{},[21,172,173],{},"security definer"," an der Funktion, die sie mit den Rechten dessen laufen lässt,\nder sie angelegt hat, statt mit denen dessen, der sie aufruft.",[10,176,177,178,181],{},"Supabase sagt es in einem Satz: eine security definer Funktion behält die Rechte\ndes Datenbankbenutzers, der sie angelegt hat, und solange das die Rolle\n",[21,179,180],{},"postgres"," ist, sollten deine Auth-Trigger mit Tabellen außerhalb umgehen können.\nDer Angestellte trägt nicht mehr den eigenen Ausweis, sondern den des Chefs.",[10,183,184,185,188,189,192,193,195],{},"Das ist eine echte Übertragung von Befugnissen, also lohnt es sich zu wissen, was\ndu da hingeschrieben hast, bevor du es einsetzt. Jede Anweisung in dieser\nFunktion läuft jetzt als Eigentümer. Supabase setzt im eigenen Beispiel den\nsearch_path auf leer, mit ",[21,186,187],{},"security definer set search_path = ''",", und deshalb\nnennt das Insert dort ",[21,190,191],{},"public.profiles"," vollständig statt nur ",[21,194,52],{},". Mit\nleerem search_path löst ein nackter Tabellenname überhaupt nichts mehr auf. Einer\nFunktion mit den Rechten des Eigentümers kann dann niemand still ihr Ziel gegen\neine andere Tabelle tauschen, je nachdem, was der search_path des Aufrufers\ngerade sagt.",[77,197],{"alt":198,"caption":199,"src":200},"Derselbe Weg zweimal gezeichnet. Oben wird eine Figur mit einem kleinen Ausweis von einer verriegelten Tür vor einem Buchfeld aufgehalten. Unten trägt dieselbe Figur einen größeren Ausweis, die Tür steht offen, und der Weg führt weiter in das Feld hinein.","Welchen Ausweis die Funktion trägt, ist der ganze Unterschied. security definer ist die untere Spur, und das ist der Ausweis des Eigentümers.","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Ftwo-passes-1600x620.png",[10,202,203,204,206],{},"Was das nicht erlaubt, ist, beim nächsten abgelehnten Zugriff wieder nach\n",[21,205,173],{}," zu greifen. Lass die Funktion eine Sache tun und zurückkehren,\nso wie Supabase es vormacht.",[36,208,210],{"id":209},"ursache-2-eine-regel-auf-der-tabelle-in-die-du-schreibst","Ursache 2: Eine Regel auf der Tabelle, in die du schreibst",[10,212,213,214,216],{},"Row Level Security auf deiner ",[21,215,52],{},"-Tabelle kann das Insert ablehnen, und\ndie Registrierung scheitert dann auf genau dieselbe Weise.",[10,218,219],{},"Supabase sagt dir in der Anleitung zu diesem Muster, dass du Row Level Security\nfür diese Tabelle anschalten sollst, und diese Anweisung ist richtig. Für deinen\nTrigger heißt das, dass das Insert erlaubt sein muss, entweder durch eine Policy,\ndie es abdeckt, oder durch eine Funktion, die als jemand läuft, für den die\nPolicies nicht gelten.",[10,221,222,223,225],{},"Hier hört das auf, ein Bug zu sein, und wird eine Entscheidung, die jemand um elf\nUhr abends trifft. Niemand kann sich registrieren, der Fehler sagt nichts, und im\nDashboard gibt es einen Schalter mit einer klar formulierten Beschriftung, der\nden Fehler verschwinden lässt: Row Level Security auf ",[21,224,52],{}," ausschalten. Der\nnächste Versuch klappt. Was ebenfalls passiert, ist, dass eine Tabelle mit deinen\nNutzerinnen und Nutzern, mit allem, was du neben ihren Namen darin hältst, jedem\nantwortet, der danach fragt.",[10,227,228,229,232,233,236],{},"Dieser Teil ist von außen sichtbar, und deshalb können wir ihn zählen. Unser\nScanner liest Live-Apps so, wie es ein Fremder täte. Hinter 8.435 der Apps, die\ner benotet hat, haben wir ein Supabase-Projekt gefunden. Bei 3.680 davon hat die\nFrage \"kann jemand ohne Konto diese Tabelle lesen\" überhaupt eine brauchbare\nAntwort bekommen, und ",[31,230,231],{},"2.096 haben mit Ja geantwortet",". Bei ",[31,234,235],{},"394"," von ihnen\nwar die offene Tabelle benannt wie eine Tabelle voller Menschen.",[10,238,239,240,75],{},"Ein Teil davon ist Absicht, denn eine veröffentlichte Speisekarte und eine Seite\nmit Anzeigen liegen in Tabellen, die ein Fremder lesen soll, und unser Scanner\nkann die nicht von einer Kundentabelle unterscheiden, die jemand geöffnet hat, um\neinen Fehler loszuwerden. Er berichtet, was geantwortet hat. Wenn du lieber deine\neigene Antwort siehst, als darüber nachzudenken: unser kostenloser Scan liest\ndeine Live-App und sagt dir, welche Tabellen geantwortet haben. Das dauert etwa\n20 Sekunden und braucht kein Konto:\n",[71,241,243],{"href":242},"\u002Fsecurity-scanner","App scannen",[10,245,246,247,251,252,256],{},"Die Policy, die ein Trigger braucht, ist um einiges enger als die Regeln\nabzuschalten.\n",[71,248,250],{"href":249},"\u002Fblog\u002Fenable-rls-on-every-supabase-table","Row Level Security für jede Tabelle anschalten","\nzeigt, wie man eine schreibt, und\n",[71,253,255],{"href":254},"\u002Fblog\u002Fnew-row-violates-row-level-security-policy","\"new row violates row-level security policy\"","\nist die Meldung, die du bekommst, wenn eine Policy ein Insert ablehnt, das du mit\neigenen Augen siehst.",[36,258,260],{"id":259},"die-anderen-ursachen-und-wie-jede-im-log-aussieht","Die anderen Ursachen, und wie jede im Log aussieht",[10,262,263],{},"Vier weitere, und die Zeile im Log unterscheidet sie in wenigen Worten.",[10,265,266,269,270,272],{},[31,267,268],{},"Eine Tabelle, die es nicht gibt."," Supabase deckt das mit ab: eine\nTrigger-Funktion, die auf eine Tabelle zeigt, die nicht existiert oder gelöscht\nwurde. Eine ",[21,271,52],{},"-Tabelle, die gelöscht und unter anderem Namen neu gebaut\nwurde, reißt jede Registrierung mit, und das Log nennt die fehlende Relation.",[10,274,275,280,281,75],{},[31,276,277,278,75],{},"Ein Constraint auf ",[21,279,48],{}," Ein Check oder ein Fremdschlüssel auf dieser\nTabelle, den die neue Zeile nicht erfüllt. Das lohnt sich auch dann zu suchen,\nwenn du sicher bist, keinen Trigger angelegt zu haben, denn ein Fremdschlüssel\nzwischen deiner eigenen Tabelle und dem Auth-Nutzer ist der häufigste Weg, auf\ndem diese Ursache ankommt. Mit seiner Standardeinstellung lehnt derselbe\nFremdschlüssel später auch das Löschen dieser Person ab, und\n",[71,282,284],{"href":283},"\u002Fblog\u002Fdatabase-error-deleting-user","diese Meldung hat einen eigenen Beitrag",[10,286,287,290,291,294,295,298,299,301,302,305,306,309],{},[31,288,289],{},"Ein Wert mit dem falschen Typ."," Dieser taucht wortwörtlich auf. Ein Trigger,\nder Registrierungsfelder aus ",[21,292,293],{},"raw_user_meta_data"," kopiert, liest sie mit ",[21,296,297],{},"->>",",\nund ",[21,300,297],{}," gibt Text zurück, wie der Wert beim Hineingehen auch ausgesehen haben\nmag. Diesen Text in eine ",[21,303,304],{},"date","-Spalte zu schreiben ergab in einem berichteten\nFall ",[21,307,308],{},"column \"birth_date\" is of type date but expression is of type text",". Die\nReparatur ist ein Cast, mit der Extraktion zuerst in Klammern:",[14,311,314],{"className":312,"code":313,"language":19},[17],"(new.raw_user_meta_data->>'birthDate')::date,\n(new.raw_user_meta_data->>'height')::integer,\n",[21,315,313],{"__ignoreMap":23},[10,317,318,321,322,325],{},[31,319,320],{},"Von Hand eingefügte Zeilen."," Supabase deckt auch Konten ab, die direkt per SQL\nstatt über die Auth-API angelegt wurden und bei denen Pflichtspalten im\nauth-Schema als NULL stehen bleiben statt als leere Zeichenketten. Hat jemand\nNutzer mit einem ",[21,323,324],{},"insert"," eingespielt, ist das eine andere Reparatur als alle\noben.",[10,327,328,329,332,333,75],{},"Eine weitere Zeile, die dir dort begegnen kann:\n",[21,330,331],{},"duplicate key value violates unique constraint",". Sie heißt, dass die Zeile, die\ndein Trigger schreibt, schon da war, etwa weil deine App dasselbe Profil nach der\nRegistrierung noch einmal einfügt, und\n",[71,334,336],{"href":335},"\u002Fblog\u002Fduplicate-key-value-violates-unique-constraint","dieser Fehler hat einen eigenen Beitrag",[10,338,339,340,343,344,75],{},"Und noch eine: ",[21,341,342],{},"null value in column … violates not-null constraint",". Dein Trigger\nhat einen leeren Wert in eine Spalte geschrieben, die einen verlangt, meist ein\nRegistrierungsfeld, das das Formular nie geschickt hat, und\n",[71,345,347],{"href":346},"\u002Fblog\u002Fnull-value-violates-not-null-constraint","auch sie hat einen eigenen Beitrag",[10,349,350,351,354,355,358,359,362,363,75],{},"Die letzte, die dir begegnen kann, ist\n",[21,352,353],{},"insert or update on table \"profiles\" violates foreign key constraint",". Meist\nheißt sie, dass der Trigger mit ",[21,356,357],{},"before insert"," angelegt wurde, sodass die Person,\nfür die er ein Profil schreibt, noch nicht gespeichert ist. Das Muster von\nSupabase weiter unten nutzt ",[21,360,361],{},"after insert",", und\n",[71,364,284],{"href":365},"\u002Fblog\u002Fviolates-foreign-key-constraint",[36,367,369],{"id":368},"die-funktionierende-fassung-vollständig","Die funktionierende Fassung, vollständig",[10,371,372],{},"Fang bei dem Muster an, das Supabase veröffentlicht, und nicht bei einem\nSuchergebnis, denn vier Dinge darin tragen die Last, und eine Paraphrase lässt\nmeistens eines davon weg.",[14,374,377],{"className":375,"code":376,"language":19},[17],"create function public.handle_new_user()\nreturns trigger\nlanguage plpgsql\nsecurity definer set search_path = ''\nas $$\nbegin\n  insert into public.profiles (id, first_name, last_name)\n  values (new.id, new.raw_user_meta_data ->> 'first_name', new.raw_user_meta_data ->> 'last_name');\n  return new;\nend;\n$$;\n\ncreate trigger on_auth_user_created\n  after insert on auth.users\n  for each row execute procedure public.handle_new_user();\n",[21,378,376],{"__ignoreMap":23},[10,380,381,382,384,385,388,389,391,392,395,396,398],{},"Die vier sind ",[21,383,173],{},", der leere ",[21,386,387],{},"search_path",", das vollständig\ngeschriebene ",[21,390,191],{}," und das ",[21,393,394],{},"return new",", mit dem die Registrierung\nweiterläuft. Deine eigenen Spaltennamen kommen in das Insert, und jede Spalte,\ndie du dort nennst, muss existieren und muss annehmen, was ",[21,397,297],{}," liefert.",[10,400,401],{},"Supabase stellt der Anleitung den Satz voran, den man wiederholen sollte: wenn\nder Trigger fehlschlägt, kann er Registrierungen blockieren, also teste deinen\nCode gründlich. Leg nach jeder Änderung daran ein echtes Konto in deiner Live-App\nan.",[36,403,405],{"id":404},"wie-deine-registrierung-nach-einer-änderung-in-betrieb-bleibt","Wie deine Registrierung nach einer Änderung in Betrieb bleibt",[10,407,408,411],{},[31,409,410],{},"Eine Registrierung ist der Teil deiner App, den du an dem Tag nicht mehr\ntestest, an dem er läuft."," Du hast dich einmal registriert, du hast ein Konto,\nund danach meldest du dich an. Der nächste Prompt, der deine Tabellen anfasst,\nkann die Registrierung für alle anderen kaputt machen, während deine eigene\nSitzung sich völlig normal weiter verhält.",[10,413,414],{},[31,415,416,420],{},[71,417,419],{"href":418},"\u002Fwebsite-monitoring","Reeve Monitor"," schaut für dich nach:",[422,423,424,427,430,433],"ul",{},[99,425,426],{},"alle neun Checks jede Stunde, für bis zu drei Apps",[99,428,429],{},"eine E-Mail an dem Tag, an dem ein erneuter Scan deine App schlechter benotet als der vorige",[99,431,432],{},"ob die App erreichbar ist, jede Minute",[99,434,435],{},"ein monatlicher Bericht darüber, was gesehen wurde",[10,437,438],{},[31,439,440,441,445],{},"Eine Regel, die zum Loswerden eines Fehlers abgeschaltet wurde, lässt eine\nTabelle voller Menschen lesbar zurück. ",[71,442,444],{"href":443},"\u002Fsupabase-backups","Reeve Care"," hält eine\nKopie deiner Supabase-Datenbank dort, wo keine Änderung an deinen Regeln sie\nerreicht.",[422,447,448,451,454,457,460],{},[99,449,450],{},"eine verschlüsselte Kopie jeden Tag, außerhalb deines Supabase-Kontos aufbewahrt",[99,452,453],{},"jede Kopie wird geprüft, bevor sie zählt, durch Zählen der Zeilen in jeder Tabelle",[99,455,456],{},"eine Wiederherstellung per Klick, die sichert, was jetzt da ist, bevor sie es ersetzt",[99,458,459],{},"deine hochgeladenen Dateien ebenfalls, sobald du eine Storage-Zugangsberechtigung verbindest",[99,461,462],{},"alles, was Monitor tut",[36,464,466],{"id":465},"was-heute-zu-tun-ist","Was heute zu tun ist",[468,469,470],"key-takeaways",{},[422,471,472,475,478,489,492],{},[99,473,474],{},"Reproduzier eine fehlgeschlagene Registrierung und merk dir die Uhrzeit, bevor du irgendetwas änderst.",[99,476,477],{},"Lies den Auth-Log-Eintrag zu diesem Zeitpunkt, und danach die Postgres-Log-Zeile zur selben Zeit, falls der Auth-Eintrag auf die Datenbank zeigt. Diese Zeile nennt die Spalte, die Relation oder die Berechtigung, an der es gescheitert ist.",[99,479,480,481,483,484,486,487,75],{},"Prüf, ob deine Trigger-Funktion ",[21,482,173],{}," trägt und ihr Ziel vollständig nennt, als ",[21,485,191],{}," statt als ",[21,488,52],{},[99,490,491],{},"Lehnt eine Policy auf dieser Tabelle das Insert ab, schreib eine Policy dafür. Row Level Security abzuschalten löst den Fehler und lässt diese Tabelle für jeden lesbar, der danach fragt.",[99,493,494],{},"Leg nach jeder Änderung an einem Registrierungs-Trigger ein echtes Konto in deiner Live-App an. Deine eigene Sitzung verbirgt eine kaputte Registrierung vollständig vor dir.",[10,496,497,498,502,503,507],{},"Fang bei der Tabelle an, in die dein Trigger schreibt, und lies dann die Policies\nauf jeder Tabelle, die du in derselben Woche angefasst hast. Die\n",[71,499,501],{"href":500},"\u002Fchecklist","10-Minuten-Sicherheits-Checkliste"," deckt ab, was in einer frisch\ngestarteten App sonst noch offen bleibt, und der\n",[71,504,506],{"href":505},"\u002Fis-your-supabase-app-safe","Supabase-Sicherheitsguide"," geht den Rest davon\ndurch, was ein Fremder erreichen kann.",{"title":23,"searchDepth":509,"depth":509,"links":510},3,[511,513,514,515,516,517,518,519,520],{"id":38,"depth":512,"text":39},2,{"id":84,"depth":512,"text":85},{"id":140,"depth":512,"text":141},{"id":167,"depth":512,"text":168},{"id":209,"depth":512,"text":210},{"id":259,"depth":512,"text":260},{"id":368,"depth":512,"text":369},{"id":404,"depth":512,"text":405},{"id":465,"depth":512,"text":466},"Sicherheitsgrundlagen","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcover-1200x630.png","Ein Eingangsbuch an einem Tresen, dessen neueste Zeile schon durchgestrichen ist, und dahinter ein zweites Buch in einem Raum mit verriegelter Tür.","\"Database error saving new user\" heißt: etwas an deiner Supabase-Registrierung ist fehlgeschlagen. Der echte Fehler steht in deinen Logs.",false,"md",[528,531,534,537,540],{"q":529,"a":530},"Was bedeutet \"Database error saving new user\"?","Es bedeutet, dass Supabase die neue Person in die eigene Tabelle auth.users geschrieben hat, dass etwas an diesem Schreibvorgang fehlgeschlagen ist und die Datenbank daraufhin den ganzen Vorgang samt der neuen Zeile zurückgenommen hat. Es wurde also kein Konto angelegt, und es liegt nichts Halbfertiges herum. Die Meldung nennt absichtlich keine Tabelle und keinen Grund, denn dein Registrierungsformular steht offen im Internet, und ein genauer Fehler würde jedem, der eine E-Mail-Adresse einträgt, deine Datenbank beschreiben.",{"q":532,"a":533},"Wo finde ich den echten Fehler?","In den Logs deines Projekts, und Supabase gibt in der eigenen Fehlerhilfe die Reihenfolge vor. Versuch eine Registrierung, lass sie scheitern und merk dir die Uhrzeit. Öffne Logs und lies den Auth-Eintrag zu diesem Zeitpunkt, der trägt das, was Auth selbst aufgeschrieben hat. Zeigt dieser Eintrag auf die Datenbank, öffne die Postgres-Logs zur selben Zeit: diese Zeile nennt die Spalte, die Relation oder die Berechtigung, an der es wirklich gescheitert ist.",{"q":535,"a":536},"Bricht Row Level Security auf meiner profiles-Tabelle die Registrierung?","Das kann sein. Schreibt dein Trigger in eine Tabelle mit Row Level Security und erlaubt keine Policy dieses Insert, wird es abgelehnt, und die Registrierung scheitert mit derselben nichtssagenden Meldung. Die Lösung ist eine Policy dafür oder eine Funktion, die mit Rechten läuft, für die die Policies nicht gelten. Die Regeln auf dieser Tabelle abzuschalten lässt den Fehler ebenfalls verschwinden, und danach ist eine Tabelle mit deinen Nutzerinnen und Nutzern für jeden lesbar, der danach fragt.",{"q":538,"a":539},"Was ist security definer, und ist das sicher?","Damit läuft die Funktion mit den Rechten dessen, der sie angelegt hat, statt mit denen dessen, der sie aufruft. Genau das lässt einen Trigger, den die Auth-Rolle ausführt, in eine Tabelle von dir schreiben. Es ist das Muster, das Supabase veröffentlicht, und es ist eine echte Übertragung von Befugnissen, deshalb sollte die Funktion genau eine enge Sache tun. Supabase setzt im eigenen Beispiel außerdem den search_path auf leer, und deshalb nennt das Insert dort public.profiles vollständig und nicht nur profiles.",{"q":541,"a":542},"Ich habe nie einen Trigger angelegt. Was kann es sonst sein?","Drei andere Dinge. Ein Constraint oder ein Fremdschlüssel auf auth.users, den die neue Zeile nicht erfüllt. Eine Trigger-Funktion, die auf eine Tabelle zeigt, die umbenannt oder gelöscht wurde. Und Supabase nennt Prisma ausdrücklich, weil es die Berechtigungen auf auth.users kaputt machen kann. Welches davon es ist, sagt dir die Zeile im Postgres-Log.","\u002Fblog\u002Fdatabase-error-saving-new-user\u002Fcard-800x500.png",[545,546,547,548,549,550,551],"database error saving new user","supabase database error saving new user","supabase registrierung fehler","auth.users trigger fehler","handle_new_user funktioniert nicht","supabase security definer trigger","supabase anmeldung 500 fehler",{},true,"\"Database error saving new user\" in Supabase","\u002Fblog\u002Fdatabase-error-saving-new-user","2026-10-14",{"title":5,"description":524},"blog\u002Fdatabase-error-saving-new-user",[560,561,562],"\"Database error saving new user\" heißt, dass Supabase die Registrierung angenommen hat, etwas daran fehlgeschlagen ist und das Ganze wieder zurückgenommen wurde. Es wurde kein Konto angelegt.","Die Meldung ist absichtlich nichtssagend, und die echte steht längst irgendwo. Supabase schickt dich in der eigenen Fehlerhilfe erst in die Auth-Logs und dann in die Postgres-Logs für die Zeile darunter.","Fast immer ist es ein Trigger auf auth.users, der die Tabelle nicht erreicht, in die er schreibt. Die Lösung ist eine security definer Funktion, und worauf es ankommt, ist, wie viel diese Funktion darf.","Bp8zTJ4UM5pCltKS3lVzi89YMmVI3d2lMq5i7xcJl0o",[565,571,577,582,587,593,599,605,611,617,623,629,635,641,647,653,659,664,670,676,682,687,693,699,705,711,717,718,724,730,736,742,748,754,760,766,772,778,784,790,796,802,808,814,820,826,831,837,843,849,855,861,867,873,879,885,891,897,903,909,915,921,926,932,938,944,950,956,962,968,974,980,986,992,998,1004,1009,1015,1021,1027,1033,1039,1045,1051,1056,1062,1068,1074,1079,1085],{"path":566,"title":567,"description":568,"published":569,"category":521,"image":570,"draft":525},"\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":572,"title":573,"description":574,"published":575,"category":521,"image":576,"draft":525},"\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":365,"title":578,"description":579,"published":580,"category":521,"image":581,"draft":525},"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":346,"title":583,"description":584,"published":585,"category":521,"image":586,"draft":525},"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":588,"title":589,"description":590,"published":591,"category":521,"image":592,"draft":525},"\u002Fblog\u002Fauth-session-missing","Supabase \"Auth session missing!\": wo die Sitzung geblieben ist","\"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.","2026-11-05","\u002Fblog\u002Fauth-session-missing\u002Fcard-800x500.png",{"path":594,"title":595,"description":596,"published":597,"category":521,"image":598,"draft":525},"\u002Fblog\u002Finvalid-claim-missing-sub-claim","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":600,"title":601,"description":602,"published":603,"category":521,"image":604,"draft":525},"\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":606,"title":607,"description":608,"published":609,"category":521,"image":610,"draft":525},"\u002Fblog\u002Fsupabase-auth-redirects-to-localhost","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":612,"title":613,"description":614,"published":615,"category":521,"image":616,"draft":525},"\u002Fblog\u002Femail-link-is-invalid-or-has-expired","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":618,"title":619,"description":620,"published":621,"category":521,"image":622,"draft":525},"\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":283,"title":624,"description":625,"published":626,"category":627,"image":628,"draft":525},"\"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":630,"title":631,"description":632,"published":633,"category":521,"image":634,"draft":525},"\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":636,"title":637,"description":638,"published":639,"category":521,"image":640,"draft":525},"\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":642,"title":643,"description":644,"published":645,"category":521,"image":646,"draft":525},"\u002Fblog\u002Fedge-function-returned-a-non-2xx-status-code","\"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":648,"title":649,"description":650,"published":651,"category":521,"image":652,"draft":525},"\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":654,"title":655,"description":656,"published":657,"category":521,"image":658,"draft":525},"\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":335,"title":660,"description":661,"published":662,"category":521,"image":663,"draft":525},"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":665,"title":666,"description":667,"published":668,"category":521,"image":669,"draft":525},"\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":671,"title":672,"description":673,"published":674,"category":521,"image":675,"draft":525},"\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":677,"title":678,"description":679,"published":680,"category":521,"image":681,"draft":525},"\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":73,"title":683,"description":684,"published":685,"category":521,"image":686,"draft":525},"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":688,"title":689,"description":690,"published":691,"category":521,"image":692,"draft":525},"\u002Fblog\u002Fsupabase-users-logged-out","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":694,"title":695,"description":696,"published":697,"category":521,"image":698,"draft":525},"\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":700,"title":701,"description":702,"published":703,"category":521,"image":704,"draft":525},"\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":706,"title":707,"description":708,"published":709,"category":521,"image":710,"draft":525},"\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":712,"title":713,"description":714,"published":715,"category":521,"image":716,"draft":525},"\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":555,"title":5,"description":524,"published":556,"category":521,"image":543,"draft":525},{"path":719,"title":720,"description":721,"published":722,"category":521,"image":723,"draft":525},"\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":725,"title":726,"description":727,"published":728,"category":521,"image":729,"draft":525},"\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":731,"title":732,"description":733,"published":734,"category":521,"image":735,"draft":525},"\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":737,"title":738,"description":739,"published":740,"category":521,"image":741,"draft":525},"\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":743,"title":744,"description":745,"published":746,"category":521,"image":747,"draft":525},"\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":749,"title":750,"description":751,"published":752,"category":521,"image":753,"draft":525},"\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":755,"title":756,"description":757,"published":758,"category":521,"image":759,"draft":525},"\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":761,"title":762,"description":763,"published":764,"category":521,"image":765,"draft":525},"\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":767,"title":768,"description":769,"published":770,"category":521,"image":771,"draft":525},"\u002Fblog\u002Fmove-a-secret-to-an-edge-function","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":773,"title":774,"description":775,"published":776,"category":521,"image":777,"draft":525},"\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":779,"title":780,"description":781,"published":782,"category":521,"image":783,"draft":525},"\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":785,"title":786,"description":787,"published":788,"category":521,"image":789,"draft":525},"\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":791,"title":792,"description":793,"published":794,"category":521,"image":795,"draft":525},"\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":797,"title":798,"description":799,"published":800,"category":521,"image":801,"draft":525},"\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":803,"title":804,"description":805,"published":806,"category":521,"image":807,"draft":525},"\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":809,"title":810,"description":811,"published":812,"category":627,"image":813,"draft":525},"\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":815,"title":816,"description":817,"published":818,"category":627,"image":819,"draft":525},"\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":821,"title":822,"description":823,"published":824,"category":627,"image":825,"draft":525},"\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":827,"title":828,"description":829,"published":824,"category":521,"image":830,"draft":525},"\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":832,"title":833,"description":834,"published":835,"category":521,"image":836,"draft":525},"\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":838,"title":839,"description":840,"published":841,"category":521,"image":842,"draft":525},"\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":844,"title":845,"description":846,"published":847,"category":627,"image":848,"draft":525},"\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":850,"title":851,"description":852,"published":853,"category":521,"image":854,"draft":525},"\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":856,"title":857,"description":858,"published":859,"category":521,"image":860,"draft":525},"\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":862,"title":863,"description":864,"published":865,"category":521,"image":866,"draft":525},"\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":868,"title":869,"description":870,"published":871,"category":521,"image":872,"draft":525},"\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":874,"title":875,"description":876,"published":877,"category":521,"image":878,"draft":525},"\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":880,"title":881,"description":882,"published":883,"category":521,"image":884,"draft":525},"\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":886,"title":887,"description":888,"published":889,"category":521,"image":890,"draft":525},"\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":892,"title":893,"description":894,"published":895,"category":521,"image":896,"draft":525},"\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":898,"title":899,"description":900,"published":901,"category":627,"image":902,"draft":525},"\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":904,"title":905,"description":906,"published":907,"category":627,"image":908,"draft":525},"\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":910,"title":911,"description":912,"published":913,"category":627,"image":914,"draft":525},"\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":916,"title":917,"description":918,"published":919,"category":521,"image":920,"draft":525},"\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":249,"title":922,"description":923,"published":924,"category":521,"image":925,"draft":525},"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":927,"title":928,"description":929,"published":930,"category":521,"image":931,"draft":525},"\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":933,"title":934,"description":935,"published":936,"category":521,"image":937,"draft":525},"\u002Fblog\u002Frotate-supabase-service-role-key","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":939,"title":940,"description":941,"published":942,"category":521,"image":943,"draft":525},"\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":945,"title":946,"description":947,"published":948,"category":521,"image":949,"draft":525},"\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":951,"title":952,"description":953,"published":954,"category":521,"image":955,"draft":525},"\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":957,"title":958,"description":959,"published":960,"category":521,"image":961,"draft":525},"\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":963,"title":964,"description":965,"published":966,"category":521,"image":967,"draft":525},"\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":969,"title":970,"description":971,"published":972,"category":521,"image":973,"draft":525},"\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":975,"title":976,"description":977,"published":978,"category":627,"image":979,"draft":525},"\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":981,"title":982,"description":983,"published":984,"category":521,"image":985,"draft":525},"\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":987,"title":988,"description":989,"published":990,"category":627,"image":991,"draft":525},"\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":993,"title":994,"description":995,"published":996,"category":521,"image":997,"draft":525},"\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":999,"title":1000,"description":1001,"published":1002,"category":521,"image":1003,"draft":525},"\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":254,"title":1005,"description":1006,"published":1007,"category":521,"image":1008,"draft":525},"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":1010,"title":1011,"description":1012,"published":1013,"category":521,"image":1014,"draft":525},"\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":1016,"title":1017,"description":1018,"published":1019,"category":627,"image":1020,"draft":525},"\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":1022,"title":1023,"description":1024,"published":1025,"category":627,"image":1026,"draft":525},"\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":1028,"title":1029,"description":1030,"published":1031,"category":521,"image":1032,"draft":525},"\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":1034,"title":1035,"description":1036,"published":1037,"category":521,"image":1038,"draft":525},"\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":1040,"title":1041,"description":1042,"published":1043,"category":627,"image":1044,"draft":525},"\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":1046,"title":1047,"description":1048,"published":1049,"category":521,"image":1050,"draft":525},"\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":1052,"title":1053,"description":1054,"published":1049,"category":521,"image":1055,"draft":525},"\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":1057,"title":1058,"description":1059,"published":1060,"category":521,"image":1061,"draft":525},"\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":1063,"title":1064,"description":1065,"published":1066,"category":627,"image":1067,"draft":525},"\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":1069,"title":1070,"description":1071,"published":1072,"category":521,"image":1073,"draft":525},"\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":1075,"title":1076,"description":1077,"published":1072,"category":627,"image":1078,"draft":525},"\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":1080,"title":1081,"description":1082,"published":1083,"category":627,"image":1084,"draft":525},"\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":1086,"title":1087,"description":1088,"published":1083,"category":521,"image":1089,"draft":525},"\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",1794213638787]