Jejak Audit Fail-Safe & Smoke Test E2E
Pencatatan riwayat aktivitas append-only yang tahan gagal serta pengujian otomatis dari ujung ke ujung menggunakan Playwright.
Membaca sekitar 2 menit
Pencatatan riwayat aktivitas append-only yang tahan gagal serta pengujian otomatis dari ujung ke ujung menggunakan Playwright.
Setiap mutasi memanggil recordAudit yang aman dari kegagalan tulis, dan skrip npm run smoke menguji alur login, MFA, navigasi, hingga CRUD dengan rollback otomatis.
Log audit tidak boleh menggagalkan transaksi bisnis utama, dan pengujian smoke otomatis memastikan perubahan kode tidak pernah diam-diam merusak alur krusial.
Masalahnya dulu
Pada sistem administrasi multi-pengguna, pertanyaan 'Siapa yang menghapus data ini kemarin malam?' pasti akan muncul. Kita membutuhkan tabel jejak audit (audit_logs) yang merekam setiap aksi sensitif. Namun ada risiko tersembunyi: bagaimana jika pencatatan audit mengalami error karena teks detail terlalu panjang? Selain itu, seiring bertambahnya modul, bagaimana kita memastikan perubahan kecil di lapisan auth tidak diam-diam merusak halaman login atau mutasi data?
Audit non-blocking dan pengujian otomatis Playwright
Di common/lib/audit.ts, fungsi recordAudit dirancang dengan prinsip fail-safe: seluruh string dipotong otomatis sesuai batas kolom VARCHAR database menggunakan .slice(), dan operasi insert dibungkus dalam try/catch mandiri agar kegagalan tulis log tidak pernah membatalkan transaksi bisnis yang sudah berhasil. Untuk menjaga kualitas rilis, saya menulis skrip scripts/smoke.mjs (npm run smoke) menggunakan Playwright yang secara otomatis menyalakan server produksi, menguji rute publik, mencoba login sebagai Super Admin (termasuk melewati tantangan TOTP MFA jika aktif), menelusuri semua menu dashboard, hingga melakukan mutasi tambah-ubah-hapus data dengan rollback otomatis.
Pencatatan log tidak boleh menjatuhkan transaksi bisnis utama, dan kualitas rilis tidak boleh hanya bergantung pada ingatan manual sebelum deploy.
Implementasi di ngodingan ini
Berikut adalah implementasi pencatatan audit tahan-gagal di common/lib/audit.ts:
// common/lib/audit.ts
export async function recordAudit({
actor,
action,
targetType,
targetUuid,
detail,
ip,
}: AuditEvent) {
try {
await prisma.auditLog.create({
data: {
actorUuid: actor?.userUuid ?? null,
actorName: actor?.name?.slice(0, 100) ?? null,
actorEmail: actor?.email?.slice(0, 191) ?? null,
action: action.slice(0, 60),
targetType: targetType?.slice(0, 50) ?? null,
targetUuid: targetUuid?.slice(0, 64) ?? null,
detail: detail?.slice(0, 1000) ?? null,
ip: ip?.slice(0, 64) ?? null,
},
});
} catch (e) {
console.error("[audit]", e);
}
}Jebakan dan detail yang harus dijaga
- Tabel audit bersifat append-only: Modul audit-log di dashboard hanya memiliki queries dan tabel tampilan baca-saja (read-only); tidak ada Server Action untuk mengedit atau menghapus baris audit log.
- Jangan pernah mencatat rahasia di kolom detail: Password, token sesi, maupun secret MFA pantang dimasukkan ke parameter detail saat memanggil recordAudit.
- Smoke test cerdas yang mampu menghitung TOTP secara mandiri: Di scripts/smoke.mjs, jika akun uji Super Admin memiliki MFA aktif, skrip pengujian mampu mendekripsi mfa_secret dari database uji dan menghitung kode TOTP 6 digit secara real-time untuk menyelesaikan alur login E2E.