Deskripsi Kontrak API yang Menyesatkan
Field jenis dilabel pilar dan admin_note diklaim diabaikan: dua deskripsi kontrak API yang salah, plus respons 400 yang belum terdokumentasi.
Ringkasan
Gue nemu deskripsi spec yang gue tulis sendiri ternyata ngaco dan bikin misleading banget. Field jenis kek campur sama pilar, admin_note katanya diabaikan buat Pengajuan padahal wajib terus minimal lima karakter, plus endpoint history belum ndokumentasiin 400. Akhirnya cuma benerin teks doang tapi JSDoc ke-update otomatis jadi pelajaran buat nge-review deskripsi seserius kode.
Waktu final review spec layanan, mata saya berhenti di satu baris yang saya tulis sendiri: deskripsi field jenis berbunyi "pilar layanan pengaju (read-only)". Dua konsep di satu kalimat itu beda hal. jenis itu jenis aplikasi yang ditentukan sistem (pendaftaran, pengaduan, atau penyewaan) dan read-only. Pilar? Itu bidang pengajunya, sumbu lain yang nggak ada hubungannya dengan field ini. Deskripsi lama menyatukan dua hal yang beda seolah satu, dan yang nulis saya sendiri.
Ternyata bukan cuma satu. Di schema request transisi status, deskripsi admin_note lama berbunyi: wajib untuk Diproses, Disetujui, atau Ditolak, diabaikan untuk Pengajuan. Klaim "diabaikan" itu nggak pernah benar. Tidak ada satu pun transisi yang menuju status pengajuan, jadi syarat yang sebenarnya jauh lebih sederhana: catatan wajib untuk setiap transisi status, minimal lima karakter. Kontrak yang saya dokumentasikan sendiri membebankan aturan yang nggak exist ke satu status, sambil menyembunyikan syarat yang beneran berlaku di semua status lain.
Yang bikin error ini awet: kalimatnya terdengar masuk akal. Pembaca yang buru-buru bakal nelan klaim "diabaikan untuk Pengajuan" tanpa verifikasi, karena bentuknya spesifik, lengkap dengan pengecualian yang jelas. Dokumentasi yang bolong bikin orang mencari di tempat lain; dokumentasi yang salah bikin orang yakin pada hal yang keliru. Yang kedua jauh lebih mahal darinya.
Pembaca Baru Nggak Punya Konteks
Saya sempat anggap ini kosmetik. Toh skemanya benar, enum-nya benar, yang salah cuma kata-kata. Tapi coba ikuti alur konsumen baru yang mau integrasi. OpenAPI memang dirancang supaya manusia dan mesin bisa memahami kemampuan sebuah API tanpa menyentuh source code [4]. Deskripsi adalah satu-satunya penjelasan yang mereka punya. Konsumen yang baca "diabaikan untuk Pengajuan" akan menulis kode yang nggak mengirim catatan untuk kasus itu, lalu bingung kenapa request-nya ditolak. Konsumen yang baca jenis sebagai pilar akan menampilkan klasifikasi yang salah ke pengguna. Dokumen yang bolong masih bikin pembaca curiga; dokumen yang bohong justru dipercaya.
Lalu ada lubang ketiga. Endpoint history untuk satu pengajuan ternyata bisa membalas 400 kalau id di path rusak, dan respons itu belum ada di spec. Artinya 400 Bad Request, yaitu server menolak memproses request karena menganggap ada kesalahan dari sisi klien [2], tidak pernah didokumentasikan untuk endpoint ini. Konsumen yang rajin bakal kejadian sendiri, dan yang nge-handle error per endpoint nggak punya dasar untuk menangkap kasus ini secara eksplisit.
Teks di Kontrak Itu Turunan Kode
Perbaikannya cuma teks: dua deskripsi diluruskan, satu respons 400 ditambahkan. Tapi dampaknya nggak berhenti di halaman docs. Tipe frontend saya generate dari spec memakai openapi-typescript, dan deskripsi di spec ikut tersalin menjadi JSDoc di tipe hasil generate [3]. Setelah regen, JSDoc di v1.d.ts ikut berubah jadi versi yang benar, lengkap dengan varian 400 baru di tipe operasi history. Setiap orang yang hover nama field di editor berikutnya membaca kebenaran, bukan warisan kalimat saya yang salah. Untuk 400-nya sendiri, spec kini nyatakan bentuk responsnya secara eksplisit: objek error dengan kode BAD_REQUEST, konvensi yang sama dengan endpoint lain yang sudah mendokumentasikan kegagalan validasinya.
Yang Saya Waspadai Selanjutnya
Tiga kebiasaan yang saya tanam dari insiden kecil ini. Pertama, review deskripsi spec dengan serius seperti review kode, karena deskripsi ikut ter-ship ke codebase lewat generator. Kedua, respons error itu bagian dari kontrak: setiap kelakuan aneh handler yang bisa dibalas ke klien, semacam id rusak yang berakhir sebagai 400 [2], punya tempatnya di spec. Ketiga, kalau ada klaim di deskripsi yang menyebut pengecualian ("diabaikan untuk X"), itu tanda bahaya. Pengecualian harus bisa ditelusuri ke transisi yang beneran ada, dan kalau nggak ada, deskripsinya yang salah. Ujiannya murah: baca ulang deskripsi satu field, tanyakan "kalimat ini masih benar kalau handler-nya berubah?" Semua yang tidak bisa dijawab dengan ya tanpa membuka kode berarti deskripsi yang nggak layak jadi kontrak.