08 — Proyek Capstone: Membangun API Toko dari Nol dengan AI¶
Bab ini menyatukan semua yang dipelajari (API + Database + Docker + Security) menjadi satu proyek nyata, dikerjakan sepenuhnya lewat AI dengan disiplin review. Tujuannya bukan menghafal kode — tapi mengalami loop kerja lengkap yang menghasilkan output berkualitas.
Yang dibangun: API mini toko online — produk, keranjang, checkout dengan pengurangan stok, dan riwayat order. Cukup kecil untuk selesai dalam beberapa sesi, cukup lengkap untuk menyentuh setiap topik.
Estimasi: 3–5 sesi. Kerjakan bertahap; jangan generate semua sekaligus.
📌 Framework di contoh memakai Laravel + PostgreSQL, tapi polanya berlaku untuk stack apa pun. Ganti detail sesuai tumpukan Anda saat memberi prompt.
Fase 0 — Spesifikasi (jangan lewati!)¶
Kualitas output vibe coding ditentukan di sini, bukan saat generate. Tulis dokumen singkat ini dulu:
PROYEK: API Toko Mini
ENTITAS & ATURAN BISNIS:
- Product: punya nama, harga, stok. Harga & stok bisa berubah.
- Cart: satu cart aktif per user. Berisi banyak item.
- CartItem: product + quantity.
- Order: dibuat dari cart saat checkout. Menyimpan total & status.
- OrderItem: SALINAN product+harga+qty saat checkout (harga tidak boleh berubah kemudian).
ATURAN KRITIS:
1. Checkout mengurangi stok. Stok tidak boleh minus (anti-overselling).
2. Checkout = transaction: buat order + order_items + kurangi stok, semua-atau-batal.
3. User hanya mengakses cart & order MILIKNYA (anti-IDOR).
4. Harga di order_items disalin saat checkout (price_at_time).
ENDPOINT:
GET /v1/products publik 200
GET /v1/products/{id} publik 200 | 404
GET /v1/cart auth 200
POST /v1/cart/items auth 201 | 422
DELETE /v1/cart/items/{product_id} auth 204 | 404
POST /v1/checkout auth 201 | 422(stok kurang/cart kosong)
GET /v1/orders auth 200 (hanya milik user)
GET /v1/orders/{id} auth 200 | 404 (hanya milik user)
Simpan ini sebagai docs/spec.md. Ini kontrak yang akan Anda pegang di setiap review.
Fase 1 — Fondasi Docker¶
Bangun environment sebelum kode, supaya "jalan di laptop saya" tidak pernah jadi masalah.
💡 Prompt: "Buatkan docker-compose.yml untuk proyek Laravel 11 + PostgreSQL 16 + Redis 7. Syarat (wajib semua): data Postgres di named volume; semua credential lewat .env dengan .env.example yang nilainya kosong; healthcheck untuk Postgres; service app menunggu Postgres sehat; versi image spesifik (bukan latest); sertakan .dockerignore yang mengabaikan .env, node_modules, vendor, .git. Jangan hardcode password di mana pun."
Gate review sebelum lanjut (dari checklist §Docker):
- [ ] Tidak ada password hardcoded — cari manual di semua file
- [ ] .env ada di .gitignore DAN .dockerignore
- [ ] Postgres pakai volume + healthcheck
- [ ] Image pakai versi spesifik
Jalankan docker compose up -d sampai semua service healthy. Baru lanjut.
Fase 2 — Skema Database¶
Desain data dulu — ini menentukan segalanya.
💡 Prompt (desain): "Berdasarkan spec ini [tempel Fase 0], buatkan ERD Mermaid dan jelaskan tiap relasi & keputusan penting. JANGAN tulis kode dulu — saya mau review desainnya. Perhatikan khusus: bagaimana order_items menyalin harga, dan bagaimana mencegah stok minus."
Review ERD terhadap spec. Tantang balik: "Bagaimana kalau produk dihapus setelah masuk order lama? Apakah order_items masih menyimpan namanya?" (Jawaban benar: order_items harus menyimpan salinan nama+harga, tidak sekadar FK ke products.)
💡 Prompt (migration): "Setuju dengan ERD. Buat migration Laravel untuk semua tabel. Wajib: harga DECIMAL(15,2); FK + index; order_items menyimpan product_name & price_at_time (salinan); constraint stock >= 0; timestamps; soft delete untuk products; rollback lengkap."
Gate review (dari checklist §Database):
- [ ] Harga DECIMAL, bukan float
- [ ] order_items punya salinan harga & nama — bukan cuma product_id
- [ ] Constraint stock >= 0 ada di level DB
- [ ] Semua FK ter-index
- [ ] Migration punya rollback
Jalankan migration. Buat seeder berisi 5 produk contoh.
Fase 3 — Endpoint Baca (paling aman dulu)¶
Mulai dari yang tidak mengubah data — risiko rendah, membangun momentum.
💡 Prompt: "Implementasikan
GET /v1/products(dengan pagination 20/halaman + filter opsional?search=) danGET /v1/products/{id}(404 bila tidak ada). Response format konsisten: bungkus dalamdata, sertakanmetauntuk pagination, harga sebagai integer/desimal konsisten, timestamps ISO 8601. Terapkan praktik: escape output, tidak ada N+1."
Gate review (§API + §Database):
- [ ] GET benar-benar read-only
- [ ] Pagination ada (tidak mengembalikan seluruh tabel)
- [ ] 404 untuk produk tidak ada — cek dengan curl
- [ ] Tidak ada N+1 (tanya AI: "berapa query yang dijalankan endpoint ini?")
Tes dengan tabel (Langkah 3 di tutorial §2.14).
Fase 4 — Endpoint Cart (mulai ada auth & kepemilikan)¶
Sekarang masuk wilayah yang butuh autentikasi + otorisasi.
💡 Prompt: "Implementasikan auth Bearer (Laravel Sanctum) dan endpoint cart:
GET /v1/cart,POST /v1/cart/items({product_id exists, quantity min 1}),DELETE /v1/cart/items/{product_id}. WAJIB: user hanya mengakses cart miliknya sendiri (cek kepemilikan eksplisit, bukan hanya cek login); validasi lewat FormRequest; duplikat item menambah quantity, bukan baris baru; response 201/204/422/404 sesuai spec."
Gate review (§Security — ini titik rawan!):
- [ ] Setiap endpoint cek kepemilikan, bukan cuma login (anti-IDOR)
- [ ] Uji manual: login user A, coba hapus item cart user B → harus gagal
- [ ] Validasi di server (FormRequest), bukan cuma frontend
- [ ] product_id divalidasi exists
Fase 5 — Checkout (puncak: transaction + race condition)¶
Endpoint paling kritis — menyentuh uang, stok, dan konsistensi. Perlakukan sebagai risiko 🔴.
💡 Prompt: "Implementasikan
POST /v1/checkout. Alur: ambil cart user login → validasi tidak kosong → untuk tiap item cek & kurangi stok secara ATOMIC (aman dari race condition, tidak boleh oversell) → buat order + order_items (salin nama & harga produk saat ini) → hitung total → kosongkan cart. SEMUA dalam satu database transaction (batal total bila ada langkah gagal). Response: 201 + order; 422 bila cart kosong atau stok kurang (sebut produk mana). Jelaskan mekanisme anti-race-condition yang kamu pakai."
Gate review — paling ketat (§Database §3.8 + §Security):
- [ ] Seluruh operasi dibungkus transaction (cari DB::transaction / BEGIN)
- [ ] Pengurangan stok atomic (WHERE stock >= qty lalu cek baris terpengaruh, atau lock) — bukan baca-lalu-tulis terpisah
- [ ] Harga & nama disalin ke order_items
- [ ] Cart kosong → 422, bukan order Rp0
- [ ] Kepemilikan cart dicek
Tes race condition (penting!): minta AI menulis skrip yang mengirim 5 request checkout bersamaan untuk produk berstok 3. Hasil benar: 3 sukses, 2 gagal 422, stok akhir = 0 (bukan negatif). Kalau stok jadi negatif → mekanisme atomic-nya salah, kembali ke prompt.
Fase 6 — Endpoint Order & Finalisasi¶
💡 Prompt: "Implementasikan
GET /v1/ordersdanGET /v1/orders/{id}— hanya menampilkan order milik user login (anti-IDOR), dengan order_items-nya (tanpa N+1). Lalu buatkan spesifikasi OpenAPI 3.0 untuk SELURUH API ini."
Gate review akhir — jalankan checklist bab 06 secara penuh di seluruh proyek, plus:
💡 Prompt audit menyeluruh: "Audit SELURUH codebase proyek ini sebagai senior + security engineer. Cek terhadap daftar ini: [tempel checklist bab 06]. Untuk tiap file, laporkan temuan format [severity — file:baris — masalah — perbaikan]. Nyatakan eksplisit kategori yang bersih. Jangan mengarang temuan."
Definition of Done — Kapan Proyek "Selesai"¶
Output vibe coding disebut berkualitas kalau semua ini terpenuhi:
Fungsional - [ ] Semua 8 endpoint jalan sesuai spec Fase 0 - [ ] Setiap endpoint lulus tabel tes (happy path + edge case) - [ ] Checkout lulus tes race condition (stok tak pernah negatif)
Kualitas kode - [ ] Tidak ada N+1 di endpoint list - [ ] Operasi multi-tabel pakai transaction - [ ] Format response konsisten di semua endpoint
Keamanan
- [ ] Setiap endpoint auth mengecek kepemilikan data (uji silang antar user)
- [ ] Tidak ada secret hardcoded; .env ter-gitignore
- [ ] Validasi server-side di semua input
- [ ] Password (bila ada register) di-hash bcrypt/argon2
Infrastruktur
- [ ] docker compose up -d menjalankan seluruh stack dari nol
- [ ] Data Postgres selamat setelah docker compose down lalu up (volume benar)
- [ ] Migration bisa dijalankan di environment kosong
Dokumentasi
- [ ] docs/spec.md dan spesifikasi OpenAPI tersedia
- [ ] Setiap fitur punya catatan tes
Kalau ada satu saja yang belum ✅ — proyek belum selesai, terlepas dari "sudah kelihatan jalan".
Yang Baru Saja Anda Latih¶
Bukan sekadar membuat API. Anda melatih loop kerja yang membedakan vibe coding amatir dari profesional:
Spesifikasi jelas → prompt presisi → generate → review dengan checklist →
tes edge case → revisi berbukti → gate sebelum lanjut → definition of done
Loop inilah produk sebenarnya dari seluruh materi ini. Framework berganti, bahasa berganti, model AI berganti — loop ini tetap.