Skip to content

Batas Aman Migrasi: Tes Roundtrip Berhenti di Checkpoint 56

Adityo Guni Waluyo

Tes roundtrip migrasi tidak turun ke nol: rantai down patah di tengah karena ENUM hilang. Checkpoint 56 menjadi batas aman yang terkunci tes.

Ringkasan

Jadi migrasi turun gak bisa sampai nol, mentok di versi 56 karena file turun 51 butuh nilai INFORMASI yang cuma ada dari migrasi 45. Buat itu tes roundtrip dikunci buat ngecek skema balik utuh di checkpoint itu. Sekalian tes devauth mastiin rute login dev hilang, 404, kecuali env development beneran.

Saat menjalankan paket tes integrasi terhadap instans basis data MySQL 5.7 pada port 3307, eksekusi suite migrasi TestMigrations_FullRoundtrip tidak turun hingga versi nol. Alih-alih mengembalikan skema ke kondisi awal yang kosong, proses migrasi turun berhenti secara adaptif pada checkpoint 56, lalu naik kembali ke versi terkini untuk memverifikasi integritas [1].

Asumsi awal yang umum dalam pengembangan perangkat lunak adalah bahwa migrasi basis data harus sepenuhnya reversibel. Format resmi golang-migrate memang mewajibkan setiap versi berpasangan dua arah: satu berkas naik dan satu berkas turun per versi, dijalankan naik pada urutan versi menaik dan turun pada urutan menurun [1]. Dari kontrak berpasangan itu gampang lari ke asumsi yang lebih besar: pasangan up/down per versi berarti seluruh rantai bisa dibongkar sampai versi 0. Tes roundtrip pun semestinya menguji penurunan penuh.

Kenyataan di lapangan menunjukkan pola yang berbeda. Rantai penurunan pada repositori KotaPortal mengalami kegagalan di tengah jalan jika dipaksa turun di bawah versi 56. Penyebab teknisnya terletak pada ketergantungan lintas migrasi antara versi 45 dan 51. Migrasi versi 45 arah atas memperkenalkan nilai INFORMASI ke dalam tipe data ENUM pada kolom modul. Sementara itu, berkas turun versi 51 mencoba menyisipkan baris kategori dengan nilai module INFORMASI tersebut. Urutan eksekusi rantai turun adalah menurun: 52, lalu 51, lalu 50, dan seterusnya. Nilai INFORMASI baru dihapus pada berkas turun versi 45, tetapi penyisipan pada berkas turun versi 51 berjalan jauh lebih dulu dalam urutan menurun itu, pada rentang ketika sah tidaknya nilai itu sudah tidak dijamin. Penyisipan baris yang keberadaannya bergantung pada migrasi lain itulah yang patah, dan migrate berhenti dengan keadaan gagal di tengah rantai. Oleh karena itu, versi 56 ditetapkan sebagai titik pemeriksaan terdalam yang aman [1].

Reversibilitas bukanlah properti absolut dari seluruh rantai migrasi, melainkan properti dari sebuah jendela versi tertentu. Mengunci perilaku ini melalui tes yang gagal jika dipaksa turun di bawah versi 56 mengubah pengetahuan tribal yang biasanya tersembunyi dalam komentar berkas migrasi arah turun menjadi invarian yang dapat dieksekusi. Fungsi TestMigrations_FullRoundtrip dalam migrations_test.go tidak hanya memverifikasi bahwa versi akhir tidak kotor, tetapi juga melakukan pemeriksaan titik terhadap 8 tabel dan 12 kolom kunci lewat informasi skema bawaan database setelah kembali ke versi puncak [1].

Penjaga Keamanan Rute Dev-Auth

Selain integritas skema, tes ini juga mengunci invarian keamanan pada lapisan perutean. Berkas devauth_test.go memperkenalkan fungsi TestDevAuthRouteAbsence yang memverifikasi perilaku rute login khusus developer. Dalam lingkungan produksi atau staging, rute ini tidak boleh terdaftar sama sekali. Tes mengonfirmasi bahwa permintaan ke rute tersebut dijawab 404 untuk setiap nilai APP_ENV selain string development yang persis sama. Bahkan nilai "DEVELOPMENT" dalam huruf kapital akan ditolak dan menghasilkan 404 [4].

Hanya dalam lingkungan "development" yang tepat, rute ini akan merespons dengan 405 Method Not Allowed jika metode HTTP yang digunakan tidak sesuai, yang menandakan bahwa rute tersebut memang ada tetapi dibatasi [4]. Respons 404 dipilih alih-alih 503 Service Unavailable yang menandakan ketidakmampuan sementara server, karena ketiadaan rute adalah kondisi permanen yang disengaja [2]. Pendekatan ini selaras dengan prinsip penanganan kesalahan yang menyarankan respons generik kepada pengguna saat terjadi kondisi tidak terduga, sambil mencatat detailnya di sisi server [3].

Implikasi terhadap Siklus Pengembangan

Keputusan untuk tidak memaksakan migrasi turun hingga nol mencerminkan pragmatisme teknis. Memastikan bahwa skema dapat kembali ke jendela versi yang aman memberikan jaminan yang jauh lebih bernilai daripada janji reversibilitas penuh yang rapuh. Ketika tim perlu menurunkan versi basis data untuk tujuan pemulihan atau pengujian, mereka memiliki batas aman yang teruji. Memaksakan penurunan hingga nol berarti menulis ulang dependensi lintas migrasi 45 dan 51 terlebih dahulu, pekerjaan yang berisiko justru ketika dilakukan dalam mode darurat pemulihan. Checkpoint yang diuji memberi sesuatu yang lebih berguna: jendela versi yang dijamin bisa diputar naik-turun, lengkap dengan spot-check terhadap tabel dan kolom kunci.

Verifikasi Otomatis sebagai Dokumentasi Hidup

Dengan menempatkan batasan ini langsung di dalam kode tes, dokumentasi teknis menjadi hidup dan diverifikasi secara otomatis pada setiap siklus integrasi. Komentar "characterization: current behavior, owner decision pending" dalam kode sumber menandakan bahwa ini adalah keputusan arsitektur yang disadari. Kombinasi antara pemeriksaan information_schema dan penjaga rute chi yang kompatibel dengan net/http standar memastikan bahwa baik lapisan data maupun lapisan aplikasi mempertahankan kontrak keamanannya [4].

Sumber

  1. Dokumentasi format berkas migrasi golang-migrate
  2. RFC 9110: HTTP Semantics
  3. OWASP Error Handling Cheat Sheet
  4. Router chi untuk Go

Artikel terkait