Akses database PostgreSQL untuk AI app builder
Siapkan akses database PostgreSQL untuk AI app builder dengan discovery read-only, kredensial terbatas, migrasi yang disetujui, dan pooling yang aman.

AI app builder dapat terhubung ke database PostgreSQL yang sudah ada tanpa memiliki skemanya, tetapi batas itu harus benar-benar diterapkan di PostgreSQL. Prompt yang berbunyi "jangan ubah produksi" bukanlah kontrol. Peran terpisah, default transaksi, peninjauan migrasi yang eksplisit, dan pemeriksaan skema adalah kontrol.
Model yang aman membagi pekerjaan database ke dalam tiga jalur. Discovery membaca metadata dan sampel data yang diizinkan. Aplikasi hanya membaca dan menulis tabel serta operasi yang dibutuhkannya. Perubahan skema berjalan melalui identitas migrasi terpisah setelah manusia menyetujui SQL yang persis. Saya pernah melihat tim menyatukan ketiga jalur itu ke satu kredensial pemilik yang praktis, lalu mendapati agen menganggap nama kolom yang masuk akal sebagai izin untuk merombak tabel aktif. Kepraktisannya hanya bertahan satu sore, sedangkan pembersihannya jauh lebih lama.
Discovery harus read-only sejak awal
Koneksi discovery memerlukan akses yang cukup untuk memahami skema yang diizinkan, bukan untuk memperbaikinya. Buat peran login yang tidak dapat membuat database atau peran, tidak dapat melewati row security, dan tidak dapat mewarisi hak tak terduga dari grup yang terlalu luas. PostgreSQL membuat peran baru tanpa kemampuan tersebut, tetapi deklarasi eksplisit membuat maksudnya mudah ditinjau.
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 memblokir penulisan biasa dalam sesi yang mempertahankan default tersebut. Ini lapisan tambahan yang berguna, bukan satu-satunya pengaman. Ketiadaan INSERT, UPDATE, DELETE, TRUNCATE, CREATE, dan kepemilikanlah yang menjaga peran tetap terbatas jika klien mengubah pengaturan transaksinya. Jangan beri peran ini keanggotaan dalam grup pemilik aplikasi, dan jangan jadikan ia pemilik skema.
Grant yang sudah ada perlu diperiksa sebelum builder terhubung. Kueri berikut menghasilkan satu baris untuk setiap hak akses tabel, sehingga peninjau dapat melihat apa pun selain SELECT:
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;
Hasil yang sehat berbentuk seperti app | invoices | SELECT. Hasil kosong dapat berarti discovery tidak dapat melihat tabel yang dibutuhkan, sedangkan baris yang berakhir dengan UPDATE berarti peran terlalu berkuasa. Periksa juga hak skema dengan has_schema_privilege dan hak database dengan has_database_privilege, karena grant tabel tidak menunjukkan apakah peran dapat membuat objek di tempat lain.
Jangan gunakan snapshot produksi sebagai alasan untuk membagikan kredensial pemilik. Salinan tetap dapat berisi data pelanggan, dan agen yang memiliki kepemilikan dapat mengubahnya sedemikian rupa hingga perbandingan selanjutnya tidak berguna. Berikan discovery identitas khusus di setiap lingkungan.
Pemeriksaan katalog harus tetap berada dalam allowlist
Builder seharusnya hanya menemukan skema yang disetujui dan mencatat apa yang benar-benar dilaporkan PostgreSQL. information_schema menyediakan tampilan portabel untuk tabel, kolom, constraint, dan izin. pg_catalog memaparkan detail PostgreSQL seperti indeks, tipe, ekspresi terhasil, dan row security. Keduanya lebih baik daripada ingatan LLM tentang tabel pelanggan pada umumnya.
Mulailah dengan allowlist seperti app dan reporting. Tolak pg_catalog, information_schema, skema sementara, skema ekstensi, dan semua skema tenant yang tidak tercantum sebagai target aplikasi. Kueri harus memfilter pada level database, peran, dan SQL, allowlist pada level prompt saja dapat hilang dalam percakapan berikutnya.
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;
Simpan hasilnya sebagai snapshot skema dengan waktu pengambilan dan pengenal database. Snapshot adalah bukti tentang apa yang dilihat generator. Itu bukan kebenaran permanen. PostgreSQL dapat berubah antara discovery dan pembuatan kode, jadi bandingkan sidik terbaru sebelum deployment. Sidik yang praktis dapat melakukan hash atas deskripsi tabel, kolom, tipe, nullable, default, constraint, dan indeks yang sudah diurutkan. Jika sidiknya berbeda, berhenti dan lakukan discovery ulang, jangan menebak perubahan mana yang tidak berbahaya.
Mengambil sampel baris adalah keputusan izin yang terpisah. Metadata kolom jarang memuat data pribadi, sedangkan sampel baris sering kali memuatnya. Utamakan tanpa pengambilan sampel baris untuk pembuatan kode. Jika contoh memang diperlukan, sediakan tampilan yang menghapus atau menyamarkan rahasia dan pengenal langsung, lalu beri SELECT hanya pada tampilan itu. LIMIT 10 tidak menjadikan kueri sensitif aman, hanya memperkecil kebocorannya.
search_path layak mendapat perlakuan yang sama. Atur ke skema yang disetujui ditambah pg_catalog, gunakan nama tabel yang memenuhi kualifikasi dalam kode yang dihasilkan, dan jangan bergantung pada objek mana pun yang ditemukan PostgreSQL lebih dahulu. Penyerang atau migrasi yang ceroboh dapat membuat objek bernama sama di skema yang dapat ditulis. Nama yang memenuhi kualifikasi seperti app.orders menghilangkan ambiguitas itu.
Peran runtime harus sesuai dengan tindakan pengguna yang nyata
Discovery dan runtime adalah pekerjaan berbeda. Aplikasi runtime mungkin perlu memasukkan pesanan, memperbarui draf, atau memanggil fungsi yang dirancang dengan hati-hati, tetapi itu tidak membenarkan akses tulis yang luas ke seluruh skema yang ditemukan. Buat matriks izin dari tindakan pengguna, lalu terjemahkan setiap tindakan menjadi grant PostgreSQL sekecil mungkin.
Misalnya, penampil faktur mungkin memerlukan SELECT pada app.invoices dan app.invoice_lines, sedangkan fitur catatan membutuhkan SELECT dan INSERT pada app.invoice_notes. Fitur itu kemungkinan tidak perlu DELETE pada faktur, akses ke catatan reset kata sandi, atau pembuatan skema. Beri penggunaan sequence hanya jika operasi insert memang bergantung pada sequence itu. PostgreSQL memperlakukan sequence sebagai objek terpisah, hal ini sering mengejutkan generator yang menguji dengan akun pemilik.
Tampilan dan fungsi dapat mempersempit permukaan akses lebih jauh. Tampilan dapat menampilkan kolom yang disetujui sambil menyembunyikan bidang internal. Fungsi SECURITY DEFINER dapat menjalankan satu operasi terkontrol yang tidak dapat diungkapkan oleh grant biasa, tetapi fungsi itu memerlukan search_path tetap, pemeriksaan input yang ketat, dan pemilik tanpa kekuasaan yang tidak perlu. Perlakukan fungsi seperti itu sebagai kode berhak istimewa, bukan jalan pintas melewati model izin.
Row level security menambahkan batas data di dalam tabel bersama. Itu tidak menggantikan grant tabel. PostgreSQL lebih dahulu memeriksa apakah peran boleh melakukan operasi, lalu menerapkan kebijakan row security jika diaktifkan dan berlaku. Uji dengan peran runtime yang persis karena pemilik tabel dan peran dengan BYPASSRLS dapat lolos dari kebijakan. Pengujian dengan pemilik migrasi hampir tidak membuktikan apa pun tentang yang dapat dilihat pengguna akhir.
Jauhkan rahasia dari prompt, kode sumber yang dihasilkan, bundle browser, log build, dan tangkapan layar. Simpan kredensial runtime di secret store lingkungan hosting dan masukkan hanya ke proses server. Aplikasi seluler dan browser tidak dapat menyimpan kata sandi PostgreSQL sebagai rahasia, jadi keduanya perlu memanggil API server, bukan terhubung langsung. Rotasi kredensial discovery, runtime, dan migrasi secara mandiri, kebocoran di satu jalur tidak boleh membuka dua jalur lainnya.
Kuasa migrasi harus berada pada jalur persetujuan terpisah
App builder dapat mengusulkan migrasi, tetapi tidak boleh mengeksekusinya dengan sesi discovery atau runtime. Beri pekerjaan migrasi peran terpisah, atau biarkan sistem deployment yang sudah ada mengambil peran itu untuk satu tugas yang disetujui. Jangan sediakan kredensialnya selama sesi chat dan pratinjau biasa.
Persetujuan harus mencakup SQL yang persis, identitas database target, sidik skema yang dipakai untuk menyiapkannya, serta perilaku lock atau rewrite yang diharapkan. Menyetujui kalimat bahasa alami seperti "tambahkan status pelanggan" menyisakan terlalu banyak ruang. Perubahan yang dapat dieksekusi mungkin menambah kolom teks nullable, membangun ulang tabel besar, menciptakan enum, atau memperbarui setiap baris yang ada. Semua itu adalah operasi berbeda dengan mode kegagalan berbeda.
Saya menggunakan paket migrasi ringkas:
- Alasan perubahan dan versi aplikasi yang memerlukannya.
- SQL maju yang persis dan, bila jujur, SQL pembalikan yang persis.
- Objek, izin, dan baris yang dapat dipengaruhi perintah.
- Kueri preflight, hasil yang diharapkan, dan sidik skema terbaru.
lock_timeout,statement_timeout, referensi backup atau snapshot, dan pemilik rilis.
Skrip pembalikan tidak selalu berarti rollback. Menghapus kolom yang baru ditambahkan dapat membalikkan perubahan katalog, tetapi juga menghancurkan data yang ditulis setelah rilis. DDL transaksional PostgreSQL membantu banyak operasi katalog, namun transaksi tidak dapat memulihkan efek samping eksternal atau data yang dihapus perintah berikutnya. Tandai pembalikan yang destruktif dengan jelas, jangan memperlakukan DOWN sebagai kata ajaib.
Atur lock_timeout agar migrasi gagal alih-alih menunggu transaksi sibuk sambil memblokir pekerjaan baru. Atur statement_timeout sesuai operasi yang ditinjau. Jalankan lagi kueri preflight di dalam jendela perubahan. Jika ukuran tabel, objek yang berkonflik, jumlah null, atau sidik skema berbeda dari asumsi yang disetujui, batalkan. Agen harus mengembalikan laporan ketidakcocokan, bukan mengimprovisasi migrasi baru terhadap produksi.
Jangan pernah menyetujui migrasi secara otomatis hanya karena pengujian yang dihasilkan lulus. Pengujian biasanya berjalan pada skema kecil dan bersih, serta melewatkan antrean lock, null lama, constraint yang tidak umum, ekstensi, dan versi aplikasi yang masih melayani trafik. Persetujuan adalah saat seseorang mencocokkan maksud yang dihasilkan dengan sistem aktif.
Connection pooling mengubah perhitungan keamanan
Pool menggunakan ulang sesi database, sehingga status sesi dapat bertahan setelah permintaan yang membuatnya selesai. Jika satu permintaan menjalankan SET search_path, mengubah peran, membuat objek sementara, atau menonaktifkan timeout, peminjam berikutnya mungkin mewarisi hasilnya. Aplikasi perlu menghindari status sesi yang dapat berubah atau meresetnya secara andal ketika koneksi kembali ke pool.
Transaction pooling membuat batasnya lebih ketat. Klien dapat memperoleh sesi server berbeda setelah setiap transaksi, yang mematahkan asumsi tentang prepared statement tingkat sesi, tabel sementara, advisory lock, dan pengaturan tingkat sesi. Builder sering menghasilkan kode yang berfungsi melalui koneksi langsung lalu gagal di balik pool karena perbedaan ini tidak dimodelkan. Tentukan apakah pool memakai mode sesi atau transaksi, lalu sertakan mode itu dalam pembuatan kode dan pengujian.
Hitung anggaran koneksi sebelum deployment. Mulai dari koneksi yang diizinkan database, sisihkan kapasitas untuk administrasi, migrasi, pemantauan, dan layanan lain, lalu bagi sisanya ke seluruh instance aplikasi. Jika sepuluh instance masing-masing membuka dua puluh koneksi, PostgreSQL melihat dua ratus sesi potensial bahkan ketika trafik sepi. Pool kecil yang konservatif dengan antrean biasanya lebih aman daripada menggandakan koneksi sampai database menolaknya.
Gunakan timeout sisi server sebagai pengaman: statement_timeout membatasi statement yang panjang, lock_timeout membatasi waktu menunggu lock, dan idle_in_transaction_session_timeout menghapus sesi yang menahan transaksi terbuka tanpa melakukan apa pun. Atur nilainya untuk setiap peran, jangan percaya bahwa setiap klien yang dihasilkan akan selalu mengingatnya. Verifikasi dengan SHOW di bawah peran aktual dan melalui pool aktual.
Health check harus ringan. SELECT 1 mengonfirmasi perjalanan pulang-pergi, tetapi tidak mengonfirmasi aplikasi dapat menjangkau tabel yang disetujui atau search_path-nya benar. Pemeriksaan kesiapan dapat mengkueri tampilan kecil yang stabil dengan peran runtime. Jauhkan migrasi dari startup aplikasi, instance yang berjalan serentak dan berlomba mengubah skema menciptakan keterikatan yang justru hendak dihilangkan desain ini.
Kolom yang dikarang harus gagal sebelum kueri dijalankan
LLM mengarang identifier yang terdengar masuk akal. Jika prompt membahas nama tampilan pelanggan, kode yang dihasilkan mungkin mencoba memakai customers.display_name padahal database menyimpan given_name dan family_name. Database akan menolak kueri itu, dan itu lebih baik daripada diam-diam membaca bidang yang salah, tetapi error produksi tetap bukan strategi validasi skema yang baik.
Hasilkan artefak skema bertipe dari snapshot katalog yang disetujui dan jadikan itu satu-satunya sumber untuk membangun kueri. Tabel atau kolom yang tidak ada dalam artefak harus menimbulkan error pembuatan. Jangan biarkan model memperbaiki error dengan menambahkan migrasi kecuali tugas secara eksplisit memasuki jalur migrasi. Identifier yang hilang dapat berarti discovery kedaluwarsa, salah eja, lingkungan yang salah, atau kebutuhan produk yang nyata. Masing-masing memerlukan respons berbeda.
Pemeriksaan statis perlu mem-parse SQL dan menyelesaikan setiap relasi serta kolom terhadap snapshot. Setelah itu, siapkan statement terhadap database sekali pakai atau transaksi yang tidak dapat menulis. Parser PostgreSQL menangkap kolom yang tidak dikenal, referensi ambigu, error tipe operator, dan banyak cast yang buruk tanpa memerlukan data bisnis yang berhasil. Jalankan pengujian integrasi dengan peran runtime agar izin dan kebijakan baris ikut diuji.
Laporan kegagalan perlu cukup detail agar seseorang dapat memutuskan. Sertakan lokasi SQL, identifier yang tidak terselesaikan, identifier valid di sekitarnya, sidik snapshot, dan identitas database target. Saran berguna, tetapi penggantian fuzzy otomatis berbahaya. Mengubah billing_address_id menjadi shipping_address_id karena namanya mirip dapat menghasilkan SQL yang valid dengan makna bisnis yang salah.
Untuk filter dan pengurutan dinamis, petakan nama API publik ke himpunan tertutup ekspresi SQL yang memenuhi kualifikasi. Jangan pernah menempelkan identifier yang diberikan model ke SQL, bahkan melalui parameter nilai. Parameter melindungi nilai, bukan nama tabel atau kolom. Jika pengguna dapat memilih bidang urut, terjemahkan created ke ekspresi yang dikenal seperti app.orders.created_at, lalu tolak setiap token yang tidak dikenal.
Schema drift harus menghentikan rilis, bukan memicu rekonsiliasi kreatif. Buat ulang snapshot, tampilkan perbedaannya, dan ulangi pengujian. Penundaan ini mungkin terasa merepotkan, tetapi lebih murah daripada menerapkan kode yang pemahamannya tentang database hanya ada dalam transkrip percakapan.
SQL destruktif memerlukan kebijakan penolakan dan bukti
Builder harus mengklasifikasikan SQL sebelum siapa pun dapat mengeksekusinya. Blokir DROP, TRUNCATE, DELETE atau UPDATE luas tanpa predikat yang ditinjau, perubahan kepemilikan, eskalasi izin, perubahan ekstensi, dan perintah yang menyasar di luar skema yang disetujui. Perlakukan ALTER TABLE sebagai wajib ditinjau, bukan otomatis aman. Perubahan tipe kolom atau constraint nonnull baru dapat memindai atau menulis ulang data dan menahan lock yang berdampak besar.
Pencocokan teks saja lemah karena SQL memiliki komentar, identifier berkutip, fungsi, dan banyak cara untuk menyatakan efek samping. Parse statement dengan parser yang memahami PostgreSQL, periksa syntax tree-nya, dan tetap andalkan peran database untuk menolak tindakan terlarang. Pengklasifikasi memperbaiki peninjauan, sedangkan hak akses menegakkan batas. Keduanya tidak boleh memikul seluruh beban sendiri.
Gunakan database staging yang dipulihkan dari snapshot terbaru yang dilindungi dengan benar saat migrasi bergantung pada bentuk tabel atau distribusi data nyata. Terapkan paket migrasi yang persis di sana, catat durasi dan pengamatan lock, jalankan pengujian aplikasi dengan kredensial runtime, lalu buang lingkungan tersebut. Jangan diam-diam mengedit SQL antara staging dan produksi. Setiap edit menciptakan artefak baru yang memerlukan sidik dan persetujuan baru.
Log harus menghubungkan proposal dengan eksekusi tanpa merekam rahasia atau baris sensitif. Catat siapa yang menyetujui artefak migrasi yang tidak dapat diubah, digest-nya, identitas target, status mulai dan selesai, serta detail error PostgreSQL. Simpan diff yang dihasilkan dan hasil preflight. Chat agen berguna sebagai konteks, tetapi bukan catatan audit karena pengguna dapat membuat cabang, mencoba ulang, dan memparafrasekan instruksi.
Snapshot dan kontrol rollback mengurangi waktu pemulihan, tetapi tidak menjadikan SQL destruktif dapat diterima. Snapshot mungkin memulihkan seluruh database ke titik sebelumnya ketika kebutuhan sebenarnya hanya satu kolom yang terhapus, dan pemulihan dapat membuang penulisan sah yang terjadi setelah snapshot. Uji pemulihan secara terpisah dan dokumentasikan siapa yang dapat menjalankannya.
Saat menggunakan Koder.ai untuk aplikasi yang menyentuh database yang sudah ada, saya mempertahankan pekerjaan dalam mode perencanaan sampai saya meninjau kode sumber yang diekspor dan batas database yang diusulkan. Snapshot dan rollback adalah kontrol pemulihan, bukan izin untuk melewati peninjauan itu. Aturan yang sama berlaku bagi builder apa pun: kenyamanan produk harus berada di balik penegakan database.
Perubahan skema harus tahan terhadap versi aplikasi campuran
Migrasi hanya aman jika aplikasi lama dan aplikasi baru dapat berjalan selama jendela rilis. Produksi jarang berpindah dari satu versi ke versi lain dalam satu saat. Permintaan dapat mencapai instance lama ketika instance baru mulai, job antrean dapat membawa payload lama, dan rollback dapat mengembalikan kode kemarin ke skema hari ini. App builder yang hanya memvalidasi kode akhir terhadap skema akhir akan melewatkan masa tumpang tindih ini.
Utamakan perubahan aditif. Tambahkan kolom nullable, tabel baru, atau indeks tanpa menghapus jalur lama. Terapkan kode yang dapat membaca kedua representasi dan menulis representasi baru bila sesuai. Isi ulang baris yang ada melalui job terpisah yang ditinjau, pantau error dan keterlambatan, lalu jadikan bidang baru sebagai sumber utama. Hapus kolom atau constraint lama pada rilis berikutnya setelah bukti menunjukkan tidak ada kode yang berjalan masih menggunakannya.
Urutan ini lebih lama daripada menghasilkan satu statement ALTER TABLE, tetapi mengisolasi kegagalan. Jika kode baru bermasalah sebelum penghapusan, jalur lama masih ada. Jika backfill tertinggal, prosesnya dapat dijeda tanpa menahan rilis aplikasi. Jika deployment di-rollback, aplikasi lama masih mengenali database. Rilis tambahan lebih murah daripada mengetahui saat rollback bahwa binary sebelumnya mengkueri kolom yang sudah dihapus migrasi.
Penggantian nama perlu perhatian khusus karena PostgreSQL langsung mengubah nama. Generator mungkin mengusulkan mengganti customer_ref menjadi customer_id karena nama baru lebih mudah dibaca. Instance lama akan gagal segera setelah migrasi di-commit. Tambahkan customer_id, jaga kedua bidang tetap sinkron dalam kode aplikasi atau trigger yang ditinjau secara ketat, pindahkan pembaca, lalu hapus customer_ref hanya setelah penulis lama tidak ada lagi. Duplikasi sementara adalah utang yang terlihat dengan syarat penghapusan, sedangkan penggantian nama langsung adalah keterikatan rilis yang tidak terlihat.
Default dan constraint nonnull juga dapat menyembunyikan pekerjaan. Sebelum menyetujui SET NOT NULL, hitung null yang ada dan buktikan setiap penulis aktif memberikan nilai. Untuk tabel besar atau sibuk, tinjau cara versi PostgreSQL memvalidasi constraint dan lock yang diambilnya. Builder perlu melaporkan prasyarat itu, bukan menyimpulkannya dari skema tanpa trafik yang representatif.
Backfill data tidak boleh berjalan di dalam transaksi skema tanpa batas. Perbarui baris dalam batch terukur melalui worker yang disetujui, catat kemajuan dengan kursor stabil, dan buat percobaan ulang idempoten. Percobaan ulang idempoten berarti menerapkannya dua kali menghasilkan keadaan yang diinginkan, bukan sekadar PostgreSQL menerima kueri kedua. Untuk nilai turunan, catat versi derivasi jika kode berikutnya mungkin menghitungnya secara berbeda.
Paket rilis harus menyebutkan empat titik kompatibilitas:
- Versi aplikasi tertua yang boleh berjalan sebelum migrasi.
- Keadaan skema yang diterima oleh versi lama dan baru.
- Sinyal yang mengizinkan rilis pembersihan destruktif.
- Jalur pemulihan jika kode baru di-rollback setelah data berubah.
Kueri yang dihasilkan sebaiknya menghindari SELECT * selama transisi ini. Menambahkan kolom dapat mengubah biaya scan, decoding hasil, pemetaan posisi, dan paparan data meski SQL lama masih dapat di-parse. Daftarkan kolom yang memenuhi kualifikasi secara eksplisit dan hasilkan decoder dari snapshot skema yang sama. Ini juga membuat peninjauan kode memperlihatkan dengan tepat data apa yang melintasi batas database.
Alat migrasi yang sudah disiapkan sering melacak versi yang diterapkan dalam tabel, tetapi nomor versi saja tidak membuktikan kompatibilitas. Catat digest artefak SQL yang persis karena dua file dengan nama ramah yang sama dapat berisi perintah berbeda. Eksekutor harus menolak versi yang sudah tercatat dengan digest berbeda. Ia juga harus menolak migrasi berikutnya bila pendahulu yang diperlukan tidak ada.
Jangan biarkan setiap instance aplikasi menjalankan migrasi saat startup. Bahkan bila alat migrasi memakai advisory lock, startup kini bergantung pada kredensial berhak istimewa dan pekerjaan skema selesai sebelum health check habis. Jalankan migrasi dalam satu job rilis, tunggu hasil yang tercatat, dan mulai instance runtime dengan identitas yang tidak dapat mengubah skema. Jika sistem rilis tidak dapat memisahkan fase-fase itu, perbaiki sistem rilis sebelum memberi aplikasi kekuasaan pemilik.
Uji linimasa ini, bukan hanya tujuan akhirnya: kode lama pada skema lama, kode lama pada skema yang diperluas, kode baru pada skema yang diperluas, dan kode yang di-rollback setelah penulisan baru. Pembersihan mendapat pengujian tersendiri kemudian. Matriks ini menangkap perubahan yang valid secara sintaks tetapi tidak mungkin dibalik secara operasional.
Buktikan batas dengan pengujian negatif
Desain keamanan belum lengkap sampai tindakan terlarang gagal saat diuji. Hubungkan sebagai discovery lalu coba insert, pembuatan tabel, dan SET TRANSACTION READ WRITE. Hubungkan sebagai runtime lalu coba akses tabel tanpa grant, pembacaan lintas tenant yang dilindungi row security, dan perubahan skema. Hasil yang diharapkan adalah error izin PostgreSQL, bukan janji dalam log agen.
Jalankan juga pengujian positif. Discovery tetap harus membaca setiap entri katalog yang diizinkan. Runtime harus menjalankan setiap tindakan pengguna yang disetujui melalui pool. Eksekusi migrasi harus berfungsi hanya lewat jalur persetujuan. Batas yang menghalangi pekerjaan normal produk akan mengundang seseorang menggantinya dengan kredensial pemilik saat terjadi insiden.
Simpan kontrak akses kecil di samping kode sumber aplikasi. Kontrak itu harus menyebut database, skema yang diizinkan, cakupan discovery, operasi runtime, mode pool, kebijakan timeout, penyetuju migrasi, metode sidik skema, dan statement yang dilarang. Bandingkan grant aktual dengan kontrak itu dalam pemeriksaan berkelanjutan. Pergeseran grant PostgreSQL adalah pergeseran konfigurasi, bahkan ketika tidak ada yang mengubah kode aplikasi.
Periksa ulang setelah perubahan peran, tabel baru, database yang dipulihkan, peningkatan pool, dan perubahan hosting. Hak akses default penting untuk objek yang akan datang: memberi SELECT ON ALL TABLES mencakup tabel saat ini, bukan tabel yang dibuat kemudian. Putuskan apakah objek baru harus tidak terlihat sampai ditinjau atau disertakan melalui default privileges yang dikonfigurasi secara sempit. Saya lebih memilih tidak terlihat secara default karena grant eksplisit memaksa tabel baru masuk ke pembahasan akses.
Sertakan pencabutan dalam rencana pengujian. Nonaktifkan kredensial discovery dan pastikan trafik runtime tetap berjalan; nonaktifkan runtime dan pastikan alat migrasi tidak diam-diam mengganti dengan identitasnya yang lebih kuat. Kemudian rotasi setiap secret saat koneksi aktif dan amati apakah pool menghentikan sesi lama dalam jendela yang ditentukan. Perubahan kata sandi tidak mengakhiri sesi yang sudah terautentikasi, sehingga prosedur rotasi memerlukan daur ulang pool yang eksplisit atau kebijakan penghentian sesi PostgreSQL.
Tinjau pesan kegagalan untuk kebocoran tidak disengaja selama pengujian ini. Error PostgreSQL dapat memuat nama relasi, fragmen SQL, nama constraint, dan nilai yang diberikan. Kirim error terperinci ke log server yang terbatas, kembalikan error publik yang stabil kepada klien, dan jangan pernah memasukkan seluruh aliran error produksi ke percakapan agen. Builder memerlukan lokasi statement dan respons database yang sudah disanitasi untuk memperbaiki kode, ia tidak memerlukan nilai pelanggan.
Satu pengujian terakhir menangkap banyak integrasi yang tidak aman: hapus sepenuhnya kredensial migrasi lalu jalankan test suite aplikasi. Jika startup normal, health check, pratinjau, atau penanganan permintaan gagal, kepemilikan skema telah bocor ke jalur runtime. Perbaiki keterikatan itu sebelum menghubungkan builder ke produksi. AI app builder dapat bekerja dengan database yang tidak dimilikinya, tetapi PostgreSQL harus mampu berkata tidak saat kode yang dihasilkan melupakan kesepakatan tersebut.
Pertanyaan umum
Bisakah AI app builder menggunakan database PostgreSQL saya yang sudah ada?
Bisa, jika builder terhubung melalui peran khusus dan hanya menelusuri skema yang disetujui. Pisahkan discovery, kueri runtime, dan migrasi ke jalur izin berbeda agar menghubungkan alat ini tidak sekaligus memberi kepemilikan skema.
Apakah pengguna PostgreSQL read-only menjamin data tidak dapat berubah?
Peran yang hanya memiliki SELECT dan tidak memiliki objek adalah kontrol utama. default_transaction_read_only menambah perlindungan, tetapi tidak boleh dijadikan pengganti untuk grant yang terlalu luas atau keanggotaan yang diwariskan.
Haruskah saya memberikan kata sandi pemilik database kepada builder?
Tidak. Kredensial pemilik meniadakan batas keamanan dan memungkinkan SQL yang dihasilkan mengubah izin, tabel, dan data. Buat kredensial terpisah untuk discovery, runtime, dan tugas migrasi yang terkontrol.
Bagaimana app builder dapat mempelajari skema saya dengan aman?
Izinkan alat ini mengkueri tampilan information_schema dan pg_catalog yang disetujui melalui peran dengan cakupan terbatas, lalu simpan snapshot berjejak sidik. Hindari pengambilan sampel baris kecuali tampilan yang telah disamarkan memang disiapkan untuk tujuan itu.
Apa yang terjadi jika AI mengarang kolom PostgreSQL?
Pembuatan kode harus gagal terhadap snapshot skema bertipe sebelum deployment. Laporkan nama yang tidak dikenal dan nama valid di sekitarnya, tetapi biarkan orang yang menentukan apakah perbaikannya berupa kode, discovery ulang, atau migrasi yang disetujui.
Bisakah aplikasi terhubung langsung dari browser atau aplikasi seluler?
Aplikasi tidak boleh terhubung langsung ke PostgreSQL karena klien tersebut tidak dapat menyimpan kata sandi database sebagai rahasia. Letakkan akses database dalam proses server dan biarkan browser atau aplikasi seluler memanggil API-nya.
Apakah aplikasi yang dihasilkan memerlukan connection pool?
Biasanya perlu, tetapi konfigurasikan dengan sengaja. Batasi jumlah sesi, pilih mode sesi atau transaksi, reset status yang dapat berubah, dan uji kode yang dihasilkan melalui pool yang sama dengan produksi.
Bisakah migrasi PostgreSQL di-rollback dengan aman?
Beberapa perubahan katalog dapat dibalik dengan bersih di dalam transaksi, sedangkan kehilangan data dan efek samping eksternal tidak. Tinjau SQL maju dan SQL pembalikan secara terpisah, lalu anggap snapshot sebagai alat pemulihan, bukan bukti bahwa perubahan aman.
Bagaimana cara mencegah builder mengubah tabel yang belum disetujui?
Gunakan allowlist skema, nama yang memenuhi kualifikasi, grant sempit, kebijakan SQL yang diparse, dan pengujian izin negatif. Peran PostgreSQL harus menolak operasi itu bahkan jika model atau pemeriksa kebijakan melakukan kesalahan.
Seberapa sering app builder harus melakukan discovery ulang terhadap skema?
Lakukan discovery ulang setiap kali sidik yang tersimpan berbeda dan setelah migrasi, pemulihan, atau perubahan lingkungan. Jangan melakukan refresh diam-diam saat rilis, tampilkan perbedaannya dan jalankan ulang validasi terhadap snapshot baru.