Buku Catatan Aktivitas yang Tidak Bisa Dihapus
Merekam secara rapi siapa yang membuat, mengedit, atau menghapus data, sehingga riwayat kegiatan selalu dapat diperiksa saat terjadi kendala.
Merekam secara rapi siapa yang membuat, mengedit, atau menghapus data, sehingga riwayat kegiatan selalu dapat diperiksa saat terjadi kendala.
Tantangan & Kebutuhan Pengguna
Ketika terjadi perubahan hak akses yang mencurigakan atau penghapusan data penting, administrator membutuhkan bukti forensik yang menjawab siapa pelakunya, kapan dilakukan, dari alamat IP mana, dan objek apa yang diubah. Namun, jika tabel audit hanya menyimpan foreign key ke `user_uuid`, riwayat log akan kehilangan konteks ketika akun pelaku tersebut kelak dihapus atau diganti namanya. Selain itu, kesalahan kecil pada pencatatan log tidak boleh sampai membatalkan transaksi bisnis utama yang sudah berhasil.
Log audit harus bersifat abadi (append-only), menyimpan potret identitas aktor pada detik kejadian, dan tidak pernah boleh membocorkan kredensial atau menggagalkan operasi utama.
Solusi & Cara Kerja
Tabel `audit_logs` dirancang tanpa relasi foreign key yang mengikat ke tabel `users`, melainkan menyimpan salinan denormalisasi `actorUuid`, `actorName`, dan `actorEmail` tepat saat peristiwa terjadi. Di tingkat aplikasi maupun skema RBAC, fitur `audit` hanya memiliki `availableActions: ['read']`—tidak ada service, Server Action, ataupun tombol UI untuk mengubah atau menghapus baris audit. Fungsi `recordAudit()` di `common/lib/audit.ts` memotong panjang string secara defensif sesuai batas kolom `VarChar` database dan membungkus penulisan di dalam blok `try/catch` terisolasi.
Berikut adalah implementasi asli pencatat audit non-blocking dengan pemotongan panjang karakter aman di dalam `common/lib/audit.ts`:
Detail & Hal yang Diperhatikan
- Defensive String Truncation: Sebelum dikirim ke Prisma, setiap field dipotong menggunakan `.slice(0, maxLen)` agar rincian perubahan yang panjang tidak pernah melempar error `Value too long for column type character varying` dari PostgreSQL.
- Sanitasi Data Sensitif: Seluruh pemanggil `recordAudit` hanya mencatat metadata perubahan (seperti nama role, email target, atau jumlah izin yang diubah) dan dilarang keras memasukkan password, token JWT, maupun secret MFA ke dalam kolom `detail`.
- Indeks Komposit untuk Pencarian Cepat: Tabel `audit_logs` dilengkapi tiga indeks (`[actorUuid, createdAt]`, `[action, createdAt]`, dan `[createdAt]`) agar pencarian dan paginasi ribuan log lewat `/api/audit-logs` tetap instan.