PostgreSQL-Datenbankzugriff für KI-App-Builder
Richten Sie PostgreSQL-Zugriff für einen KI-App-Builder mit schreibgeschützter Erkundung, eingeschränkten Zugangsdaten, freigegebenen Migrationen und sicherem Pooling ein.

Ein KI-App-Builder kann sich mit einer bestehenden PostgreSQL-Datenbank verbinden, ohne ihr Schema zu besitzen. Dafür muss diese Grenze aber in PostgreSQL wirklich durchgesetzt werden. Ein Prompt wie „Produktion nicht ändern“ ist keine Kontrolle. Eine separate Rolle, Transaktionsvorgaben, ausdrücklich geprüfte Migrationen und Schema-Prüfungen sind Kontrollen.
Das sichere Modell teilt die Datenbankarbeit in drei Bereiche. Die Erkundung liest Metadaten und zulässige Beispieldaten. Die Anwendung liest und schreibt nur die Tabellen und Vorgänge, die sie braucht. Schemaänderungen laufen erst nach menschlicher Freigabe des exakten SQL über eine separate Migrationsidentität. Teams fassen diese Bereiche oft in einer bequemen Eigentümer-Zugangsdaten zusammen und stellen dann fest, dass ein Agent einen plausiblen Spaltennamen als Erlaubnis verstand, eine Live-Tabelle umzubauen. Die Bequemlichkeit hielt einen Nachmittag, die Aufräumarbeit deutlich länger.
Die Erkundung muss konstruktiv schreibgeschützt sein
Eine Erkundungsverbindung braucht genug Zugriff, um das erlaubte Schema zu verstehen, aber nicht genug, um es „verbessern“ zu können. Erstellen Sie eine Anmelderolle, die keine Datenbanken oder Rollen anlegen, keine Row-Level Security umgehen und keine überraschenden Rechte aus einer breiten Gruppe erben kann. PostgreSQL vergibt diese Befugnisse neuen Rollen zunächst nicht, doch ausdrückliche Festlegungen machen die Absicht prüfbar.
CREATE ROLE app_discovery
LOGIN
NOSUPERUSER
NOCREATEDB
NOCREATEROLE
NOINHERIT
NOBYPASSRLS
CONNECTION LIMIT 3
PASSWORD 'replace-through-secret-manager';
ALTER ROLE app_discovery SET default_transaction_read_only = on;
GRANT CONNECT ON DATABASE customer_portal TO app_discovery;
GRANT USAGE ON SCHEMA app TO app_discovery;
GRANT SELECT ON ALL TABLES IN SCHEMA app TO app_discovery;
default_transaction_read_only blockiert gewöhnliche Schreibvorgänge in Sitzungen, die die Vorgabe beibehalten. Es ist ein zusätzlicher Schutz, nicht die einzige Sicherung. Dass INSERT, UPDATE, DELETE, TRUNCATE, CREATE und Eigentümerschaft fehlen, hält die Rolle auch dann begrenzt, wenn ein Client seine Transaktionseinstellung ändert. Geben Sie der Rolle keine Mitgliedschaft in einer Eigentümergruppe der Anwendung und machen Sie sie nicht zum Eigentümer eines Schemas.
Prüfen Sie vorhandene Rechte, bevor sich der Builder verbindet. Die folgende Abfrage liefert pro Tabellenrecht eine Zeile, sodass eine prüfende Person alles außer SELECT erkennen kann:
SELECT table_schema, table_name, privilege_type
FROM information_schema.role_table_grants
WHERE grantee = 'app_discovery'
ORDER BY table_schema, table_name, privilege_type;
Ein gesundes Ergebnis sieht etwa so aus: app | invoices | SELECT. Ein leeres Ergebnis kann bedeuten, dass die Erkundung eine benötigte Tabelle nicht sieht. Eine Zeile mit UPDATE am Ende zeigt, dass die Rolle zu mächtig ist. Prüfen Sie außerdem Schema-Rechte mit has_schema_privilege und Datenbankrechte mit has_database_privilege, denn Tabellenrechte zeigen nicht, ob die Rolle anderswo Objekte anlegen kann.
Nutzen Sie keinen Produktions-Snapshot als Vorwand, Zugangsdaten eines Eigentümers zu teilen. Auch eine Kopie kann Kundendaten enthalten, und ein Agent mit Eigentümerschaft kann sie so weit verändern, dass spätere Vergleiche wertlos werden. Geben Sie der Erkundung in jeder Umgebung eine eigene Identität.
Katalogprüfung muss innerhalb einer Allowlist bleiben
Der Builder sollte nur freigegebene Schemas erkunden und festhalten, was PostgreSQL tatsächlich meldet. information_schema bietet portable Views für Tabellen, Spalten, Constraints und Rechte. pg_catalog liefert PostgreSQL-Details wie Indizes, Typen, generierte Ausdrücke und Row-Level Security. Beide Quellen sind besser als die Erinnerung eines LLM an eine typische Kundentabelle.
Beginnen Sie mit einer Allowlist wie app und reporting. Lehnen Sie pg_catalog, information_schema, temporäre Schemas, Erweiterungs-Schemas und jedes nicht gelistete Mandanten-Schema als Anwendungsziele ab. Die Abfrage sollte auf Datenbank-, Rollen- und SQL-Ebene filtern. Eine Allowlist nur im Prompt kann in einem späteren Chat verschwinden.
SELECT
c.table_schema,
c.table_name,
c.ordinal_position,
c.column_name,
c.data_type,
c.is_nullable,
c.column_default
FROM information_schema.columns AS c
WHERE c.table_schema IN ('app', 'reporting')
ORDER BY c.table_schema, c.table_name, c.ordinal_position;
Speichern Sie das Ergebnis als Schema-Snapshot mit Abrufzeit und Datenbankkennung. Der Snapshot belegt, was der Generator gesehen hat. Er ist keine dauerhafte Wahrheit. PostgreSQL kann sich zwischen Erkundung und Codegenerierung ändern. Vergleichen Sie daher vor dem Deployment einen neuen Fingerprint. Ein brauchbarer Fingerprint kann geordnete Beschreibungen von Tabellen, Spalten, Typen, Nullbarkeit, Vorgaben, Constraints und Indizes hashen. Weicht er ab, stoppen Sie und erkunden Sie erneut, statt zu raten, welche Änderung harmlos ist.
Das Ziehen von Beispielzeilen ist eine eigene Berechtigungsentscheidung. Spaltenmetadaten enthalten selten personenbezogene Daten, Zeilenproben oft schon. Für die Codegenerierung sind null Beispielzeilen vorzuziehen. Wenn Beispiele nötig sind, stellen Sie eine View bereit, die Geheimnisse und direkte Identifikatoren entfernt oder maskiert, und gewähren Sie nur auf diese View SELECT. LIMIT 10 macht eine sensible Abfrage nicht sicher, es verkleinert nur das Leck.
Der Suchpfad verdient dieselbe Behandlung. Setzen Sie ihn auf das freigegebene Schema plus pg_catalog, qualifizieren Sie generierte Tabellennamen und verlassen Sie sich nie auf das Objekt, das PostgreSQL zuerst auflöst. Ein Angreifer oder eine unvorsichtige Migration kann in einem beschreibbaren Schema ein gleichnamiges Objekt anlegen. Qualifizierte Namen wie app.orders beseitigen diese Mehrdeutigkeit.
Die Laufzeitrolle muss zu den tatsächlichen Nutzeraktionen passen
Erkundung und Laufzeit sind unterschiedliche Aufgaben. Die Laufzeitanwendung muss vielleicht eine Bestellung einfügen, einen Entwurf aktualisieren oder eine sorgfältig entworfene Funktion aufrufen. Das rechtfertigt keinen breiten Schreibzugriff auf das erkundete Schema. Erstellen Sie aus Nutzeraktionen eine Berechtigungsmatrix und übersetzen Sie jede Aktion in die kleinste PostgreSQL-Berechtigung.
Ein Rechnungsbetrachter braucht etwa SELECT auf app.invoices und app.invoice_lines, während eine Notizfunktion SELECT und INSERT auf app.invoice_notes braucht. Wahrscheinlich benötigt sie weder DELETE auf Rechnungen noch Zugriff auf Passwort-Reset-Datensätze oder Schemaerstellung. Gewähren Sie die Nutzung einer Sequenz nur, wenn ein Insert diese Sequenz wirklich nutzt. PostgreSQL behandelt Sequenzen als eigenständige Objekte, was Generatoren überrascht, die mit einem Eigentümerkonto testen.
Views und Funktionen können die Oberfläche weiter verkleinern. Eine View kann freigegebene Spalten zeigen und interne Felder ausblenden. Eine SECURITY DEFINER-Funktion kann einen kontrollierten Vorgang ausführen, den normale Rechte nicht ausdrücken. Sie braucht jedoch einen festen search_path, strenge Eingabeprüfungen und einen Eigentümer ohne unnötige Befugnisse. Behandeln Sie eine solche Funktion als privilegierten Code, nicht als Abkürzung um das Berechtigungsmodell herum.
Row-Level Security ergänzt innerhalb einer gemeinsamen Tabelle eine Datengrenze. Sie ersetzt keine Tabellenrechte. PostgreSQL prüft zuerst, ob die Rolle den Vorgang ausführen darf, und wendet dann, wenn aktiviert und zutreffend, Row-Security-Richtlinien an. Testen Sie mit der exakten Laufzeitrolle, denn Tabelleneigentümer und Rollen mit BYPASSRLS können Richtlinien umgehen. Ein Test mit dem Migrations-Eigentümer beweist fast nichts darüber, was Endnutzer sehen können.
Halten Sie Geheimnisse aus Prompts, generiertem Quellcode, Browser-Bundles, Build-Logs und Screenshots heraus. Legen Sie die Laufzeit-Zugangsdaten im Secret Store der Hosting-Umgebung ab und injizieren Sie sie nur in den Serverprozess. Mobil- und Browser-Anwendungen können ein PostgreSQL-Passwort nicht geheim halten und sollten deshalb eine Server-API aufrufen, statt sich direkt zu verbinden. Rotieren Sie Erkundungs-, Laufzeit- und Migrationszugangsdaten unabhängig voneinander. Ein Leck in einem Bereich darf die beiden anderen nicht öffnen.
Migrationsrechte gehören in einen separaten Freigabepfad
Ein App-Builder darf Migrationen vorschlagen, sollte sie aber nicht über seine Erkundungs- oder Laufzeitsitzung ausführen. Geben Sie Migrationsarbeiten eine separate Rolle oder lassen Sie ein etabliertes Deployment-System diese Rolle für einen freigegebenen Job übernehmen. Halten Sie ihre Zugangsdaten in normalen Chat- und Vorschau-Sitzungen unzugänglich.
Die Freigabe muss exaktes SQL, die Identität der Zieldatenbank, den bei der Vorbereitung verwendeten Schema-Fingerprint sowie das erwartete Sperr- oder Rewrite-Verhalten abdecken. Die Freigabe eines Satzes wie „Kundenstatus hinzufügen“ lässt zu viel Spielraum. Die ausführbare Änderung könnte eine nullable Textspalte hinzufügen, eine große Tabelle neu schreiben, ein Enum erfinden oder jede bestehende Zeile aktualisieren. Das sind verschiedene Vorgänge mit unterschiedlichen Fehlermodi.
Ich verwende ein kompaktes Migrationspaket:
- Grund der Änderung und die benötigende Anwendungsversion.
- Exaktes Vorwärts-SQL und, soweit ehrlich möglich, exaktes Umkehr-SQL.
- Objekte, Rechte und Zeilen, die die Befehle beeinflussen können.
- Preflight-Abfragen, erwartete Ergebnisse und einen aktuellen Schema-Fingerprint.
- Lock-Timeout, Statement-Timeout, Backup- oder Snapshot-Referenz und Release-Verantwortliche.
Ein Umkehrskript ist nicht immer ein Rollback. Das Löschen einer neu hinzugefügten Spalte kehrt zwar die Katalogänderung um, zerstört aber auch Daten, die nach dem Release geschrieben wurden. Das transaktionale DDL von PostgreSQL hilft bei vielen Katalogvorgängen, doch eine Transaktion kann weder externe Nebenwirkungen noch Daten zurückholen, die ein späterer Befehl gelöscht hat. Kennzeichnen Sie destruktive Umkehrungen klar, statt DOWN als Zauberwort zu behandeln.
Setzen Sie lock_timeout, damit eine Migration fehlschlägt, statt hinter einer beschäftigten Transaktion zu warten und neue Arbeit zu blockieren. Setzen Sie statement_timeout entsprechend dem geprüften Vorgang. Führen Sie die Preflight-Abfragen im Änderungsfenster erneut aus. Wenn Tabellengröße, kollidierende Objekte, Null-Anzahlen oder Schema-Fingerprint von den freigegebenen Annahmen abweichen, brechen Sie ab. Der Agent sollte einen Abweichungsbericht liefern, keine neue Migration für Produktion improvisieren.
Geben Sie eine Migration niemals automatisch frei, nur weil generierte Tests erfolgreich waren. Tests laufen meist auf einem kleinen, sauberen Schema und übersehen Sperrwarteschlangen, alte Nullwerte, ungewöhnliche Constraints, Erweiterungen und noch laufende Anwendungsversionen. Bei der Freigabe gleicht eine Person die generierte Absicht mit dem Live-System ab.
Connection Pooling verändert die Sicherheitsbetrachtung
Ein Pool nutzt Datenbanksitzungen erneut, daher kann Sitzungszustand länger leben als die Anfrage, die ihn erzeugt hat. Wenn eine Anfrage SET search_path ausführt, eine Rolle wechselt, ein temporäres Objekt anlegt oder ein Timeout deaktiviert, kann der nächste Entleiher das Ergebnis übernehmen. Die Anwendung muss veränderlichen Sitzungszustand vermeiden oder ihn beim Rückgeben der Verbindung zuverlässig zurücksetzen.
Transaction Pooling zieht die Grenze enger. Nach jeder Transaktion kann ein Client eine andere Server-Sitzung erhalten. Das bricht Annahmen über sitzungsbezogene Prepared Statements, temporäre Tabellen, Advisory Locks und Einstellungen auf Sitzungsebene. Builder erzeugen oft Code, der über eine direkte Verbindung funktioniert und hinter einem Pool scheitert, weil sie diesen Unterschied nicht modellieren. Entscheiden Sie sich für Sitzungs- oder Transaktionsmodus und berücksichtigen Sie ihn bei Generierung und Tests.
Planen Sie Verbindungen vor dem Deployment. Starten Sie mit der zulässigen Verbindungszahl der Datenbank, reservieren Sie Kapazität für Administration, Migrationen, Monitoring und andere Dienste und teilen Sie den Rest auf Anwendungsinstanzen auf. Wenn zehn Instanzen jeweils zwanzig Verbindungen öffnen, sieht PostgreSQL zweihundert mögliche Sitzungen, selbst bei ruhigem Verkehr. Ein konservativer kleiner Pool mit Warteschlange ist meist sicherer, als Verbindungen zu vervielfachen, bis die Datenbank sie ablehnt.
Verwenden Sie serverseitige Timeouts als Sicherheitsnetz: statement_timeout begrenzt lange Statements, lock_timeout Wartezeiten auf Sperren und idle_in_transaction_session_timeout entfernt Sitzungen, die eine Transaktion offen halten und nichts tun. Setzen Sie Werte je Rolle, statt darauf zu vertrauen, dass jeder generierte Client daran denkt. Prüfen Sie sie mit SHOW unter der tatsächlichen Rolle und über den tatsächlichen Pool.
Health Checks sollten günstig sein. SELECT 1 bestätigt einen Hin- und Rückweg, aber nicht, dass die Anwendung eine freigegebene Tabelle erreicht oder ihr Suchpfad stimmt. Ein Readiness Check kann mit der Laufzeitrolle eine kleine stabile View abfragen. Halten Sie Migrationen aus dem Anwendungsstart heraus. Gleichzeitig startende Instanzen, die um Schemaänderungen konkurrieren, schaffen genau die Kopplung, die dieses Design vermeiden soll.
Erfundenen Spalten müssen vor der Abfrage scheitern
LLMs erfinden plausible Bezeichner. Wenn ein Prompt den Anzeigenamen eines Kunden erwähnt, greift generierter Code vielleicht auf customers.display_name zu, obwohl die Datenbank given_name und family_name speichert. Die Datenbank weist diese Abfrage zurück, was besser ist als still das falsche Feld zu lesen. Ein Produktionsfehler ist dennoch eine schlechte Strategie zur Schemavalidierung.
Generieren Sie aus dem freigegebenen Katalog-Snapshot ein typisiertes Schema-Artefakt und machen Sie es zur einzigen Quelle für die Abfragekonstruktion. Eine Tabelle oder Spalte, die darin fehlt, muss einen Generierungsfehler verursachen. Lassen Sie das Modell den Fehler nicht durch Hinzufügen einer Migration beheben, außer die Aufgabe wechselt ausdrücklich in den Migrationsbereich. Ein fehlender Bezeichner kann veraltete Erkundung, einen Schreibfehler, die falsche Umgebung oder eine echte Produktanforderung bedeuten. Jede Ursache verlangt eine andere Reaktion.
Statische Prüfungen sollten SQL parsen und jede Relation und Spalte gegen den Snapshot auflösen. Bereiten Sie Statements dann gegen eine wegwerfbare Datenbank oder in einer nicht schreibfähigen Transaktion vor. Der PostgreSQL-Parser erkennt unbekannte Spalten, mehrdeutige Referenzen, Operator-Typfehler und viele falsche Casts, ohne erfolgreiche Geschäftsdaten zu benötigen. Führen Sie Integrationstests mit der Laufzeitrolle aus, damit Rechte und Zeilenrichtlinien mitwirken.
Der Fehlerbericht braucht genug Details für eine menschliche Entscheidung. Geben Sie SQL-Position, nicht aufgelösten Bezeichner, nahe gültige Bezeichner, Snapshot-Fingerprint und Identität der Zieldatenbank an. Vorschläge helfen, automatische unscharfe Ersetzung ist jedoch gefährlich. billing_address_id durch shipping_address_id zu ersetzen, weil die Namen ähnlich aussehen, kann gültiges SQL mit falscher fachlicher Bedeutung erzeugen.
Ordnen Sie bei dynamischen Filtern und Sortierungen öffentliche API-Namen einer geschlossenen Menge qualifizierter SQL-Ausdrücke zu. Fügen Sie niemals einen vom Modell gelieferten Bezeichner in SQL ein, auch nicht über einen Wertparameter. Parameter schützen Werte, keine Tabellen- oder Spaltennamen. Wenn Nutzende ein Sortierfeld wählen dürfen, übersetzen Sie created in einen bekannten Ausdruck wie app.orders.created_at und lehnen jeden unbekannten Token ab.
Schema Drift sollte ein Release stoppen, keine kreative Abstimmung auslösen. Generieren Sie den Snapshot neu, zeigen Sie den Unterschied und wiederholen Sie die Tests. Die Verzögerung wirkt vielleicht pingelig, ist aber günstiger als Code zu deployen, dessen Datenbankverständnis nur in einem Gesprächsprotokoll existiert.
Destruktives SQL braucht eine Sperrrichtlinie und Nachweise
Ein Builder sollte SQL klassifizieren, bevor jemand es ausführen kann. Blockieren Sie DROP, TRUNCATE, breite DELETE- oder UPDATE-Anweisungen ohne geprüfte Bedingung, Eigentümerwechsel, Rechteausweitung, Änderungen an Erweiterungen und Befehle außerhalb freigegebener Schemas. Behandeln Sie ALTER TABLE als freigabepflichtig, nicht automatisch sicher. Ein Spaltentypwechsel oder eine neue Nonnull-Constraint kann Daten scannen oder neu schreiben und folgenschwere Sperren halten.
Reine Textsuche ist schwach, weil SQL Kommentare, zitierte Bezeichner, Funktionen und viele Formen von Nebenwirkungen kennt. Parsen Sie Statements mit einem PostgreSQL-fähigen Parser, prüfen Sie ihre Syntaxbäume und verlassen Sie sich zusätzlich darauf, dass die Datenbankrolle verbotene Aktionen ablehnt. Der Klassifikator verbessert die Prüfung, Berechtigungen erzwingen die Grenze. Keines von beiden sollte die gesamte Last tragen.
Nutzen Sie eine Staging-Datenbank, die aus einem aktuellen, angemessen geschützten Snapshot wiederhergestellt wurde, wenn eine Migration von realen Tabellenformen oder Datenverteilungen abhängt. Wenden Sie dort das exakte Migrationspaket an, erfassen Sie Dauer und Sperrbeobachtungen, führen Sie Anwendungstests mit Laufzeit-Zugangsdaten aus und verwerfen Sie die Umgebung danach. Bearbeiten Sie SQL nicht still zwischen Staging und Produktion. Jede Änderung schafft ein neues Artefakt, das einen neuen Fingerprint und eine neue Freigabe braucht.
Logs sollten einen Vorschlag mit einer Ausführung verbinden, ohne Geheimnisse oder sensible Zeilen zu speichern. Erfassen Sie, wer das unveränderliche Migrationsartefakt freigegeben hat, dessen Digest, Zielidentität, Start- und Endstatus sowie PostgreSQL-Fehlerdetails. Bewahren Sie generierten Diff und Preflight-Ergebnisse auf. Ein Agent-Chat liefert nützlichen Kontext, ist aber kein Audit-Protokoll, weil Nutzende verzweigen, wiederholen und Anweisungen umformulieren können.
Snapshots und Rollback-Kontrollen verkürzen die Wiederherstellungszeit, machen destruktives SQL jedoch nicht akzeptabel. Ein Snapshot kann eine ganze Datenbank auf einen früheren Zeitpunkt zurücksetzen, obwohl eigentlich nur eine gelöschte Spalte benötigt wird. Die Wiederherstellung kann legitime Schreibvorgänge nach dem Snapshot verwerfen. Testen Sie Wiederherstellung separat und dokumentieren Sie, wer sie auslösen darf.
Wenn ich Koder.ai für eine App nutze, die eine etablierte Datenbank berührt, bleibe ich im Planungsmodus, bis ich den exportierten Quellcode und die vorgeschlagene Datenbankgrenze geprüft habe. Snapshots und Rollback sind Wiederherstellungskontrollen, keine Erlaubnis, diese Prüfung zu überspringen. Das gilt für jeden Builder: Produktkomfort muss hinter der Durchsetzung durch die Datenbank stehen.
Schemaänderungen müssen gemischte Anwendungsversionen vertragen
Eine Migration ist nur sicher, wenn alte und neue Anwendung während des Release-Fensters laufen können. Produktion wechselt selten in einem einzigen Moment von einer Version zur nächsten. Anfragen können alte Instanzen erreichen, während neue starten, Warteschlangenjobs können ältere Nutzdaten tragen, und ein Rollback kann den Code von gestern gegen das Schema von heute setzen. Ein App-Builder, der nur finalen Code gegen finales Schema validiert, übersieht diese Überlappung.
Bevorzugen Sie zuerst additive Änderungen. Fügen Sie eine nullable Spalte, eine neue Tabelle oder einen Index hinzu, ohne den alten Pfad zu entfernen. Deployen Sie Code, der beide Darstellungen lesen kann und, wo passend, die neue schreibt. Füllen Sie bestehende Zeilen mit einem separat geprüften Job nach, beobachten Sie Fehler und Rückstand und machen Sie das neue Feld anschließend maßgeblich. Entfernen Sie alte Spalte oder Constraint erst in einem späteren Release, wenn belegt ist, dass kein laufender Code sie nutzt.
Diese Reihenfolge dauert länger als ein generiertes ALTER TABLE-Statement, grenzt aber Fehler ein. Wenn der neue Code sich vor dem Entfernen falsch verhält, existiert der alte Pfad noch. Bleibt ein Backfill zurück, kann er pausieren, ohne das App-Release festzuhalten. Bei einem Deployment-Rollback versteht die alte Anwendung die Datenbank weiterhin. Das zusätzliche Release ist günstiger, als beim Rollback festzustellen, dass das vorherige Binary eine bereits gelöschte Spalte abfragt.
Umbenennungen brauchen besondere Sorgfalt, weil PostgreSQL den Namen sofort ändert. Ein Generator schlägt vielleicht vor, customer_ref in customer_id umzubenennen, weil der neue Name besser klingt. Alte Instanzen scheitern, sobald die Migration committet. Fügen Sie customer_id hinzu, halten Sie beide Felder im Anwendungscode oder über einen eng geprüften Trigger synchron, verschieben Sie Leser und entfernen Sie customer_ref erst, wenn alte Schreiber verschwunden sind. Die vorübergehende Doppelung ist sichtbare Schuld mit einer Bedingung für ihre Beseitigung. Eine sofortige Umbenennung ist unsichtbare Release-Kopplung.
Vorgaben und Nonnull-Constraints können ebenfalls Arbeit verbergen. Zählen Sie vor der Freigabe von SET NOT NULL bestehende Nullwerte und beweisen Sie, dass jeder aktive Schreiber einen Wert liefert. Prüfen Sie bei großen oder stark genutzten Tabellen, wie die PostgreSQL-Version die Constraint validiert und welche Sperren sie nimmt. Ein Builder sollte diese Voraussetzungen melden, statt sie aus einem Schema ohne repräsentativen Verkehr abzuleiten.
Daten-Backfills sollten nicht in einer unbegrenzten Schema-Transaktion mitlaufen. Aktualisieren Sie Zeilen in gemessenen Batches durch einen freigegebenen Worker, erfassen Sie den Fortschritt mit einem stabilen Cursor und gestalten Sie Wiederholungen idempotent. Eine Wiederholung ist idempotent, wenn zweimalige Ausführung den vorgesehenen Zustand erzeugt, nicht nur, wenn PostgreSQL die zweite Abfrage akzeptiert. Bei abgeleiteten Werten erfassen Sie die Herleitungsversion, falls späterer Code sie anders berechnet.
Das Release-Paket sollte vier Kompatibilitätspunkte benennen:
- Die älteste Anwendungsversion, die vor der Migration laufen darf.
- Den Schema-Zustand, den alte und neue Version akzeptieren.
- Das Signal, das den destruktiven Bereinigungs-Release erlaubt.
- Den Wiederherstellungsweg, wenn neuer Code nach Datenänderungen zurückgerollt wird.
Generierte Abfragen sollten in diesen Übergängen SELECT * vermeiden. Eine zusätzliche Spalte kann Scan-Kosten, Ergebnisdekodierung, positionsbezogenes Mapping und Datenoffenlegung ändern, obwohl altes SQL noch parst. Listen Sie qualifizierte Spalten ausdrücklich auf und generieren Sie Decoder aus demselben Schema-Snapshot. So zeigt auch eine Quellcodeprüfung genau, welche Daten die Datenbankgrenze überschreiten.
Vorbereitete Migrationstools verfolgen oft eine angewendete Version in einer Tabelle, doch eine Versionsnummer allein beweist keine Kompatibilität. Speichern Sie den Digest des exakten SQL-Artefakts, denn zwei Dateien mit demselben freundlichen Namen können verschiedene Befehle enthalten. Der Executor sollte eine bereits erfasste Version mit anderem Digest ablehnen. Ebenso sollte er eine spätere Migration ablehnen, wenn ein nötiger Vorgänger fehlt.
Lassen Sie nicht jede Anwendungsinstanz Migrationen beim Start ausführen. Selbst wenn ein Migrationstool einen Advisory Lock nutzt, hängt der Start nun von privilegierten Zugangsdaten und vom Abschluss der Schemaarbeit vor Ablauf der Health Checks ab. Führen Sie Migrationen in einem Release-Job aus, warten Sie auf dessen erfasstes Ergebnis und starten Sie Laufzeitinstanzen mit einer Identität, die das Schema nicht ändern kann. Kann das Release-System diese Phasen nicht trennen, reparieren Sie es, bevor Sie der Anwendung Eigentümerrechte geben.
Testen Sie diese Zeitachse, nicht nur das Ziel: alter Code auf altem Schema, alter Code auf erweitertem Schema, neuer Code auf erweitertem Schema und zurückgerollter Code nach neuen Schreibvorgängen. Die Bereinigung erhält später ihren eigenen Test. Diese Matrix erkennt Änderungen, die syntaktisch gültig, betrieblich aber nicht rückgängig zu machen sind.
Die Grenze mit negativen Tests beweisen
Ein Sicherheitsdesign ist unvollständig, bis verbotene Aktionen im Test scheitern. Verbinden Sie sich als Erkundungsrolle und versuchen Sie einen Insert, das Anlegen einer Tabelle und SET TRANSACTION READ WRITE. Verbinden Sie sich als Laufzeitrolle und versuchen Sie Zugriff auf eine nicht gewährte Tabelle, einen mandantenübergreifenden, durch Row Security geschützten Lesezugriff und eine Schemaänderung. Das erwartete Ergebnis ist ein PostgreSQL-Berechtigungsfehler, kein Versprechen in einem Agent-Log.
Führen Sie auch positive Tests aus. Die Erkundung muss weiterhin jeden erlaubten Katalogeintrag lesen. Die Laufzeit muss jede freigegebene Nutzeraktion über den Pool ausführen. Die Migration darf nur über den Freigabepfad funktionieren. Eine Grenze, die die normale Arbeit des Produkts blockiert, verleitet in einem Vorfall dazu, sie durch Zugangsdaten eines Eigentümers zu ersetzen.
Halten Sie einen kleinen Zugriffsvertrag neben dem Anwendungsquellcode. Er sollte Datenbank, erlaubte Schemas, Erkundungsumfang, Laufzeitvorgänge, Pool-Modus, Timeout-Richtlinie, Migrationsfreigebende, Schema-Fingerprint-Methode und verbotene Statements nennen. Vergleichen Sie die tatsächlichen Rechte in kontinuierlichen Prüfungen mit diesem Vertrag. Drift bei PostgreSQL-Rechten ist Konfigurationsdrift, auch wenn niemand Anwendungscode geändert hat.
Prüfen Sie erneut nach Rollenänderungen, neuen Tabellen, wiederhergestellten Datenbanken, Pool-Upgrades und Hosting-Änderungen. Standardrechte gelten für künftige Objekte: SELECT ON ALL TABLES deckt aktuelle Tabellen ab, nicht später erstellte. Entscheiden Sie, ob neue Objekte bis zur Prüfung unsichtbar bleiben oder über eng konfigurierte Standardrechte einbezogen werden. Ich bevorzuge unsichtbar als Standard, weil eine ausdrückliche Berechtigung die neue Tabelle in die Zugriffsentscheidung zwingt.
Nehmen Sie den Entzug von Rechten in den Testplan auf. Deaktivieren Sie die Erkundungs-Zugangsdaten und bestätigen Sie, dass Laufzeitverkehr weiterläuft. Deaktivieren Sie die Laufzeitdaten und bestätigen Sie, dass Migrationswerkzeuge nicht still ihre stärkere Identität einsetzen. Rotieren Sie dann jedes Secret bei aktiven Verbindungen und beobachten Sie, ob der Pool alte Sitzungen im vorgesehenen Zeitraum beendet. Eine Passwortänderung beendet bereits authentifizierte Sitzungen nicht, daher brauchen Rotationsabläufe ein ausdrückliches Pool-Recycling oder eine Richtlinie zur Beendigung von PostgreSQL-Sitzungen.
Prüfen Sie in diesen Tests Fehlermeldungen auf versehentliche Offenlegung. PostgreSQL-Fehler können Relationsnamen, SQL-Fragmente, Constraint-Namen und übergebene Werte enthalten. Senden Sie detaillierte Fehler in eingeschränkte Server-Logs, geben Sie Clients einen stabilen öffentlichen Fehler zurück und speisen Sie niemals einen gesamten Produktions-Fehlerstrom in ein Agent-Gespräch ein. Der Builder braucht Statement-Position und bereinigte Datenbankantwort, um Code zu reparieren. Er braucht keine Kundenwerte.
Ein letzter Test erkennt überraschend viele unsichere Integrationen: Entfernen Sie die Migrations-Zugangsdaten vollständig und führen Sie die Anwendungstestsuite aus. Falls normaler Start, Health Checks, Vorschauen oder Anfragen fehlschlagen, ist Schema-Eigentümerschaft in den Laufzeitpfad gelangt. Beseitigen Sie diese Kopplung, bevor Sie den Builder mit Produktion verbinden. Ein KI-App-Builder kann mit einer Datenbank arbeiten, die ihm nicht gehört, aber PostgreSQL muss Nein sagen können, wenn generierter Code diese Vereinbarung vergisst.
FAQ
Kann ein KI-App-Builder meine vorhandene PostgreSQL-Datenbank nutzen?
Ja, wenn der Builder über eigene Rollen zugreift und nur freigegebene Schemas untersucht. Halten Sie Erkundung, Laufzeitabfragen und Migrationen auf getrennten Berechtigungspfaden, damit die Verbindung des Tools keine Schema-Eigentümerschaft verleiht.
Garantiert ein schreibgeschützter PostgreSQL-Benutzer, dass sich keine Daten ändern können?
Eine Rolle mit ausschließlich SELECT und ohne Eigentümerschaft an Objekten ist die wichtigste Kontrolle. default_transaction_read_only bietet zusätzlichen Schutz, darf aber keine zu weit gefassten Rechte oder geerbten Mitgliedschaften ausgleichen.
Soll ich dem Builder das Passwort meines Datenbank-Eigentümers geben?
Nein. Zugangsdaten eines Eigentümers heben die Grenze auf und erlauben generiertem SQL, Berechtigungen, Tabellen und Daten zu ändern. Verwenden Sie getrennte Zugangsdaten für Erkundung, Laufzeit und den kontrollierten Migrationsjob.
Wie kann ein App-Builder mein Schema sicher kennenlernen?
Lassen Sie ihn über eine eingeschränkte Rolle freigegebene Ansichten von information_schema und pg_catalog abfragen und speichern Sie anschließend einen Snapshot mit Fingerprint. Verzichten Sie auf Stichproben von Zeilen, sofern dafür keine maskierte View vorbereitet wurde.
Was passiert, wenn die KI eine PostgreSQL-Spalte erfindet?
Die Generierung sollte vor dem Deployment an einem typisierten Schema-Snapshot scheitern. Melden Sie den unbekannten Namen und ähnliche gültige Namen, aber lassen Sie einen Menschen entscheiden, ob Code, eine neue Erkundung oder eine freigegebene Migration die Lösung ist.
Kann die Anwendung sich direkt aus einem Browser oder einer Mobil-App verbinden?
Sie sollte sich nicht direkt mit PostgreSQL verbinden, denn diese Clients können ein Datenbankpasswort nicht geheim halten. Legen Sie den Datenbankzugriff in einen Serverprozess und lassen Sie Browser oder Mobil-App dessen API aufrufen.
Brauche ich für generierte Anwendungen einen Connection Pool?
Meistens ja, aber bewusst konfiguriert. Begrenzen Sie die Gesamtzahl der Sitzungen, wählen Sie Sitzungs- oder Transaktionsmodus, setzen Sie veränderlichen Zustand zurück und testen Sie generierten Code über denselben Pool wie in Produktion.
Kann man PostgreSQL-Migrationen sicher zurückrollen?
Manche Katalogänderungen lassen sich sauber innerhalb einer Transaktion umkehren, Datenverlust und externe Nebenwirkungen jedoch nicht. Prüfen Sie Vorwärts- und Umkehr-SQL getrennt und betrachten Sie Snapshots als Wiederherstellungswerkzeuge, nicht als Beweis für eine sichere Änderung.
Wie verhindere ich, dass der Builder nicht freigegebene Tabellen ändert?
Nutzen Sie Schema-Allowlist, qualifizierte Namen, enge Rechte, eine geparste SQL-Richtlinie und negative Berechtigungstests. Die PostgreSQL-Rolle muss die Aktion ablehnen, selbst wenn Modell oder Richtlinienprüfung einen Fehler machen.
Wie oft sollte der App-Builder das Schema erneut erkunden?
Führen Sie die Erkundung erneut aus, sobald der gespeicherte Fingerprint abweicht, sowie nach Migrationen, Wiederherstellungen oder Umgebungsänderungen. Aktualisieren Sie nicht still während eines Releases, sondern zeigen Sie den Unterschied und validieren Sie gegen den neuen Snapshot erneut.