CRUD yang benar
CRUD bukan sekadar meneruskan fetch. Setiap operasi harus melewati route API, validasi schema, autentikasi, ownership check, dan service database.
Read
Gunakan HTTP client/proxy yang disediakan aplikasi. Container mem-parse payload unknown
dengan schema Zod sebelum dirender; jangan memasukkan API secret atau database client ke
browser bundle.
Scope organisasi berasal dari session, bukan hanya input URL. API harus menolak ID yang tidak dimiliki user.
Create
await apiFetch('/api/organization', {
method: 'POST',
body: { name, email, category: 'retail' },
headers: { Authorization: `Bearer ${token}` }
});Validasi required fields, enum, format email, dan duplicate key berada di server. Client validation hanya untuk feedback cepat.
Update dan delete
await apiFetch(`/api/organization/${organizationId}`, {
method: 'PATCH',
body: { displayName },
headers: { Authorization: `Bearer ${token}` }
});
await apiFetch(`/api/organization/${organizationId}`, {
method: 'DELETE',
headers: { Authorization: `Bearer ${token}` }
});Gunakan PATCH untuk perubahan parsial. Jangan menghapus record lintas database tanpa cascade policy yang jelas. Untuk resource turunan, validasi parent dan ownership dalam transaksi/service yang sama.
Aturan lintas database
- Ambil actor dari session/trusted proxy, bukan input browser.
- Tenant-scope resource berdasarkan Organization owner dan permission actor.
- Validasi resource reference di database pemiliknya.
- Tulis record pada database domain.
- Untuk dampak lintas domain, tulis outbox lokal idempoten dan gunakan projection/inbox; jangan memakai join/transaksi Prisma lintas database.
- Kembalikan response yang tidak mengekspos credential atau internal stack.
Jangan melakukan write langsung dari server component ke Prisma client database lain; panggil service/API boundary yang memiliki aturan tersebut.