← Kembali ke wawasan

Software Engineering

Cara Merancang API untuk Traceability dan Auditability

LinkedIn X

API yang berperilaku benar untuk pemanggil yang dituju tetap bisa nyaris mustahil diaudit enam bulan kemudian, dan kedua properti itu hampir tidak berkaitan satu sama lain. Kebenaran diukur terhadap spesifikasi saat build. Auditability diukur terhadap pertanyaan yang belum diajukan siapa pun — siapa yang melakukan ini, atas nama siapa, dan apa yang berubah sebagai akibatnya — dan pada saat pertanyaan itu akhirnya diajukan, sudah terlambat untuk menambahkan jawabannya secara retroaktif.

Saya pernah membangun API untuk backend fintech dan untuk sistem informasi rumah sakit, dua lingkungan tempat pertanyaan itu sering diajukan dan jawabannya penting segera — sebuah transaksi yang disengketakan, sebuah rekam medis yang diakses di luar alur kerja biasa seorang klinisi. Keduanya mengajarkan pelajaran yang sama dari sudut berbeda: traceability harus menjadi properti dari desain API, bukan fitur yang ditempelkan pada loggingnya belakangan.

Tulisan ini membahas pola konkret yang saya andalkan untuk merancang API yang perilakunya bisa direkonstruksi di kemudian hari, tanpa perlu bergantung pada ingatan siapa pun tentang cara sistem biasanya berperilaku.

Catat aktor dan principal-nya, bukan hanya request-nya

Request log yang hanya mencatat bahwa sebuah endpoint dipanggil menjawab pertanyaan paling tidak berguna yang pernah diajukan sebuah audit. Pola yang layak dirancang sejak awal adalah mencatat siapa yang membuat panggilan itu, dan secara terpisah, atas nama siapa — seorang support agent bertindak untuk pelanggan, sebuah service account bertindak untuk job terjadwal, seorang admin melakukan impersonation ke pengguna untuk debug sebuah masalah. Itu adalah aktor-aktor berbeda dengan akuntabilitas berbeda, dan menggabungkannya menjadi satu field identifier pengguna di log adalah keputusan yang akan Anda sesali pertama kali seseorang bertanya yang mana sebenarnya yang terjadi.

Beri setiap request sebuah correlation identifier dan pertahankan

Satu aksi pengguna jarang tetap berada di dalam satu panggilan API saja. Ia bercabang ke layanan hilir, job yang di-queue, dan efek samping asinkron, dan jika tidak satu pun darinya berbagi identifier yang sama, merekonstruksi seluruh urutan kejadian berarti mengorelasikan timestamp dan berharap tidak ada hal lain yang terjadi pada momen yang sama. Correlation identifier yang dibuat di tepi sistem dan dialirkan melalui setiap panggilan hilir, baris log, dan event mengubah harapan itu menjadi sebuah query. Ini adalah investasi traceability paling murah yang bisa dibuat sebuah API, dan yang paling sering dilewatkan karena tidak memengaruhi kebenaran — hanya auditability, yang tidak disadari siapa pun hilang sampai mereka membutuhkannya.

Catat apa yang berubah, bukan hanya bahwa sesuatu berubah

"Record updated" adalah baris log yang tidak memuaskan apa pun ketika seseorang kemudian bertanya apa yang sebenarnya berubah. API yang auditable mencatat before-and-after yang bermakna — field mana yang berubah, bukan seluruh rekamannya, karena membandingkan seluruh rekaman berbulan-bulan kemudian terhadap perubahan yang tidak terkait menjadi investigasi tersendiri. Ini paling penting justru di tempat yang paling menggoda untuk dilewatkan: endpoint administratif dan bulk-update, yang menyentuh banyak rekaman sekaligus dan, bukan kebetulan, yang paling mungkin ditanyakan sebuah audit.

Perlakukan request yang ditolak dan error juga sebagai event yang auditable

Request yang gagal otorisasi atau validasi sering justru menjadi event yang lebih menarik bagi sebuah audit dibanding yang berhasil — ia adalah bukti tentang apa yang dicoba, bukan hanya apa yang diizinkan. API yang hanya mencatat perubahan state yang berhasil memiliki blind spot persis di tempat yang paling dibutuhkan visibilitasnya oleh sebuah review insiden: percobaan akses yang benar ditolak, request cacat yang mengindikasikan bug klien atau penyerang yang sedang menjajaki. Beri versi pada alasan kegagalan sebagaimana Anda memberi versi pada API itu sendiri, sehingga sebuah penolakan yang tercatat setahun lalu masih berarti sama seperti saat ditulis.

Buat jejaknya append-only dan hubungkan dengan sistem lainnya

Semua di atas tidak berarti apa-apa jika log itu sendiri bisa diam-diam diedit belakangan — audit trail yang bisa diedit adalah klaim, bukan bukti. Menulis ke penyimpanan append-only, membatasi siapa yang boleh menulis ke sana, dan memperlakukannya dengan ekspektasi integritas yang sama seperti data yang dideskripsikannya mengubah log API menjadi sesuatu yang benar-benar bisa diandalkan sebuah audit. Ini disiplin yang sama yang membuat keputusan sebuah fitur bertenaga AI bisa direkonstruksi berbulan-bulan kemudian — mekanismenya berbeda, tetapi kebutuhannya identik: sebuah rekaman yang permanen, terstruktur, tamper-evident tentang siapa melakukan apa, dan mengapa, yang tidak bergantung pada ingatan siapa pun.

Tidak satu pun dari pola-pola ini eksotis, dan itu disengaja — API yang dirancang untuk auditability sejak awal terlihat hampir sama seperti API yang dirancang dengan baik, dengan beberapa field tambahan dan satu identifier konsisten yang dialirkan melaluinya. Biaya menambahkannya belakangan adalah yang membuatnya layak diputuskan sejak dini: menambal traceability ke dalam API yang sudah production berarti meminta sistem mengingat hal-hal yang tidak pernah dirancang untuk disimpannya, dan ia tidak pernah benar-benar bisa.

Terbuka untuk diskusi seputar pengembangan produk yang aman, applied AI, dan compliance engineering.