Draft, Publish, Unpublish, Delete:
Empat State yang Harus Diuji Terpisah.
Satu tombol status tidak cukup menjelaskan apa yang dilihat penulis, origin, CDN, dan pembaca publik. Setiap transisi memerlukan authoritative readback.
Seluruh nama layanan, domain, rute, identifier, dan artefak pengujian telah dihapus. Objek disposable dibuat dan dibersihkan oleh peneliti.
Fitur publikasi tampak sederhana: tulis, terbitkan, lalu hapus. Di belakangnya ada beberapa state yang berjalan melalui database, worker, origin, cache, dan browser. Bug lifecycle sering muncul bukan karena satu state salah, melainkan karena dua komponen tidak sepakat tentang state mana yang berlaku.
State publikasi bukan boolean
Draft berarti konten dapat diedit tetapi belum boleh dilihat publik. Publish membuat satu versi menjadi canonical. Unpublish menarik versi live tanpa selalu menghapus pekerjaan editor. Delete dapat menghapus objek, menjadwalkan cleanup, atau mempertahankan tombstone. Jika semuanya dimodelkan sebagai satu flag, edge case mudah muncul ketika cache, preview, atau worker tertinggal.
State machine yang lebih jujur mencatat transition actor, timestamp, version, dan visibility. Setiap read path lalu memeriksa state yang sama. Preview boleh membaca draft dengan capability khusus; public route hanya menerima live version; worker dan CDN harus menerima invalidation ketika live state berubah.
Halaman editor bukan sumber kebenaran untuk publikasi. URL publik dari sesi bersih adalah pembacaan yang harus diuji.
Eksperimen dengan marker versi
Gunakan marker unik untuk draft dan live agar perbedaan mudah terlihat. Baseline dimulai dari versi live yang dapat dibaca publik. Penulis lalu mengubah draft tanpa menerbitkannya. Pengamatan yang sehat adalah URL publik tetap menampilkan marker live dan tidak memuat marker draft.
Kontrol ini penting karena editor sering menunjukkan draft terbaru dan dapat menipu penguji. Memuat URL di tab lain juga belum cukup jika tab membawa session atau preview cookie. Gunakan sesi anonim, cache-busting yang terkontrol, dan permintaan langsung ke canonical URL.
Publish harus mengubah versi otoritatif
Setelah publish, marker baru harus terlihat dari jalur publik. Periksa bukan hanya status 200, melainkan body, ETag, Age, Cache-Control, dan waktu perubahan. Jika origin sudah baru tetapi CDN masih lama, problemnya berbeda dari publish worker yang belum memperbarui database.
Dalam eksperimen teredaksi, draft marker tidak bocor saat versi live lama masih tayang. Hasil negatif ini berharga: ia mempersempit hipotesis dan menunjukkan pemisahan draft-live bekerja pada state, transport, dan waktu yang diuji. Ia tidak membuktikan semua role, route, atau format aman.
Unpublish berbeda dari delete
Unpublish seharusnya menghilangkan konten dari publik tanpa menghancurkan draft yang mungkin akan diterbitkan ulang. Pengujian melakukan readback segera setelah transisi dan kembali setelah jeda. URL publik berhenti menyajikan konten. Header cache diperiksa untuk memastikan hasil bukan sekadar satu browser yang lupa.
Delete kemudian diuji sebagai transisi terpisah. Konten tetap tidak tersedia dan pembacaan tertunda juga menghasilkan 404. Objek disposable serta komponen terkait dibersihkan. Ini adalah contoh negative security result yang layak disimpan: kontrol lifecycle bekerja dalam eksperimen tersebut.
Mengapa delayed control penting
Invalidation dapat tampak benar sesaat karena request menuju origin, lalu node CDN lain menyajikan salinan lama. Sebaliknya, cache lokal dapat menyembunyikan perbaikan origin. Immediate readback menguji transisi cepat; delayed readback menguji konsistensi setelah worker, replication, dan TTL bergerak.
Catat Age dan ETag bila tersedia. Cache miss setelah unpublish membantu membedakan salinan lama dari respons baru. Gunakan lokasi atau transport tambahan hanya jika scope dan risiko mengizinkan. Tujuannya bukan membanjiri CDN, melainkan memperoleh perbandingan satu variabel.
Matriks pengujian
- Draft: penulis melihat draft, publik hanya melihat versi live atau 404.
- Publish: canonical URL memuat versi yang disetujui dan metadata sesuai.
- Unpublish: public read berhenti, preview terotorisasi dapat tetap tersedia jika desain mengharuskan.
- Delete: public dan preview mengikuti retention policy; identifier lama tidak menghidupkan kembali konten.
- Republish: version dan cache key tidak mengembalikan aset lama secara keliru.
Dua penjelasan benign yang harus dipisahkan
Pertama, konten lama setelah unpublish mungkin berasal dari CDN yang belum menerima invalidation, bukan authorization failure. Kedua, akses melalui URL preview mungkin memang capability yang didokumentasikan dan tidak setara dengan URL publik. Periksa cookie, host, query, header, dan response provenance sebelum memilih kesimpulan.
Desain defensif
Gunakan versioned publication record dan satu policy visibility yang dipanggil semua transport. Invalidation harus terjadi pada publish, unpublish, delete, dan perubahan permission. Preview capability perlu expiry, binding, revocation, serta label jelas. Audit log harus memungkinkan tim menjawab versi mana aktif pada waktu tertentu.
Tambahkan tes integrasi yang mengikuti lifecycle lengkap dengan marker. Jangan hanya memanggil mutation dan memeriksa respons sukses. Test harus membuka canonical public route sebelum dan sesudah transisi, menunggu kontrol tertunda, kemudian membersihkan objek.
Nilai dari hasil negatif
Tim keamanan sering terdorong hanya menyimpan bug. Padahal bukti bahwa draft isolation, unpublish, cache invalidation, dan delete bekerja adalah baseline regresi yang sangat berguna. Ketika arsitektur berubah, eksperimen yang sama dapat dijalankan ulang untuk mengetahui komponen mana mulai berbeda.
Hasil negatif tetap harus dibatasi. Eksperimen ini tidak membuktikan semua tenant, role, format, region, atau legacy endpoint memiliki perilaku sama. Ia menutup tuple exact: objek disposable, actor, state transition, canonical read, dan window waktu yang diuji.
Checklist sebelum menyebut lifecycle aman
Tentukan invariant setiap state. Pertahankan marker live dan draft yang berbeda. Lakukan baseline publik, satu mutasi, matched control, immediate readback, delayed readback, dan cleanup. Periksa body serta cache headers. Bila satu path gagal, cari authority decision yang berbeda; bila seluruh path konsisten, catat DISPROVED-EXACT untuk hipotesis kebocoran yang diuji.
Jangan biarkan cache menentukan kebenaran produk.
Kami menguji state machine, preview capability, publication worker, cache invalidation, dan cleanup secara end-to-end.