engineering docs

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

  1. Ambil actor dari session/trusted proxy, bukan input browser.
  2. Tenant-scope resource berdasarkan Organization owner dan permission actor.
  3. Validasi resource reference di database pemiliknya.
  4. Tulis record pada database domain.
  5. Untuk dampak lintas domain, tulis outbox lokal idempoten dan gunakan projection/inbox; jangan memakai join/transaksi Prisma lintas database.
  6. 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.