Baca migration Supabase sebagai sumber kebenaran: tabel, index, RLS, fungsi lookup, trigger nomor donasi, status guard, dan seed campaign.
35m bacaanKuis WajibMicro Badge Lesson
Jalankan Migration & Pahami Seed
Data contract sudah menjelaskan peta. Sekarang kita cek tanah aslinya: database.
Di project AI coding, migration bukan sekadar file SQL. Migration adalah cara kamu membuktikan bahwa struktur yang kamu bicarakan benar-benar bisa dibuat. Kalau migration gagal, semua prompt fitur setelahnya akan berdiri di atas asumsi yang rapuh.
Starter memakai satu migration inti:
text
supabase/migrations/20260829_vertical_slice.sql
File ini membuat:
extension pgcrypto;
tabel campaigns, donors, donations, payments;
index untuk donation flow;
RLS policy;
fungsi lookup guest;
sequence dan trigger nomor donasi;
trigger penjaga transisi status;
seed campaign contoh.
Jalankan di database yang benar
Buka Supabase Dashboard → SQL Editor. Pastikan kamu berada di project yang sama dengan .env.local.
Cara aman mengecek tanpa menampilkan nilai secret:
bash
grep -E '^NEXT_PUBLIC_SUPABASE_URL=' .env.local
Cocokkan project ref pada URL dengan dashboard yang sedang kamu buka. Jangan paste nilai env ke chat atau laporan.
Setelah yakin project benar, buka isi migration, paste ke SQL Editor, lalu Run.
Kalau migration sudah pernah dijalankan, sebagian statement aman karena memakai if not exists dan on conflict. Tetapi policy dengan nama yang sama bisa tetap bentrok di database tertentu. Kalau muncul error “policy already exists”, itu berarti struktur kemungkinan sudah pernah dibuat. Jangan langsung hapus policy. Cek dulu via dashboard atau query introspeksi.
Baca struktur tabel
Jalankan query ini di SQL Editor:
sql
select table_namefrom information_schema.tableswhere table_schema = 'public' and table_name in ('campaigns', 'donors', 'donations', 'payments')order by table_name;
Output yang kamu harapkan:
text
campaignsdonationsdonorspayments
Urutannya bisa berbeda tergantung tampilan, tapi empat tabel itu harus ada.
Lalu cek kolom penting:
sql
select table_name, column_name, is_nullable, data_typefrom information_schema.columnswhere table_schema = 'public' and table_name in ('campaigns', 'donors', 'donations', 'payments') and column_name in ( 'slug', 'status', 'campaign_id', 'donor_id', 'donation_number', 'payment_method', 'lookup_token_hash', 'idempotency_key', 'donation_id' )order by table_name, column_name;
Dari sini kamu bisa membuktikan beberapa hal:
campaigns.slug ada;
donations.campaign_id tidak nullable;
donations.donor_id nullable;
donations.donation_number ada dan unik di migration;
payments.donation_id wajib.
Baca index yang menjaga donation flow
Di migration ada dua index penting:
sql
create unique index if not exists donations_idempotency_key_idx on public.donations (idempotency_key) where idempotency_key is not null;
sql
create index if not exists donations_lookup_token_hash_idx on public.donations (lookup_token_hash) where lookup_token_hash is not null;
Index pertama mencegah submit ganda dengan idempotency key yang sama. Index kedua membantu lookup halaman konfirmasi tanpa menyimpan token mentah sebagai query utama.
Cek index di database:
sql
select indexname, indexdeffrom pg_indexeswhere schemaname = 'public' and tablename = 'donations'order by indexname;
anon/authenticated boleh insert donation hanya status pending
donations
Donor reads own donations
authenticated baca donation miliknya
payments RLS aktif, tetapi belum ada policy publik pada migration ini. Itu berarti akses payment default tertutup. Ini bukan sesuatu yang perlu “dibetulkan” sekarang. Nanti saat payment flow dikerjakan, aksesnya harus didesain dengan sengaja.
Fungsi lookup guest
Ada fungsi:
sql
create or replace function public.get_donation_by_lookup(p_token_hash text)returns table (...)language plpgsqlsecurity definerset search_path = public
Fungsi ini penting karena donatur guest tidak selalu punya auth.uid(). Kalau confirmation page perlu membaca donasi guest, ia tidak bisa mengandalkan policy “pemilik akun”. Solusinya: lookup memakai token hash melalui fungsi yang dibatasi.
Perhatikan dua hal:
function menerima p_token_hash, bukan token mentah;
function hanya mengembalikan field yang dibutuhkan confirmation page.
create sequence if not exists public.donation_number_seq;
Lalu trigger nomor donasi:
sql
create trigger trg_donations_assign_numberbefore insert on public.donationsfor each rowwhen (new.donation_number is null)execute function public.assign_donation_number();
Artinya database bisa mengisi donation_number kalau insert tidak mengirim nomor.
Ada juga trigger status:
sql
create trigger trg_donations_check_statusbefore update on public.donationsfor each rowexecute function public.check_donation_status_transition();
Aturannya:
sql
(old.status = 'pending' and new.status in ('verified','rejected','cancelled')) or(old.status = 'verified' and new.status = 'refunded')
Jadi transisi seperti rejected → verified harus ditolak. Ini bukan sekadar aturan UI. Database ikut menjaga.
Paket Pangan untuk Keluarga | paket-pangan-keluarga | 100000000 | published
Seed ini yang membuat homepage punya campaign untuk diklik saat latihan.
Minta Antigravity membuat ringkasan schema
Sekarang boleh minta bantuan agent, tapi hanya untuk merangkum.
text
Saya ingin membuat docs/schema-catatan.md.Jangan mengubah migration dan jangan mengubah kode aplikasi.Baca supabase/migrations/20260829_vertical_slice.sql, lalu bantu saya menulis catatan schema maksimal 1 halaman yang berisi:1. empat tabel utama dan perannya,2. index penting untuk donation flow,3. RLS policy per tabel,4. fungsi get_donation_by_lookup dan kenapa dipakai untuk guest,5. trigger nomor donasi dan trigger status transition,6. seed campaign awal.Jangan menambahkan aturan yang tidak ada di migration.Tandai jika ada bagian yang perlu diverifikasi di Supabase Dashboard.
Setelah agent memberi draft, cocokkan lagi dengan query di atas. Jangan jadikan agent sebagai sumber kebenaran utama.
Tulis docs/schema-catatan.md
Isi ringkasnya bisa seperti ini:
md
# Schema Catatan — Platform Donasi Amanah## Tabel utama- campaigns: program donasi. Publik membaca yang statusnya published.- donors: profil/identitas donatur. user_id opsional.- donations: record utama donasi. Wajib campaign_id, donor_id opsional, status awal pending.- payments: attempt pembayaran untuk donation.## Index penting- donations_idempotency_key_idx: mencegah submit ganda dengan key sama.- donations_lookup_token_hash_idx: mempercepat lookup confirmation via token hash.- donations_campaign_id_idx: query donasi per campaign.- donations_status_idx: query donasi berdasarkan status.## RLS- campaigns: anon/authenticated boleh select hanya published.- donors: anon/authenticated boleh insert; authenticated baca miliknya.- donations: anon/authenticated boleh insert hanya pending; authenticated baca miliknya.- payments: RLS aktif; policy publik belum dibuka.## Guest confirmation- get_donation_by_lookup(p_token_hash) adalah security definer function.- Dipakai untuk membaca donasi guest lewat hash token, bukan auth.uid().- Return field dibatasi untuk confirmation page.## Trigger- trg_donations_assign_number: before insert, isi donation_number jika null.- trg_donations_check_status: before update, batasi transisi status.## Seed- Campaign: Paket Pangan untuk Keluarga.- Slug: paket-pangan-keluarga.- Target: 100000000.- Status: published.
Prinsip yang perlu dibawa
Migration memberi tiga jenis kebenaran:
struktur — tabel, kolom, tipe, relasi;
aturan — CHECK, RLS, trigger, function;
data awal — seed yang dipakai untuk latihan.
Kalau nanti AI mengusulkan perubahan yang bertentangan dengan migration, kamu punya dasar untuk menolak atau meminta revisi. Bukan karena kamu “lebih tahu semua SQL”, tapi karena kamu sudah membaca bukti.
Checkpoint
Migration dijalankan di project Supabase yang benar.
Empat tabel utama terlihat di database.
RLS aktif untuk campaigns, donors, donations, dan payments.
Kamu bisa menjelaskan fungsi get_donation_by_lookup.
Kamu bisa menjelaskan dua trigger pada donations.
Seed paket-pangan-keluarga ada dan statusnya published.
docs/schema-catatan.md selesai.
Selesai bagian database awal. Kalau tadi sempat terasa berat karena banyak SQL, wajar kok. Yang penting kamu sudah melihat sendiri bahwa donation flow ini bukan cuma form: ada RLS, lookup token, idempotency index, dan trigger status yang akan jadi pegangan saat agent mulai membangun fitur berikutnya.
Checkpoint KuisTarget: 70%
Kuis 02.2 — Jalankan Migration & Pahami Seed
Kuis ini wajib untuk sertifikat. Kamu tetap bisa lanjut ke pelajaran berikutnya dan mengerjakannya nanti.