Logo Doa & Tahlil Bersama
Masuk

Skenario Pengujian

SKENARIO PENGUJIAN
Aplikasi Doa & Tahlil Bersama

Format: ID | Skenario | Langkah | Hasil yang diharapkan

=====================================================================
A. AUTENTIKASI DAN AKUN
=====================================================================
TC-A-01 | Login lokal benar
  Masuk dengan user id dan kata sandi yang benar.
  -> Diarahkan ke Beranda. Audit trail memuat aksi "login".

TC-A-02 | Login salah berulang
  Salahkan kata sandi sebanyak batas maksimum.
  -> Akun terkunci sementara. Audit memuat "login_failed" tiap percobaan.

TC-A-03 | Wajib ganti kata sandi
  Masuk memakai kredensial hasil install.
  -> Dipaksa ke halaman ganti kata sandi sebelum dapat memakai aplikasi.

TC-A-04 | Kata sandi lemah ditolak
  Isi kata sandi 8 karakter tanpa angka.
  -> Ditolak dengan pesan syarat kata sandi.

TC-A-05 | Login Google peserta baru
  Masuk dengan akun Google yang belum terdaftar.
  -> Akun dibuat berstatus active, langsung masuk tanpa persetujuan admin.

TC-A-06 | Token Google palsu
  Kirim POST /google-login dengan token sembarang.
  -> Ditolak 401. Audit memuat "google_login_invalid".

TC-A-07 | Akun ditangguhkan
  Suspend akun, lalu coba masuk.
  -> Ditolak dengan pesan penangguhan.

TC-A-08 | Lupa kata sandi untuk email tak terdaftar
  -> Pesan sukses yang sama seperti email terdaftar (tidak membocorkan
     keberadaan akun). Tidak ada email terkirim.

TC-A-09 | Tautan reset dipakai dua kali
  -> Pemakaian kedua ditolak sebagai kedaluwarsa.

TC-A-10 | User ID tidak dapat diubah
  Buka Profil.
  -> Kolom User ID dalam keadaan nonaktif.

=====================================================================
B. OTORISASI DAN MULTI-SITE
=====================================================================
TC-B-01 | Menu mengikuti kewenangan
  Masuk sebagai Peserta.
  -> Kelompok menu Sistem tidak muncul sama sekali.

TC-B-02 | Akses langsung tanpa kewenangan
  Sebagai Peserta, buka /admin/pengguna melalui bilah alamat.
  -> Halaman 403. Audit memuat "access_denied".

TC-B-03 | Isolasi antar-site
  Sebagai Admin Site A, coba berpindah ke site B lewat manipulasi form.
  -> Perpindahan diabaikan, konteks tetap pada site A.

TC-B-04 | Matriks otorisasi berlaku langsung
  Matikan hak Read pada objek Feedback untuk suatu peran, lalu masuk
  sebagai peran tersebut.
  -> Menu Feedback Masuk hilang dan akses langsung ditolak.

TC-B-05 | Otorisasi Superadmin terkunci
  Coba simpan matriks untuk peran superadmin.
  -> Ditolak dengan pesan terkunci.

TC-B-06 | Perubahan otorisasi tercatat
  -> Audit memuat "authorization_update" beserta pelaku dan waktu.

=====================================================================
C. KEAMANAN
=====================================================================
TC-C-01 | SQL injection pada pencarian pengguna
  Isi kolom cari dengan: ' OR 1=1 --
  -> Tidak ada baris tambahan yang muncul, tidak ada galat basis data.

TC-C-02 | XSS pada nama
  Simpan nama berisi <script>alert(1)</script>.
  -> Ditampilkan sebagai teks biasa, skrip tidak dijalankan.

TC-C-03 | CSRF
  Kirim POST tanpa token _csrf.
  -> Ditolak dengan kode 419.

TC-C-04 | Unggah berkas berbahaya
  Unggah berkas .php yang dinamai ulang menjadi .jpg.
  -> Ditolak karena jenis konten sebenarnya tidak diizinkan.

TC-C-05 | Akses langsung berkas internal
  Buka /app/bootstrap.php, /sql/002_seed.sql, /storage/logs/php-error.log
  -> Seluruhnya mengembalikan 404 atau 403.

TC-C-06 | Kebocoran koordinat
  Periksa seluruh respons API saat mengikuti event.
  -> Tidak ada latitude atau longitude presisi milik pengguna lain.

TC-C-07 | Freeze transaksi
  Aktifkan freeze, lalu jalankan aksi transaksional.
  -> Ditolak dengan pesan pembekuan.

=====================================================================
D. AUDIT, BACKUP, RESET
=====================================================================
TC-D-01 | Audit mencatat nilai lama dan baru
  Ubah konfigurasi.
  -> Baris audit memuat nilai sebelum dan sesudah.

TC-D-02 | Audit tidak dapat diubah
  Jalankan UPDATE atau DELETE pada tabel audit_logs melalui psql.
  -> Ditolak oleh trigger dengan pesan append-only.

TC-D-03 | Nilai rahasia tersamar
  Ubah setelan yang ditandai rahasia.
  -> Audit memuat *** alih-alih nilai sebenarnya.

TC-D-04 | Verifikasi rantai hash
  Buka menu verifikasi.
  -> Menyatakan rantai utuh beserta jumlah entri.

TC-D-05 | Backup mengecualikan data pengguna
  Centang opsi pengecualian, buat backup, lalu unduh.
  -> Berkas tidak memuat tabel users, user_sites, dan role_permissions.

TC-D-06 | Deskripsi backup boleh kosong
  -> Backup tetap berhasil dibuat.

TC-D-07 | Restore memerlukan konfirmasi
  Kirim restore tanpa mengetik RESTORE.
  -> Ditolak.

TC-D-08 | Reset sistem mempertahankan Superadmin
  Jalankan reset.
  -> Tabel kosong, tetapi akun Superadmin, peran, otorisasi, site, dan
     konfigurasi tetap ada. Audit trail kosong dan rantai dimulai ulang.

=====================================================================
E. KONFIGURASI, CRON, NOTIFIKASI
=====================================================================
TC-E-01 | Konfigurasi site menimpa global
  Beri nilai berbeda pada kunci yang sama di tingkat site.
  -> Aplikasi memakai nilai tingkat site.

TC-E-02 | Tidak ada nilai tertanam dalam kode
  Ubah rentang sesi pagi pada konfigurasi.
  -> Perubahan tampak pada perilaku aplikasi tanpa menyentuh kode.

TC-E-03 | CRON berjalan
  Tunggu satu menit setelah crontab dipasang.
  -> Kolom "Terakhir" pada menu CRON terisi dan status ok.

TC-E-04 | Ekspresi jadwal tidak sah ditolak
  Isi jadwal dengan "abc".
  -> Tidak tersimpan.

TC-E-05 | Notifikasi dapat dimatikan
  Matikan satu template, lalu picu prosesnya.
  -> Tidak ada baris baru pada antrean notifikasi.

=====================================================================
F. TAMPILAN DAN PWA
=====================================================================
TC-F-01 | Tampilan ponsel
  Buka pada layar selebar 360 piksel.
  -> Menu berubah menjadi tombol, tabel dapat digeser mendatar,
     tidak ada elemen yang terpotong.

TC-F-02 | Posisi scroll dipertahankan
  Gulir ke bawah pada daftar panjang, lakukan aksi, kembali.
  -> Posisi gulir tidak melompat ke atas.

TC-F-03 | Menu selalu di kiri dan berkelompok
  -> Menu berada di sisi kiri dengan judul kelompok.

TC-F-04 | Logo pada setiap window
  -> Logo tampak pada bilah atas seluruh halaman.

TC-F-05 | Menu atas dan credit bawah
  -> Manual, petunjuk, dan skenario pengujian di bagian paling atas.
     Credit aplikasi di bagian paling bawah bilah samping.

TC-F-06 | Format tanggal
  -> Seluruh tanggal tampil dd/mm/yyyy dan jam hh:mm.

TC-F-07 | Ganti bahasa
  Pilih EN pada pemilih bahasa.
  -> Seluruh label antarmuka berubah ke bahasa Inggris.

TC-F-08 | PWA dapat dipasang
  -> Manifest terbaca, ikon tampil, aplikasi dapat ditambahkan ke
     layar utama, dan berjalan dalam mode standalone.

TC-F-09 | Gambar proporsional
  -> Tidak ada gambar yang gepeng atau melar.

=====================================================================
G. MODUL PEMBACAAN MANDIRI (Fase 2)
=====================================================================
TC-G-01 | Gerbang validasi syariah
  Buka versi liturgi yang belum ditandai tervalidasi, tekan Terbitkan.
  -> Ditolak. Status tetap draft. Audit memuat "liturgy_publish_blocked".

TC-G-02 | Catatan validasi wajib
  Tandai tervalidasi dengan catatan kosong.
  -> Ditolak dengan pesan catatan wajib diisi.

TC-G-03 | Penerbitan membuat paket
  Setelah tervalidasi, tekan Terbitkan.
  -> Status menjadi published, berkas JSON terbentuk di /assets/content,
     dan kolom paket terisi.

TC-G-04 | Versi terbit terkunci
  Ubah segmen pada versi yang sudah diterbitkan.
  -> Ditolak. Jumlah segmen tidak berubah.

TC-G-05 | Bobot progres proporsional
  Periksa paket JSON.
  -> Al-Fatihah berbobot lebih besar daripada satu kali tasbih, sehingga
     persentase tidak menghitung keduanya setara.

TC-G-06 | Membaca tanpa akun
  Buka /baca lalu pilih satu versi dalam mode penyamaran.
  -> Halaman pembaca terbuka tanpa diminta login.

TC-G-07 | Teks tersimpan di perangkat
  Buka pembaca, tunggu termuat, matikan jaringan, muat ulang halaman.
  -> Teks tetap tampil dari IndexedDB.

TC-G-08 | Posisi baca dilanjutkan
  Baca sampai segmen keempat, tutup peramban, buka lagi.
  -> Kembali ke segmen keempat disertai pemberitahuan.

TC-G-09 | Counter dzikir
  Pada segmen tasbih 33 kali, ketuk layar berulang.
  -> Angka bertambah, cincin terisi, getaran terasa, dan pada hitungan
     ke-33 berpindah otomatis ke segmen berikutnya.

TC-G-10 | Koreksi hitungan
  Tekan tombol minus setelah salah hitung.
  -> Angka berkurang satu dan tidak pernah kurang dari nol.

TC-G-11 | Mematikan segmen
  Matikan beberapa segmen di tab Pilih Segmen.
  -> Segmen tersebut dilewati dan total segmen pada bilah atas berkurang.

TC-G-12 | Profil setelan
  Ubah ukuran font, simpan sebagai profil baru, ganti ke profil Bawaan,
  lalu kembali ke profil baru.
  -> Setelan tiap profil tersimpan terpisah dan tidak saling menimpa.

TC-G-13 | Ekspor dan impor profil
  Ekspor sebuah profil, hapus profilnya, lalu impor kembali berkasnya.
  -> Profil kembali dengan seluruh setelan yang sama.

TC-G-14 | Impor berkas tidak sah
  Impor berkas JSON sembarang.
  -> Ditolak dengan pesan, aplikasi tidak rusak.

TC-G-15 | Batas kecepatan audio
  Geser penggeser kecepatan ke ujung.
  -> Tidak dapat melewati 0,75x dan 1,25x.

TC-G-16 | Gulir otomatis berhenti saat disentuh
  Pada mode senyap, gulir layar dengan jari saat bacaan berjalan.
  -> Gulir otomatis berhenti dan tombol "Kembali ke bacaan" muncul.

TC-G-17 | Tema gelap
  Pilih tema gelap.
  -> Latar dan warna teks berubah, teks Arab tetap terbaca jelas.

TC-G-18 | Menghormati pengurangan gerak
  Aktifkan pengurangan gerak pada sistem operasi.
  -> Animasi counter tidak berjalan meski setelan animasi penuh.

TC-G-19 | Bersihkan cache
  Tekan Bersihkan teks dan posisi baca.
  -> Teks dan posisi terhapus, tetapi daftar profil tetap ada.

TC-G-20 | Paket lama tidak berubah di tengah bacaan
  Saat sebuah perangkat sedang membaca, arsipkan versi tersebut di admin.
  -> Perangkat yang sedang membaca tidak terganggu sampai selesai.

=====================================================================
H. EVENT BERJAMAAH (Fase 3)
=====================================================================
TC-H-01 | Pelaksana wajib punya nomor ponsel
  Daftarkan event tanpa mengisi nomor ponsel pada profil.
  -> Ditolak dengan pesan melengkapi nomor ponsel. Tidak ada event dibuat.

TC-H-02 | Rebutan slot
  Dua pelaksana menekan simpan pada tanggal dan sesi yang sama nyaris
  bersamaan.
  -> Tepat satu event terbentuk. Yang kalah menerima pesan slot baru
     saja diambil. Ini wajib diuji dengan beban, bukan manual.

TC-H-03 | Satu sesi satu event
  Daftarkan event kedua pada sesi yang sudah terisi.
  -> Ditolak, apa pun jenis liturginya.

TC-H-04 | Waktu di luar rentang sesi
  Pilih pukul 23:00 pada sesi pagi.
  -> Ditolak.

TC-H-05 | Granularitas waktu
  Isi pukul 07:03.
  -> Ditolak karena bukan kelipatan lima menit.

TC-H-06 | Jendela pemesanan
  Pilih tanggal besok, lalu tanggal 60 hari lagi.
  -> Keduanya ditolak dengan rentang tanggal yang berlaku disebutkan.

TC-H-07 | Batas event aktif per pengguna
  Daftarkan event kedua saat masih ada satu event aktif.
  -> Ditolak sesuai konfigurasi.

TC-H-08 | Sanksi tidak hadir
  Setel dua event pengguna menjadi status no_show, lalu coba mendaftar.
  -> Ditolak selama masa jeda yang dikonfigurasi.

TC-H-09 | Tanggal terblokir
  Blokir sebuah tanggal, lalu coba mendaftar pada tanggal itu.
  -> Ditolak.

TC-H-10 | Blokir bentrok
  Blokir tanggal yang slotnya sudah terisi event.
  -> Ditolak agar event yang sudah terdaftar tidak dirugikan.

TC-H-11 | Pengingat terjadwal saat mendaftar
  Ikuti sebuah event.
  -> Dua baris pengingat masuk antrean sesuai konfigurasi menit.

TC-H-12 | Pengingat dijadwalkan ulang saat waktu berubah
  Ubah waktu mulai event.
  -> Pengingat lama berstatus cancelled dan pengingat baru dibuat.
     Ini bug yang paling mudah terlewat pada modul notifikasi.

TC-H-13 | Pembatalan melepas slot
  Batalkan sebuah event.
  -> Slot kembali kosong, peserta dinotifikasi, pengingat dibatalkan.

TC-H-14 | Pembatalan mendadak
  Batalkan event kurang dari 24 jam sebelum pelaksanaan sebagai pelaksana
  biasa.
  -> Ditolak, memerlukan pengelola.

TC-H-15 | Tombol Mulai wajib ditekan manusia
  Biarkan waktu mulai lewat tanpa menekan apa pun.
  -> Event tidak berubah menjadi live dengan sendirinya sebelum tenggat
     mode mandiri.

TC-H-16 | Mode mandiri saat pelaksana tidak hadir
  Tunggu sampai tenggat auto-start terlampaui.
  -> Peserta ditawari membaca sendiri, dan event tidak dibatalkan.

TC-H-17 | Wakil pelaksana
  Tunjuk wakil, lalu coba mulai sebagai wakil sebelum tenggat.
  -> Ditolak sebelum tenggat, diizinkan sesudahnya.

TC-H-18 | Progres imam proporsional bobot
  Tandai segmen keempat sebagai sedang dibaca.
  -> Persentase mengikuti jumlah bobot, bukan jumlah segmen.

TC-H-19 | Progres peserta dihitung atas bobot kanonik
  Matikan sebagian segmen di profil, lalu ikuti event.
  -> Persentase yang dikirim ke server tetap dihitung terhadap susunan
     kanonik event, sehingga tidak dapat melonjak ke 100 persen.

TC-H-20 | Segmen dzikir tidak dapat dimatikan dalam event
  Buka tab Pilih Segmen saat mengikuti event.
  -> Segmen dzikir tetap aktif.

TC-H-21 | Koordinat presisi tidak pernah keluar
  Periksa seluruh respons /api/event/{id}/peta dan /peserta.
  -> Hanya centroid kelompok yang muncul. Tidak ada latitude atau
     longitude presisi milik siapa pun.

TC-H-22 | Kelompok kecil menyembunyikan identitas
  Buat kelompok berisi kurang dari tiga peserta.
  -> Nama kota kelompok tidak ditampilkan.

TC-H-23 | POST API tanpa token CSRF
  Kirim ke /api/event/pimpin tanpa header token.
  -> Ditolak 419.

TC-H-24 | Menandai imam tanpa kewenangan
  Peserta biasa memanggil /api/event/pimpin.
  -> Ditolak 403.

TC-H-25 | Ikuti Imam
  Saat imam berada di segmen keenam, tekan Ikuti Imam.
  -> Tampilan melompat ke segmen keenam tanpa memaksa peserta lain.

TC-H-26 | Beban lonjakan
  Simulasikan 500 peserta bergabung dalam rentang dua menit.
  -> Waktu tanggap tetap wajar. Pola bertahap tidak sah sebagai uji.

=====================================================================
I. WAKAF (Fase 4)
=====================================================================
TC-I-01 | Alokasi wajib berjumlah 100
  Simpan skema dengan total 95 persen.
  -> Ditolak dan skema lama tetap utuh, tidak terhapus sebagian.

TC-I-02 | Alokasi minimal dua pihak
  Simpan skema berisi satu nazhir 100 persen.
  -> Ditolak.

TC-I-03 | Pembulatan tidak pernah kehilangan rupiah
  Wakaf Rp 100.001 dengan pembagian 40 dan 60 persen.
  -> Bagian berjumlah tepat Rp 100.001. Sisa pembulatan diberikan
     kepada pihak berpersentase terbesar dan ditandai di rincian.

TC-I-04 | Pembulatan pada persentase ganjil
  Tiga pihak 33,333 / 33,333 / 33,334 persen atas Rp 100.
  -> 33 + 33 + 34 = 100. Uji juga pada Rp 1, Rp 3, dan Rp 7.

TC-I-05 | Akad wajib disetujui
  Kirim wakaf tanpa mencentang akad.
  -> Ditolak.

TC-I-06 | Berwakaf tetap opsional
  Lewati layar ajakan wakaf pada event.
  -> Tidak ada fitur yang terkunci, event tetap dapat diikuti.

TC-I-07 | Alokasi dibekukan saat wakaf dibuat
  Buat wakaf, lalu ubah skema alokasi site, lalu buka rincian wakaf tadi.
  -> Rincian tetap memakai persentase lama.

TC-I-08 | Konfirmasi memerlukan rujukan bukti
  Konfirmasi donasi dengan kolom rujukan kosong.
  -> Ditolak.

TC-I-09 | Konfirmasi ganda ditolak
  Konfirmasi donasi yang sama dua kali.
  -> Yang kedua ditolak, tidak ada jurnal ganda.

TC-I-10 | Neraca ledger seimbang
  Setelah beberapa konfirmasi, buka menu Ledger.
  -> Total debit sama persis dengan total kredit.

TC-I-11 | Ledger tidak dapat diubah
  Coba UPDATE atau DELETE baris ledger melalui basis data.
  -> Koreksi hanya boleh melalui jurnal balik. Jurnal balik menjaga
     neraca tetap seimbang dan merujuk baris aslinya.

TC-I-12 | Jurnal balik hanya sekali
  Balik jurnal yang sama dua kali.
  -> Yang kedua ditolak.

TC-I-13 | Tanda terima bertanda tangan
  Buka tanda terima melalui tautannya tanpa login.
  -> Menyatakan tanda tangan sah beserta rincian alokasi.

TC-I-14 | Tanda terima mendeteksi perubahan
  Ubah nominal donasi langsung di basis data, lalu buka tanda terimanya.
  -> Dinyatakan tidak sah. Ini uji paling penting pada modul ini.

TC-I-15 | Penyaluran tidak melebihi saldo
  Catat penyaluran satu rupiah di atas saldo belum tersalur.
  -> Ditolak dengan menyebut saldo yang tersedia.

TC-I-16 | Penyaluran masuk ledger hanya setelah dibuktikan
  Catat penyaluran, periksa ledger sebelum bukti diunggah.
  -> Belum ada jurnal. Setelah bukti diunggah, jurnal terbentuk dan
     saldo belum tersalur berkurang.

TC-I-17 | Bukti penyaluran tampil di halaman publik
  Unggah bukti, buka halaman transparansi tanpa login.
  -> Bukti tercantum beserta nominal dan nazhirnya.

TC-I-18 | Verifikasi STBPN manual
  Verifikasi nazhir yang nomor STBPN-nya kosong.
  -> Ditolak. Nomor wajib diisi dan dicocokkan manusia ke data BWI.

TC-I-19 | Nazhir tanpa kanal pembayaran
  Buat wakaf yang dialokasikan ke nazhir tanpa QRIS maupun rekening.
  -> Halaman instruksi menyatakan kanal belum tersedia, bukan halaman
     kosong yang membingungkan.

TC-I-20 | Rekonsiliasi tanpa endpoint
  Jalankan job rekonsiliasi saat endpoint API belum dikonfigurasi.
  -> Job tidak melakukan apa pun dan melaporkan jumlah donasi yang
     menunggu penanganan manual. Job tidak boleh menebak status.

TC-I-21 | Rekonsiliasi menolak selisih nominal
  Balas API dengan status paid tetapi nominal berbeda satu rupiah.
  -> Tidak dikonfirmasi. Audit mencatat ketidakcocokan.

TC-I-22 | Freeze menghentikan transaksi wakaf
  Aktifkan freeze, lalu coba berwakaf dan mencatat penyaluran.
  -> Keduanya ditolak.

=====================================================================
J. PERKAKAS PRODUKSI KONTEN (Fase 5)
=====================================================================
TC-J-01 | Qori tanpa dasar lisensi ditolak
  Simpan qori dengan catatan lisensi kosong.
  -> Ditolak dan tidak ada baris tersimpan. Lisensi rekaman adalah
     risiko hukum tertinggi proyek ini, jadi gerbang ini tidak boleh
     dapat dilewati.

TC-J-02 | Audio wajib HTTPS
  Daftarkan berkas audio dengan URL http biasa.
  -> Ditolak.

TC-J-03 | Audio dari qori tanpa lisensi ditolak
  Coba daftarkan trek untuk qori yang catatan lisensinya kosong.
  -> Ditolak.

TC-J-04 | Peta waktu tumpang tindih ditolak
  Simpan penanda yang saling bertumpang tindih.
  -> Ditolak dengan menyebut nomor unit yang bertabrakan.

TC-J-05 | Nomor unit bolong ditolak
  Simpan penanda bernomor 1 dan 3 tanpa 2.
  -> Ditolak.

TC-J-06 | Penanda melewati akhir audio ditolak
  Simpan penanda berakhir jauh sesudah durasi audio.
  -> Ditolak.

TC-J-07 | Peta lama tetap utuh setelah penolakan
  Simpan peta cacat pada trek yang sudah punya peta sah.
  -> Peta lama tidak berubah. Penolakan yang menghapus separuh data
     lebih berbahaya daripada tidak menolak.

TC-J-08 | Peringatan, bukan penolakan
  Simpan peta yang sah tetapi menyisakan ekor panjang tak tertandai,
  atau memuat unit sangat pendek.
  -> Diterima disertai peringatan agar penandai memeriksa ulang.

TC-J-09 | Urutan acak dirapikan
  Simpan penanda dengan urutan nomor terbalik.
  -> Diterima dan diurutkan otomatis berdasarkan waktu mulai.

TC-J-10 | Impor peta waktu berbagai bentuk
  Impor JSON berbentuk larik langsung, berkunci timing, berkunci
  markers dengan from/to, dan bersatuan detik pecahan.
  -> Keempatnya terbaca dengan benar. Detik pecahan dikalikan menjadi
     milidetik.

TC-J-11 | Studio menandai dengan satu tombol
  Putar audio, tekan Ketuk pada setiap batas ayat.
  -> Setiap ketukan mengakhiri unit berjalan sekaligus memulai unit
     berikutnya. Ctrl+S menyimpan.

TC-J-12 | Studio memperingatkan perubahan belum disimpan
  Tandai beberapa unit lalu tutup tab.
  -> Peramban meminta konfirmasi.

TC-J-13 | Impor teks liturgi dari CSV
  Impor CSV berisi kolom code, title, type, ar, latin, translation,
  repeat, weight.
  -> Segmen terbentuk dengan bobot dan jumlah pengulangan yang benar.

TC-J-14 | Pemisah ayat pada CSV
  Isi kolom teks Arab dengan pemisah \n antar ayat.
  -> Tersimpan sebagai baris terpisah, sehingga dapat disorot satu
     per satu. Tanpa ini seluruh surah menjadi satu unit.

TC-J-15 | Impor tidak melewati gerbang validasi
  Impor naskah ke sebuah versi, lalu periksa statusnya.
  -> Versi tetap draft dan belum tervalidasi, sehingga tetap tidak
     dapat diterbitkan sebelum penasihat syariah menandainya.

TC-J-16 | Impor ke versi terbit ditolak
  Impor ke versi berstatus published.
  -> Ditolak dan jumlah segmennya tidak berubah.

TC-J-17 | Impor tambah versus ganti
  Impor tanpa mencentang ganti, lalu dengan mencentang.
  -> Yang pertama menambahkan di belakang, yang kedua mengganti
     seluruhnya. Nomor urut selalu dirapikan.

TC-J-18 | Laporan kesiapan audio
  Buka menu Audio dan Peta Waktu.
  -> Menampilkan berapa segmen yang sudah punya audio beserta peta
     waktunya, dihitung dari data, bukan ditebak.

TC-J-19 | Penguji API menolak endpoint non-HTTPS
  Uji endpoint berawalan http biasa.
  -> Ditolak.

TC-J-20 | Penguji API memeriksa kontrak, bukan sekadar hidup
  Uji endpoint yang menjawab 200 tetapi tanpa medan amount.
  -> Dinyatakan belum memenuhi syarat, dan rekonsiliasi otomatis
     tidak boleh dinyalakan.

=====================================================================
K. KELENGKAPAN DAN KEAMANAN LANJUTAN (Fase 6)
=====================================================================
TC-K-01 | Audit kelengkapan otomatis
  Jalankan php cli/audit.php.
  -> Tidak ada temuan KRITIS. Temuan yang tersisa hanya STD-41 yang
     memang sengaja tidak dibangun.

TC-K-02 | Berkas unggahan tidak dapat diakses langsung
  Buka /storage/uploads/profile/xxx.png melalui peramban.
  -> 404 atau 403 dari web server. Berkas hanya boleh melalui /media.

TC-K-03 | Foto pending tidak terlihat orang lain
  Unggah foto, lalu buka tautannya tanpa login.
  -> 403. Pemilik sendiri tetap dapat melihatnya.

TC-K-04 | Foto disetujui baru terlihat
  Setujui foto di menu Moderasi, buka sebagai pengguna lain.
  -> 200. Bila pemilik mematikan tampilkan foto, kembali 403.

TC-K-05 | Path traversal pada media
  Minta /media/profile/../../config.php dan varian tersandi.
  -> Ditolak. Tidak ada berkas di luar folder unggahan yang tersaji.

TC-K-06 | Jenis berkas diperiksa saat menyajikan
  Ganti isi berkas .png menjadi skrip PHP, lalu minta melalui /media.
  -> Ditolak karena jenis konten sebenarnya tidak diizinkan.

TC-K-07 | Pembatasan laju login
  Salahkan kata sandi enam kali berturut-turut.
  -> Percobaan keenam mengembalikan 429 disertai Retry-After.

TC-K-08 | Login berhasil mengosongkan hitungan
  Setelah beberapa kegagalan, masuk dengan benar.
  -> Hitungan direset agar pemakaian sah tidak terhukum.

TC-K-09 | MFA wajib bagi Superadmin
  Masuk sebagai Superadmin tanpa MFA aktif.
  -> Diarahkan ke halaman pengaktifan dan tidak dapat melewatinya.

TC-K-10 | MFA cocok dengan aplikasi autentikator
  Pindai kode QR di Google Authenticator, masukkan kodenya.
  -> Diterima. Vektor uji RFC 6238 juga menghasilkan kode yang sama.

TC-K-11 | Kode MFA kedaluwarsa ditolak
  Masukkan kode dari lima menit lalu.
  -> Ditolak. Toleransi hanya satu langkah waktu.

TC-K-12 | Kode cadangan MFA sekali pakai
  Pakai satu kode cadangan dua kali.
  -> Pemakaian kedua ditolak.

TC-K-13 | MFA tidak dapat dinonaktifkan oleh peran yang mewajibkannya
  Coba nonaktifkan sebagai Superadmin.
  -> Ditolak.

TC-K-14 | OTP disimpan sebagai hash
  Kirim OTP, periksa baris auth_tokens di basis data.
  -> Kolom token_hash berisi hash 64 karakter, bukan enam angka.

TC-K-15 | OTP salah dibatasi percobaannya
  Salahkan kode enam kali.
  -> Ditolak dan kode dianggap hangus.

TC-K-16 | Nomor wajib E.164
  Kirim OTP untuk 0812999.
  -> Ditolak.

TC-K-17 | Pelaksana wajib nomor terverifikasi
  Daftarkan event dengan nomor yang belum diverifikasi.
  -> Ditolak sesuai F-G-01.

TC-K-18 | Event terbatas tidak tampil publik
  Buat event terbatas, buka /event-publik dan peta publik.
  -> Tidak muncul di keduanya.

TC-K-19 | Undangan kedaluwarsa ditolak
  Buka tautan undangan yang sudah lewat masa berlakunya.
  -> Ditolak 410. Token tidak sah dan token kedaluwarsa memberi jawaban
     yang sama, sehingga keberadaan token tidak terbocorkan.

TC-K-20 | Batas pemakaian undangan
  Pakai undangan bermax_uses 2 sebanyak tiga kali.
  -> Pemakaian ketiga ditolak.

TC-K-21 | Cabut undangan
  Cabut sebuah tautan, lalu buka tautannya.
  -> Ditolak.

TC-K-22 | Berkas kalender .ics
  Unduh dari halaman event, buka di aplikasi kalender.
  -> Acara masuk dengan pengingat 30 menit sebelum mulai.

TC-K-23 | .ics event terbatas hanya untuk peserta
  Unduh .ics event terbatas tanpa menjadi peserta.
  -> Ditolak 403.

TC-K-24 | Ekspor data pribadi
  Unduh dari menu Profil.
  -> Berisi akun, profil, event, wakaf, pesan, feedback. Koordinat
     presisi TIDAK ikut, agar berkas ekspor tidak menjadi jalur bocornya
     data yang justru dilindungi.

TC-K-25 | Penghapusan akun
  Hapus akun yang pernah berwakaf.
  -> Identitas, profil, koordinat, dan pesan terhapus. Catatan wakaf
     tetap ada tetapi terputus dari identitas, karena ledger wajib utuh.

TC-K-26 | Penghapusan ditolak bila masih memimpin event
  Hapus akun yang punya event aktif.
  -> Ditolak agar jamaah yang sudah mendaftar tidak ditinggalkan.

TC-K-27 | Superadmin tidak dapat menghapus dirinya
  -> Ditolak.

TC-K-28 | Moderasi menolak foto
  Tolak sebuah foto.
  -> Berkasnya benar-benar dihapus dari penyimpanan, bukan sekadar
     ditandai, dan pengunggahnya diberi tahu.

TC-K-29 | Sesi perangkat tercatat
  Masuk dari dua peramban berbeda.
  -> Keduanya tercatat pada tabel user_sessions dan tampil di Profil.

TC-K-30 | Rute berparameter menerima nama berkas
  Minta /media/profile/nama.berkas.png dan /event/12/kalender.
  -> Keduanya cocok. Sebelum diperbaiki, titik pada parameter membuat
     rute tidak pernah cocok dan selalu berakhir 404.

=====================================================================
L. LOGIN GOOGLE (perbaikan)
=====================================================================
TC-L-01 | Permintaan login Google membawa token CSRF
  Masuk dengan Google, periksa permintaan ke /google-login pada tab
  Network peramban.
  -> Header X-CSRF-TOKEN terkirim. Tanpa itu router menolak 419 dan
     pesan yang tampil hanya "tidak dapat menghubungi server".

TC-L-02 | Jawaban server selalu JSON
  Picu kegagalan apa pun pada /google-login.
  -> Jawabannya JSON dengan medan msg, bukan halaman teks. Klien
     membaca teks lebih dulu lalu mencoba menguraikannya, sehingga
     jawaban bukan JSON pun tetap menghasilkan pesan yang berguna.

TC-L-03 | Client ID belum dikonfigurasi
  Kosongkan google.client_id lalu coba masuk.
  -> HTTP 503 dengan pesan bahwa login Google belum dikonfigurasi.

TC-L-04 | Server tidak dapat menghubungi Google
  Blokir sambungan keluar ke googleapis.com lalu coba masuk.
  -> HTTP 503 dengan pesan bahwa hosting kemungkinan memblokir
     sambungan keluar. TIDAK dilaporkan sebagai token tidak sah.

TC-L-05 | Proxy membalas 200 dengan isi bukan JWKS
  Arahkan googleapis.com ke proxy yang mengembalikan halaman sendiri.
  -> Tetap terdeteksi sebagai server tidak dapat menghubungi Google.
     Sambungan berhasil tidak sama dengan jawaban yang benar.

TC-L-06 | Client ID server berbeda dengan halaman
  Ubah google.client_id menjadi nilai lain, lalu masuk.
  -> HTTP 503 dengan pesan bahwa Client ID di server berbeda.

TC-L-07 | Token benar-benar palsu
  Kirim JWT dengan tanda tangan sembarang saat JWKS terjangkau.
  -> HTTP 401 dengan pesan token tidak sah. Dibedakan dari kegagalan
     sisi server.

TC-L-08 | Diagnosis dari baris perintah
  Jalankan php cli/install.php --status.
  -> Menampilkan Client ID, status allow_url_fopen, dan apakah kunci
     publik Google benar-benar terambil beserta jumlahnya.

TC-L-09 | Penanda versi aset mengikuti isi berkas
  Ubah isi assets/js/app.js, muat ulang halaman.
  -> Penanda ?v= pada URL berubah tanpa menyentuh konstanta apa pun.
     Sebelum diperbaiki, penandanya tetap 1.0.0 sehingga peramban
     menyajikan berkas lama selama 30 hari sesuai aturan cache.

TC-L-10 | Service worker tidak menyajikan skrip basi
  Pasang PWA, ubah app.js di server, buka kembali aplikasi.
  -> Skrip baru terambil. Skrip dan gaya memakai jaringan lebih dulu,
     cache hanya dipakai bila jaringan mati.

TC-L-11 | Endpoint versi
  Buka /api/ping.
  -> Menampilkan versi aplikasi dan penanda isi berkas JavaScript,
     sehingga versi di server dapat dibandingkan dengan yang dipakai
     peramban.

TC-L-12 | Token CSRF cadangan
  Hapus meta csrf-token dari halaman, lalu masuk dengan Google.
  -> Klien mengambil token dari /api/csrf alih-alih menyerah.

TC-L-13 | Keluaran liar sebelum header
  Tambahkan BOM UTF-8 di awal berkas konfigurasi, lalu picu kegagalan
  login Google.
  -> Status HTTP tetap benar (419 atau 503, bukan 200) dan jawabannya
     tetap JSON murni yang diawali karakter kurung kurawal.

TC-L-14 | Diagnosis keluaran liar
  Jalankan php cli/install.php --status dengan config ber-BOM.
  -> Bagian BERKAS KONFIGURASI menyebut nama berkas, jumlah byte, dan
     awalan byte-nya.

TC-L-15 | Penolakan CSRF berbentuk JSON
  Kirim POST ber-Accept application/json tanpa token.
  -> 419 dengan badan JSON, bukan teks biasa.

TC-L-16 | Pesan galat memuat cuplikan jawaban
  Buat server membalas HTML pada /google-login.
  -> Pesan kepada pengguna memuat cuplikan jawaban, sehingga pengelola
     punya petunjuk konkret alih-alih pesan umum.

TC-L-17 | Halaman diagnostik mati secara bawaan
  Buka /diagnostik tanpa install_token terisi.
  -> 404. Dengan token salah, 403.

TC-L-18 | Diagnostik menunjukkan sebab
  Buka /diagnostik dengan token benar pada server yang memblokir
  googleapis.com.
  -> Baris Kunci publik Google ditandai gagal beserta penjelasannya.

TC-L-19 | Uji titik akhir dari peramban
  Tekan tombol Uji /google-login pada halaman diagnostik.
  -> Menampilkan status HTTP, tipe konten, ada tidaknya BOM, dan
     apakah JSON dapat diurai.

TC-L-20 | Diagnostik terbuka bagi Superadmin tanpa token
  Masuk sebagai Superadmin, buka /diagnostik tanpa parameter.
  -> Terbuka. Tidak perlu menyunting berkas konfigurasi hanya untuk
     melihat diagnostik.

TC-L-21 | Halaman terkunci memberi petunjuk
  Buka /diagnostik tanpa login dan tanpa install_token.
  -> Menampilkan dua cara membukanya, berkas konfigurasi mana yang
     terdeteksi di server, dan baris siap salin dengan nilai acak.

TC-L-22 | Pembuatan akun dari login Google
  Masuk dengan akun Google yang belum pernah terdaftar.
  -> Akun terbentuk berstatus active, baris user_profiles ikut
     terbentuk, peran Peserta terpasang, notifikasi diantrekan, dan
     tercatat di audit trail.

TC-L-23 | INSERT ke tabel tanpa kolom id
  Panggil DB::insert('user_profiles', [...]) tanpa parameter ketiga.
  -> Tidak lagi memicu galat "column id does not exist". Bagian
     RETURNING dilewati bila kolomnya memang tidak ada.

TC-L-24 | Audit menangkap pemanggilan berisiko
  Kembalikan pemanggilan DB::insert ke tabel tanpa kolom id sehingga
  tanpa parameter eksplisit, lalu jalankan php cli/audit.php.
  -> Muncul sebagai temuan KRITIS.

TC-L-25 | Login Google berulang tidak menggandakan akun
  Masuk dua kali dengan akun Google yang sama.
  -> Tetap satu baris pengguna, dikenali lewat google_sub.

=====================================================================
M. MESSAGE CENTRE
=====================================================================
TC-M-01 | Baris baru pada isi pesan
  Buka menu Pesan setelah mendaftar.
  -> Isi pesan berbaris rapi. Tidak ada tulisan \n yang tampil sebagai
     teks.

TC-M-02 | Migrasi memperbaiki data lama
  Jalankan sql/005_perbaikan_baris_baru.sql pada basis data yang
  templatenya masih memuat literal \n.
  -> Template, pesan terkirim, dan antrean notifikasi ikut diperbaiki.
     Aman dijalankan berulang.

TC-M-03 | Pengaman di sisi kode
  Kembalikan sebuah template ke bentuk berliteral \n, lalu picu
  notifikasi baru.
  -> Pesan tetap tampil berbaris rapi, karena isinya dinormalkan saat
     template diisi.

TC-M-04 | Tautan dapat diklik
  Kirim pesan yang memuat alamat https.
  -> Tampil sebagai tautan, dan teksnya tetap ter-escape sehingga tidak
     membuka celah XSS.

TC-M-05 | Pesan belum dibaca menonjol
  -> Ditandai garis emas di sisi kiri, ikon berbeda, dan label baru.

TC-M-06 | Tandai dibaca satu per satu
  Tekan Tandai dibaca pada satu pesan.
  -> Hanya pesan itu yang berubah, sisanya tetap.

TC-M-07 | Keadaan kosong
  Buka menu Pesan pada akun baru tanpa pesan.
  -> Menampilkan penjelasan, bukan halaman kosong tanpa keterangan.

=====================================================================
N. PEMBATASAN PERAN PESERTA
=====================================================================
TC-N-01 | Menu Peserta hanya empat hal pokok
  Masuk sebagai Peserta, periksa bilah samping.
  -> Hanya Daftar Event, Wakaf, Wakaf Saya, dan Transparansi Wakaf,
     ditambah menu pribadi Beranda, Profil, Pesan, Feedback, dan Baca
     Mandiri. Tidak ada kelompok Konten, Wakaf admin, Laporan, maupun
     Sistem.

TC-N-02 | Menu admin bukan sekadar disembunyikan
  Sebagai Peserta, buka langsung /admin/liturgi, /admin/donasi,
  /admin/feedback, /admin/pengguna, /admin/nazhir, /admin/ledger.
  -> Seluruhnya 403. Menyembunyikan menu tanpa mencabut kewenangan
     akan menyisakan alamat yang tetap dapat dibuka.

TC-N-03 | Hak baca yang memunculkan menu
  Periksa matriks otorisasi peran Peserta.
  -> Tidak ada hak baca pada liturgy, donation, maupun feedback.
     Ketiganyalah yang dahulu memunculkan menu Liturgi, Versi Liturgi,
     Donasi Masuk, dan Feedback Masuk.

TC-N-04 | Peserta tetap dapat berwakaf
  -> /wakaf dan /wakaf/riwayat terbuka meski hak baca donation dicabut,
     karena riwayat diambil melalui jalur pemiliknya sendiri.

TC-N-05 | Superadmin tidak ikut terbatasi
  Masuk sebagai Superadmin.
  -> Seluruh kelompok menu tetap ada.

TC-N-06 | Migrasi kewenangan aman diulang
  Jalankan sql/006_otorisasi_peserta.sql dua kali.
  -> Hasilnya sama, tidak ada baris ganda, dan tercatat di audit trail.

=====================================================================
O. DASBOR PESERTA
=====================================================================
TC-O-01 | Seluruh isi dasbor berupa kartu yang dapat diklik
  Buka Beranda sebagai Peserta.
  -> Enam kartu, tidak ada tabel. Setiap kartu membawa ke halaman
     tempat pengguna dapat bertindak.

TC-O-02 | Kartu Tandai Kehadiran mengikuti keadaan
  a. Belum mengikuti event mana pun -> mengarah ke daftar event.
  b. Sudah mengikuti event mendatang -> menampilkan hitungan mundur
     dan mengarah ke halaman event.
  c. Event sedang berlangsung -> kartu menonjol dan mengarah langsung
     ke layar bacaan.

TC-O-03 | Kartu Akan Saya Hadiri
  Tekan kartunya.
  -> Membuka daftar event tersaring, hanya yang diikuti pengguna.

TC-O-04 | Kartu Pesan Baru muncul bersyarat
  -> Hanya tampil bila ada pesan belum dibaca.

TC-O-05 | Menghormati pengurangan gerak
  Aktifkan pengurangan gerak pada sistem operasi.
  -> Denyut pada kartu event berlangsung berhenti.

TC-N-07 | Menu Buat Event hanya untuk yang berwenang
  Bandingkan bilah samping Superadmin dan Peserta.
  -> Superadmin melihat Ikut Event, Buat Event, Event Terbatas, dan
     Blokir Tanggal. Peserta hanya melihat Ikut Event.

TC-N-08 | Peserta tidak dapat membuka halaman buat event
  Buka /event/buat dan /event/terbatas sebagai Peserta.
  -> Keduanya 403.

=====================================================================
P. PEMBUATAN EVENT UNTUK UMUM
=====================================================================
TC-P-01 | Menu Buat Event terlihat oleh Peserta
  Masuk sebagai Peserta biasa.
  -> Kelompok Event memuat Ikut Event dan Buat Event. Dasbor memuat
     kartu Buat Event.

TC-P-02 | Batas 30 hari ditegakkan
  Pilih tanggal 31 hari ke depan.
  -> Ditolak dengan menyebut rentang tanggal yang berlaku.

TC-P-03 | Batas terdekat H-2
  Pilih tanggal besok.
  -> Ditolak. Batas ini memberi waktu peserta lain untuk bersiap dan
     dapat diubah lewat event.booking_close_days. Isi 0 bila ingin
     mengizinkan pendaftaran untuk hari ini.

TC-P-04 | Tanggal dalam jendela diterima
  Pilih tanggal 29 hari ke depan.
  -> Diterima dan slotnya terkunci.

TC-P-05 | Nomor ponsel wajib terverifikasi
  Daftarkan event tanpa memverifikasi nomor ponsel.
  -> Ditolak, disertai tombol menuju halaman Profil.

TC-P-06 | Batas satu event aktif per pengguna
  Daftarkan event kedua saat satu masih aktif.
  -> Ditolak. Total event pengguna tetap satu.

TC-P-07 | Event terbatas tetap tertutup bagi Peserta
  Buka /event/terbatas sebagai Peserta.
  -> 403. Hak event_private tidak diberikan kepada Peserta dan dapat
     diatur terpisah melalui menu Otorisasi.

TC-P-08 | Tabel ketersediaan penuh hanya untuk pengelola
  Bandingkan halaman Buat Event antara Peserta dan Superadmin.
  -> Peserta hanya melihat daftar tanggal yang masih kosong.
     Pengelola melihat seluruh tanggal beserta pemiliknya.

TC-P-09 | Setelan pengaman tidak boleh tertinggal longgar
  Periksa max_active_events_per_user dan max_events_per_30d di
  Konfigurasi Global.
  -> Bawaannya 1 dan 2. Nilai yang sempat dilonggarkan saat pengujian
     wajib dikembalikan sebelum rilis.

=====================================================================
Q. MIGRASI BASIS DATA LEWAT WEB
=====================================================================
TC-Q-01 | Halaman migrasi hanya untuk Superadmin
  Buka /admin/migrasi sebagai Peserta maupun Admin Site.
  -> 403.

TC-Q-02 | Migrasi yang belum diterapkan terlihat
  Buka halaman sebagai Superadmin pada basis data yang belum
  dimigrasikan.
  -> Menampilkan jumlah yang belum dijalankan beserta daftar berkasnya
     dan ringkasan tujuannya.

TC-Q-03 | Jalankan semua
  Tekan Jalankan semua yang belum.
  -> Seluruhnya berjalan berurutan, ditandai diterapkan, dan tercatat
     pada Audit Trail.

TC-Q-04 | Perintah khusus psql tidak menggagalkan
  Migrasi memuat baris \echo dan \set.
  -> Baris itu dibuang sebelum dikirim ke basis data. Blok $$ ... $$
     tidak ikut terpotong.

TC-Q-05 | Berkas pemasangan awal ditolak
  Coba jalankan 001_schema.sql atau 002_seed.sql dari halaman ini.
  -> Ditolak. Hanya berkas bernomor 005 ke atas yang diizinkan.

TC-Q-06 | Aman dijalankan ulang
  Jalankan ulang migrasi yang sudah diterapkan.
  -> Berhasil tanpa menggandakan data.

TC-Q-07 | Kegagalan ditampilkan apa adanya
  Rusak sebuah berkas migrasi, lalu jalankan.
  -> Menampilkan pesan basis data dan potongan perintah yang gagal,
     bukan sekadar kata gagal.

TC-Q-08 | Jejak galat tidak pernah sampai ke pengguna
  Paksa display_errors aktif di php.ini, lalu picu galat fatal.
  -> Yang tampil halaman kesalahan yang wajar berstatus 500. Tidak ada
     nama kelas, nomor baris, maupun jalur berkas server. Rinciannya
     tetap tercatat pada storage/logs/php-error.log.

TC-Q-09 | Endpoint API dijawab JSON saat galat
  Picu galat fatal pada alamat berawalan /api/.
  -> Jawabannya JSON, bukan halaman HTML, sehingga klien tetap dapat
     menguraikannya.

TC-Q-10 | Pemformat tanggal tidak menjatuhkan halaman
  Kirim teks bebas ke fdate().
  -> Dikembalikan apa adanya dan dicatat di log. Fungsi pemformat tidak
     sepantasnya menghentikan seluruh halaman karena satu nilai keliru.

TC-Q-11 | Diagnostik melaporkan display_errors
  Buka Diagnostik Server pada hosting yang menimpa pengaturan itu.
  -> Baris display_errors ditandai perlu perhatian, disertai penjelasan
     bahwa jejak galat sudah dicegat jaring pengaman.

=====================================================================
R. KELENGKAPAN DATA, PROGRES, DAN PETA
=====================================================================
TC-R-01 | Gerbang kelengkapan data
  Sebagai peserta yang datanya belum lengkap, buka Buat Event.
  -> Dialihkan ke halaman Lengkapi Data, bukan ditolak, disertai
     daftar apa saja yang masih kurang.

TC-R-02 | Empat hal yang diminta
  -> Nama lengkap, kota, nomor ponsel terverifikasi, dan titik lokasi.

TC-R-03 | Koordinat presisi tidak pernah dibagikan
  Simpan titik -6.917464, 107.619123.
  -> Server menyimpan presisi itu, tetapi kelompok yang dibagikan
     hanya -6.9_107.6, dan teks di layar pun menampilkan bentuk
     bulat itu agar pengguna tahu apa yang sebenarnya dibagikan.

TC-R-04 | Verifikasi OTP lintas sesi
  Kirim kode, lalu verifikasi dari tab lain atau setelah sesi terputus.
  -> Berhasil. Nomor diambil dari token, bukan hanya dari sesi.

TC-R-05 | Lokasi ditanya ulang saat ikut event
  Tekan Ikuti event.
  -> Muncul halaman konfirmasi berisi peta. Titik lama dipakai sebagai
     awalan dan dapat digeser, karena orang berpindah tempat.

TC-R-06 | Lokasi baru menimpa yang lama
  Konfirmasi dengan titik berbeda saat ikut event.
  -> Profil dan baris peserta ikut diperbarui, sehingga peta sebaran
     mencerminkan tempat ia benar-benar akan membaca.

TC-R-07 | Progres berjamaah terlihat peserta
  Buka halaman event.
  -> Menampilkan jumlah peserta, yang sedang membaca, rata-rata
     progres, progres imam, dan status event. Disegarkan berkala.

TC-R-08 | Peta sebaran peserta
  -> Menampilkan lingkaran per kelompok, besarnya mengikuti jumlah
     anggota. Kelompok kecil tidak menampilkan nama kota.

TC-R-09 | Daftar peserta terpaginasi
  -> Dimuat bertahap, bukan sekaligus, dan hanya untuk yang sudah masuk.

TC-R-10 | Menu berkelompok dan dapat dilipat
  Tekan judul kelompok.
  -> Melipat dan membuka, keadaannya diingat antar halaman. Kelompok
     yang memuat halaman aktif terbuka otomatis.

TC-R-11 | Beranda melipat semua
  Tekan Beranda.
  -> Seluruh kelompok kembali terlipat.

TC-R-12 | Migrasi 008 tangguh
  Cabut izin event dan buang constraint UNIQUE, lalu jalankan 008.
  -> Izin terpasang kembali dan constraint dibuat ulang. Berkas ini
     tidak memakai ON CONFLICT sehingga tidak bergantung pada
     constraint yang mungkin tidak ada.

=====================================================================
S. SETELAN KELENGKAPAN DAN BILAH ATAS
=====================================================================
TC-S-01 | Syarat data dapat dimatikan
  Setel onboarding.require_phone menjadi 0 pada Konfigurasi Global.
  -> Halaman Lengkapi Data tidak lagi menampilkan bagian Nomor Ponsel,
     dan Buat Event terbuka tanpa nomor ponsel.

TC-S-02 | Pengaman slot ikut menyesuaikan
  Dengan require_phone mati, daftarkan event.
  -> Tidak lagi ditolak karena nomor ponsel. Pengaman yang tersisa
     adalah batas event aktif, batas per 30 hari, dan sanksi tidak
     hadir.

TC-S-03 | Verifikasi tanpa nomor tidak masuk akal
  Setel require_phone 0 tetapi require_phone_verified 1.
  -> Verifikasi tidak diwajibkan, karena nomornya sendiri tidak diminta.

TC-S-04 | Penomoran langkah menyesuaikan
  Matikan syarat nomor ponsel.
  -> Langkah pada halaman Lengkapi Data ternomori ulang, tidak ada
     nomor yang melompat.

TC-S-05 | Kelompok menu terbuka secara bawaan
  Masuk sebagai pengguna baru.
  -> Seluruh kelompok terbuka. Sebelumnya terlipat, dan menu seperti
     Buat Event menjadi tidak terlihat sama sekali.

TC-S-06 | Yang diingat adalah kelompok yang ditutup
  Tutup sebuah kelompok, pindah halaman.
  -> Tetap tertutup. Kelompok yang memuat halaman aktif selalu terbuka
     agar posisi pengguna terlihat.

TC-S-07 | Dokumen teknis hanya untuk pengelola
  Bandingkan bilah atas Superadmin dan Peserta.
  -> Peserta hanya melihat Manual Penggunaan. Petunjuk Implementasi
     dan Skenario Pengujian tidak tampil.

TC-S-08 | Identitas pengguna pada bilah atas
  -> Menampilkan inisial dan nama, tertaut ke halaman Profil. Pada
     layar sempit hanya inisialnya yang tampil.

=====================================================================
T. CONTOH BACAAN UNTUK UJI COBA
=====================================================================
TC-T-01 | Panel muncul saat belum ada versi terbit
  Buka menu Liturgi pada pemasangan baru.
  -> Menampilkan dua jalan: memasukkan naskah yang disahkan, atau
     memasang contoh untuk mencoba.

TC-T-02 | Pemasangan contoh
  Tekan Pasang contoh untuk uji coba.
  -> Terbentuk 12 segmen, terbit, dan paket JSON tertulis. Kerangka
     ratib Al-Haddad, Al-Attas, dan Al-Aidrus ikut dibuat kosong.

TC-T-03 | Penandaan tegas
  Periksa nama liturgi dan catatan validasinya.
  -> Namanya memuat CONTOH UJI COBA dan catatan validasinya menyatakan
     tegas bahwa itu bukan validasi syariah.

TC-T-04 | Sorotan per ayat berfungsi
  Buka pembaca pada segmen Al-Fatihah.
  -> Tujuh baris terpisah, sehingga penyorotan berjalan per ayat.

TC-T-05 | Penghitung dzikir
  Buka segmen Tahlil.
  -> Penghitung menampilkan target 100 dan bertambah tiap ketukan.

TC-T-06 | Gerbang validasi tetap berlaku untuk naskah asli
  Buat versi baru dari naskah sendiri lalu coba terbitkan tanpa
  menandainya tervalidasi.
  -> Ditolak. Pemasang contoh tidak melonggarkan gerbang ini.

TC-T-07 | Pilihan kaligrafi disertai alasan
  Buka panel setelan pembaca.
  -> Terdapat penjelasan mengapa Kufi, Diwani, dan Ruq'ah tidak
     disediakan untuk badan teks.

TC-T-08 | Rentang kecepatan dapat diatur
  Ubah pembaca.speed_min dan speed_max pada Konfigurasi.
  -> Penggeser kecepatan pada pembaca ikut berubah.

=====================================================================
U. PENDAFTARAN EVENT PADA HARI YANG SAMA
=====================================================================
TC-U-01 | Hari ini tersedia bila diizinkan
  Setel event.booking_close_days menjadi 0.
  -> Tanggal hari ini muncul pada pilihan, disertai keterangan tenggang
     persiapan minimumnya.

TC-U-02 | Waktu yang sudah lewat ditolak
  Pilih hari ini dengan jam yang sudah terlewat.
  -> Ditolak, disertai jam paling cepat yang masih boleh.

TC-U-03 | Waktu terlalu mepet ditolak
  Pilih jam 20 menit dari sekarang saat min_lead_minutes bernilai 60.
  -> Ditolak. Jendela pemesanan bekerja pada tingkat tanggal, sehingga
     tanpa tenggang menit, hari yang sama berarti event dapat dimulai
     beberapa menit lagi.

TC-U-04 | Waktu yang cukup diterima
  Pilih jam tiga jam dari sekarang.
  -> Diterima dan slotnya terkunci.

TC-U-05 | Pilihan waktu disaring di server
  Bandingkan daftar waktu untuk hari ini dan hari lain.
  -> Hari lain menampilkan seluruh rentang sesi, hari ini hanya waktu
     yang masih memenuhi tenggang. Penyaringan dilakukan di server agar
     tetap benar meski jam perangkat pengguna meleset.

TC-U-06 | Setelan site menimpa setelan global
  Ubah session_pagi_end pada Konfigurasi Site.
  -> Nilai site yang berlaku. Ini rancangan yang disengaja, dan perlu
     diingat saat menelusuri mengapa sebuah jam ditolak.

TC-U-07 | Pelaksana memulai eventnya sendiri
  Sebagai Peserta biasa yang mendaftarkan event, tekan Mulai sekarang.
  -> Berhasil. Memimpin ditentukan kepemilikan, bukan peran. Gerbang
     peran pernah dipasang di sini dan membuat pelaksana tidak dapat
     memulai eventnya sendiri.

TC-U-08 | Pengelola dapat mengambil alih
  Sebagai pengelola berkewenangan event_lead, tandai segmen pada event
  milik orang lain.
  -> Berhasil. Inilah gunanya kewenangan event_lead.

TC-U-09 | Orang lain ditolak
  Sebagai peserta biasa yang bukan pelaksana, panggil endpoint memimpin.
  -> 403.

TC-U-10 | Penolakan pada API dijawab JSON
  Periksa badan jawaban penolakan di atas.
  -> JSON yang dapat diurai, bukan halaman HTML. Halaman HTML membuat
     klien gagal mengurai dan pengguna hanya melihat pesan umum.

TC-U-11 | Pesan galat menyebut sebab
  Picu penolakan dari layar pelaksanaan.
  -> Pesan menyebut bahwa hanya pelaksana, wakil, atau pengelola yang
     berwenang, bukan sekadar tidak dapat memulai.

=====================================================================
V. BERKAS PAKET TEKS HILANG
=====================================================================
TC-V-01 | Berkas paket hilang terdeteksi
  Hapus berkas JSON pada assets/content untuk versi yang terbit, lalu
  buka layar pelaksanaan atau halaman pembaca.
  -> Menampilkan halaman Teks Bacaan Belum Siap. TIDAK berhenti pada
     tulisan memuat teks tanpa penjelasan.

TC-V-02 | Petunjuk perbaikan sesuai peran
  Buka halaman itu sebagai pengelola dan sebagai peserta biasa.
  -> Pengelola melihat jalur berkas yang dicari dan tautan ke halaman
     segmen. Peserta hanya diminta menghubungi pengelola.

TC-V-03 | Diagnostik melaporkannya
  Buka Diagnostik Server.
  -> Baris Paket teks bacaan menyebut berapa versi yang berkasnya
     hilang beserta namanya.

TC-V-04 | Terbitkan ulang memulihkan
  Tekan Terbitkan pada halaman segmen versi itu.
  -> Berkas ditulis ulang dari isi basis data, tidak ada teks hilang,
     dan layar pelaksanaan langsung berfungsi kembali.

TC-V-05 | Kegagalan pemuatan terlihat pada mode event
  Picu kegagalan pemuatan saat berada di layar pelaksanaan.
  -> Lapisan pra-acara disingkirkan agar pesannya terbaca. Sebelumnya
     pesan itu tertulis di baliknya sehingga layar tampak berhenti
     tanpa sebab.

=====================================================================
W. PENARIKAN VERSI LITURGI
=====================================================================
TC-W-01 | Versi terbit dapat diterbitkan ulang
  Tekan Terbitkan ulang pada versi yang sudah terbit.
  -> Berhasil. Berkas paket ditulis ulang dari isi basis data dan isi
     teksnya tidak berubah. Ini jalan memperbaiki paket yang hilang
     tanpa menyentuh naskah.

TC-W-02 | Penarikan ditolak bila masih dipakai event
  Tarik versi yang masih dipakai event terjadwal.
  -> Ditolak, disertai nomor event yang bersangkutan. Menarik versi
     yang sedang dipakai berarti mencabut isi bacaan dari jamaah yang
     sudah mendaftar.

TC-W-03 | Penarikan berhasil setelah event dibereskan
  Batalkan event tersebut, lalu tarik lagi.
  -> Status kembali menjadi draft dan paketnya tidak lagi berlaku.

TC-W-04 | Penandaan validasi ikut dicabut
  Periksa versi setelah ditarik.
  -> validated_at kosong dan catatan lama diberi awalan DICABUT
     beserta waktunya. Naskah yang hendak diubah wajib diperiksa
     ulang; membiarkan tanda validasi lama menempel pada teks yang
     sudah berbeda membuat gerbang syariah kehilangan artinya.

TC-W-05 | Segmen terbuka kembali
  Buka halaman segmen setelah penarikan.
  -> Kolom isian dapat disunting. Hanya nomor urut yang tetap terkunci
     karena diatur sistem.

TC-W-06 | Hilang dari katalog pembaca
  Buka /baca setelah penarikan.
  -> Versi itu tidak lagi tampil, karena katalog hanya memuat versi
     terbit.

TC-W-07 | Menerbitkan lagi menuntut validasi ulang
  Tekan Terbitkan setelah penarikan.
  -> Ditolak sampai versinya ditandai tervalidasi kembali.

TC-W-08 | Paksa hanya untuk Superadmin
  Sebagai pengelola bukan Superadmin, tarik versi yang masih dipakai.
  -> Tombolnya nonaktif dan pilihan paksa tidak tersedia.

TC-W-09 | Arsipkan berbeda dari menarik
  -> Menarik mengembalikan ke draft untuk disunting. Mengarsipkan
     memensiunkan versi untuk selamanya. Keduanya sama-sama memeriksa
     event yang masih memakainya.

=====================================================================
X. PENYALINAN VERSI LITURGI
=====================================================================
TC-X-01 | Salin dari halaman segmen
  Buka halaman segmen sebuah versi, gunakan bagian Salin Versi Ini.
  -> Nama, semver, dan kode versi sudah terisi usulan yang dapat
     diubah. Semver diusulkan naik satu tingkat minor.

TC-X-02 | Hasil salinan selalu draft
  Salin versi yang berstatus terbit dan sudah tervalidasi.
  -> Salinan berstatus draft, tanpa penandaan validasi, dan tanpa
     berkas paket. Salinan adalah naskah baru yang belum diperiksa
     siapa pun; mewarisi tanda validasi akan membuat gerbang syariah
     dapat dilewati hanya dengan menyalin.

TC-X-03 | Isi tersalin utuh
  Bandingkan segmen sumber dan salinan.
  -> Jumlah segmen, teks Arab, jumlah pengulangan, dan bobot sama
     persis. Pemisah baris pada surah ikut terjaga, sehingga
     penyorotan per ayat tetap bekerja.

TC-X-04 | Salinan dapat langsung disunting
  Buka halaman segmen salinan.
  -> Tidak ada pesan versi terkunci, kolom isian aktif.

TC-X-05 | Semver ganda ditolak
  Salin dengan semver yang sudah dipakai pada liturgi tujuan.
  -> Ditolak dengan pesan yang menyebut nomornya.

TC-X-06 | Salin ke liturgi lain
  Pilih liturgi tujuan yang berbeda.
  -> Berhasil. Susunan sebuah liturgi dapat dipakai sebagai titik awal
     liturgi lain, misalnya tahlil menjadi kerangka ratib.

TC-X-07 | Tidak ada dua fitur yang sama
  Periksa rute duplikasi.
  -> Hanya satu, yaitu /admin/liturgi/versi/duplikat. Halaman segmen
     memakai rute yang sama, bukan implementasi tersendiri.

=====================================================================
X. SALIN VERSI LITURGI
=====================================================================
TC-X-01 | Salin ke versi baru pada liturgi yang sama
  Buka Salin versi ini, isi nama dan semver, kirim.
  -> Versi baru terbentuk berisi seluruh segmen sumber, berstatus
     draft.

TC-X-02 | Salin ke liturgi LAIN
  Pilih liturgi tujuan yang berbeda, misalnya kerangka ratib.
  -> Segmen tersalin ke liturgi tujuan. Berguna sebagai titik awal
     penyusunan tradisi lain.

TC-X-03 | Penandaan validasi TIDAK ikut disalin
  Salin dari versi yang sudah tervalidasi.
  -> Salinan berstatus draft dengan validated_at kosong, dan catatan
     validasinya menyebut asal salinan. Yang disahkan penasihat syariah
     adalah naskah pada versi tertentu, bukan susunannya secara umum.

TC-X-04 | Isi tersalin utuh
  Bandingkan segmen sumber dan salinan.
  -> Tidak ada selisih pada kode, teks Arab, jumlah pengulangan, dan
     bobot. Nomor urut dirapikan berurutan mulai dari satu.

TC-X-05 | Semver ganda ditolak
  Salin memakai semver yang sudah ada pada liturgi tujuan.
  -> Ditolak.

TC-X-06 | Menambahkan ke draft yang ada
  Salin ke versi draft tanpa mencentang ganti.
  -> Segmen ditambahkan di belakang, nomor urut menyambung.

TC-X-07 | Mengganti seluruh isi draft
  Salin ke versi draft dengan mencentang ganti.
  -> Segmen lama terhapus dan digantikan segmen sumber.

TC-X-08 | Versi terbit tidak boleh menjadi tujuan
  Pilih versi terbit sebagai tujuan.
  -> Ditolak dengan penjelasan bahwa versi terbit terkunci. Daftar
     pilihan pun hanya memuat versi draft, sehingga penolakan itu
     menjadi lapis kedua.

TC-X-09 | Tujuan tidak boleh sama dengan sumber
  -> Ditolak.

=====================================================================
Y. PENGHAPUSAN LITURGI DAN VERSI
=====================================================================
TC-Y-01 | Konfirmasi wajib diketik
  Tekan hapus tanpa mengisi kolom konfirmasi.
  -> Ditolak. Versi tetap ada.

TC-Y-02 | Versi terbit tidak dapat dihapus
  Hapus versi berstatus published.
  -> Ditolak, diarahkan menarik ke draft atau mengarsipkan lebih dulu.

TC-Y-03 | Versi yang pernah dipakai event tidak dapat dihapus
  Hapus versi yang pernah dipakai event, termasuk event yang sudah
  selesai.
  -> Ditolak dengan menyebut nomor eventnya. Event menyimpan nomor
     versi sebagai bagian riwayatnya; menghapusnya membuat catatan
     ibadah masa lalu menunjuk ke sesuatu yang tidak ada.

TC-Y-04 | Penghapusan berhasil bila tidak ada ketergantungan
  -> Versi dan seluruh segmennya hilang, berkas paket JSON-nya ikut
     dibuang agar tidak menjadi sampah di server.

TC-Y-05 | Jejak audit memuat isi yang dihapus
  Periksa audit_logs sesudah penghapusan.
  -> Memuat nama liturgi, nama versi, semver, status, dan jumlah
     segmen. Jejak dibuat sebelum baris hilang, sehingga isinya sempat
     tercatat.

TC-Y-06 | Menghapus liturgi memakai konfirmasi kode
  Ketik kata sembarang pada kolom konfirmasi.
  -> Ditolak. Yang diminta adalah kode liturgi, agar orang membaca
     baris mana yang sedang dihapus.

TC-Y-07 | Liturgi dengan versi terbit ditolak
  -> Ditolak dengan menyebut nama versinya.

TC-Y-08 | Daftar liturgi menandai mana yang aman dihapus
  -> Setiap baris menampilkan jumlah versi terbit dan jumlah event yang
     memakainya. Yang tidak aman tidak menampilkan tombol hapus.

=====================================================================
Z. RANTAI AUDIT
=====================================================================
TC-Z-01 | Migrasi tidak boleh menyisipkan baris audit bertangan
  Periksa seluruh berkas sql untuk INSERT INTO audit_logs.
  -> Tidak ada. Menyisipkan baris audit dengan hash buatan memutus
     rantai dan membuat pemeriksaan keutuhan melaporkan kerusakan
     palsu.

TC-Z-02 | Titik putus yang diketahui tidak dilaporkan sebagai manipulasi
  Jalankan 012_perbaiki_rantai_audit.sql pada basis data yang rantainya
  sudah terlanjur putus.
  -> Baris penyebabnya TIDAK dihapus, hanya ditandai. Verifikasi rantai
     kembali melaporkan utuh, dan alasannya dapat dibaca pada
     system_flags.

TC-Z-03 | Baris sesudah titik putus tetap diperiksa ketat
  Ubah sebuah baris audit sesudah titik putus.
  -> Terdeteksi rusak. Pengecualian hanya berlaku pada satu baris yang
     sudah dijelaskan.

=====================================================================
AA. SUNTING LITURGI DAN VERSI
=====================================================================
TC-AA-01 | Tombol Ubah tersedia
  Buka menu Liturgi dan Versi Liturgi.
  -> Setiap baris memiliki tombol Ubah yang mengisi formulir di
     bawahnya. Sebelumnya kemampuan menyunting sudah ada di kode
     tetapi tidak punya tombol, sehingga tidak dapat dipakai.

TC-AA-02 | Ubah nama, jenis, dan keterangan liturgi
  -> Tersimpan, dan perubahannya tercatat di audit trail.

TC-AA-03 | Versi draft dapat diubah seluruhnya
  Ubah kode versi, nama, semver, tradisi, dan sumber rujukan.
  -> Seluruhnya tersimpan.

TC-AA-04 | Versi terbit: nama tampilan boleh diubah
  -> Tersimpan. Melarang perbaikan salah ketik hanya akan mendorong
     orang menarik versi dari peredaran tanpa perlu.

TC-AA-05 | Versi terbit: identitas paket terkunci
  Ubah semver, kode versi, atau liturgi induk pada versi terbit.
  -> Ditolak. Ketiganya menyusun nama berkas paket yang sudah
     tersimpan di perangkat pembaca; mengubahnya membuat perangkat
     mengejar berkas yang tidak ada. Kolomnya pun dinonaktifkan di
     layar agar penolakan terlihat sebelum tombol ditekan.

TC-AA-06 | Hapus versi langsung dari daftar
  -> Meminta pengetikan HAPUS, lalu menghapus beserta segmennya.

TC-AA-07 | Baris yang tidak boleh dihapus tidak menampilkan tombol
  Periksa baris versi terbit dan versi yang dipakai event.
  -> Tidak ada tombol hapus, hanya tanda hubung disertai keterangan
     saat disorot.

TC-AA-08 | Penjelasan liturgi dan versi
  -> Kedua halaman memuat penjelasan singkat perbedaannya, sehingga
     tidak perlu ditebak dari nama menunya.

=====================================================================
AB. RESET SISTEM BERTINGKAT
=====================================================================
TC-AB-01 | Saklar keamanan menahan seluruh tingkat
  Dengan keamanan.enable_system_reset bernilai 0, jalankan ketiga jenis
  reset.
  -> Seluruhnya ditolak dan tercatat pada audit. Tidak ada jalur yang
     diam-diam lebih longgar.

TC-AB-02 | Konfirmasi wajib diketik
  Kirim dengan teks selain RESET.
  -> Ditolak.

TC-AB-03 | Reset transaksi menyisakan yang penting
  Jalankan Hapus Transaksi.
  -> Event, peserta, donasi, ledger, penyaluran, pesan, dan feedback
     kosong. Pengguna, liturgi, segmen, peran, dan konfigurasi tetap
     utuh.

TC-AB-04 | Reset liturgi ditolak selagi masih ada event
  Jalankan Kembalikan Liturgi saat masih ada event.
  -> Ditolak dengan menyebut jumlah eventnya, karena event menyimpan
     nomor versi sebagai bagian riwayatnya.

TC-AB-05 | Reset liturgi memasang ulang contoh bawaan
  Jalankan setelah transaksi kosong.
  -> Seluruh liturgi lama hilang, contoh 12 segmen terpasang dan
     terbit, kerangka ratib ikut dibuat, dan berkas paket lama dibuang
     dari disk.

TC-AB-06 | Jumlah baris ditampilkan sebelum ditekan
  Buka halaman reset.
  -> Setiap tabel menampilkan jumlah barisnya, sehingga pengelola tahu
     persis apa yang akan hilang.

TC-AB-07 | Audit mencatat sebelum dan sesudah
  -> Terdapat pasangan reset_transaksi_mulai dan selesai, beserta
     jumlah baris per tabel. Rantai audit tetap utuh.

TC-AB-08 | Tabel di luar daftar tidak tersentuh
  Tambahkan tabel baru lalu jalankan reset transaksi.
  -> Tabel itu tidak ikut dikosongkan. Daftar tabel ditulis tegas di
     kode, bukan disapu otomatis.

TC-AB-09 | Lapisan pra-acara tidak muncul kembali setelah Mulai
  Tekan Mulai sekarang, lalu tunggu beberapa putaran polling.
  -> Lapisan tetap tersembunyi. Jawaban polling yang sudah dalam
     perjalanan saat tombol ditekan masih membawa status lama; tanpa
     penanda lokal, jawaban basi itu memunculkannya kembali dan
     pengguna mengira tombolnya tidak bekerja.

TC-AB-10 | Keadaan event terlihat, tidak perlu ditebak
  -> Layar pra-acara menampilkan status event dan apakah pengguna
     berwenang memimpin.

TC-AB-11 | Jalan keluar manual selalu tersedia
  Tekan Lewati layar ini dan buka bacaan.
  -> Bacaan terbuka. Teksnya memang sudah termuat di balik layar itu,
     jadi tidak ada alasan menahan orang yang ingin mulai membaca.

TC-AB-12 | Tombol Mulai memberi umpan balik
  -> Berubah menjadi Memulai selama permintaan berjalan, dan kembali
     dapat ditekan bila gagal.

TC-AB-13 | Atribut hidden harus menang atas aturan display
  Periksa berkas CSS.
  -> Terdapat aturan [hidden] { display: none !important; } pada
     reader.css dan style.css.

  Latar belakangnya: peramban menyembunyikan elemen ber-atribut hidden
  melalui aturan bawaan display:none, dan aturan itu KALAH oleh
  selektor kelas mana pun yang menyetel display. Akibatnya:

    .ev-stage  display:grid  -> lapisan pra-acara tidak pernah dapat
                                ditutup, menutupi seluruh teks bacaan
    #panel     display:flex  -> panel setelan selalu terbuka, tombol
                                tutup tampak tidak bekerja dan tab
                                seperti membeku
    #doneBox   display:grid  -> layar selesai menutupi bacaan
    .rd-counter display:flex -> penghitung dzikir selalu tampil

  Satu cacat ini menghasilkan beberapa gejala yang tampak tidak
  berhubungan. Pelajarannya: bila sebuah elemen dikendalikan atribut
  hidden, jangan pernah memberinya aturan display tanpa pasangan
  [hidden] yang menimpanya.

TC-AB-14 | Lapisan pra-acara benar-benar tertutup
  Tekan Mulai sekarang atau Lewati layar ini.
  -> Lapisan hilang dan teks bacaan terlihat.

TC-AB-15 | Panel setelan dapat ditutup
  Tekan tanda silang pada panel setelan, termasuk di ponsel.
  -> Panel tertutup dan bacaan kembali terlihat.

TC-AB-16 | Perpindahan tab panel
  Tekan tab Daftar Segmen, Jamaah, Peta, dan Pilih Segmen.
  -> Isinya berganti. Sebelumnya panel tidak pernah benar-benar
     tertutup sehingga tampak membeku.

=====================================================================
AC. LAJU BACA DAN SOROTAN MODE SENYAP
=====================================================================
TC-AC-01 | Sorotan berjalan tanpa rekaman qori
  Buka bacaan pada mode Senyap.
  -> Ayat yang sedang dibaca tersorot dan berpindah sendiri. Lamanya
     ditakar dari panjang teks, bukan dari peta waktu qori.

TC-AC-02 | Penanda sisa waktu terlihat
  -> Bilah kendali menampilkan nomor ayat, jumlah ayat, dan sisa detik
     ayat berjalan.

TC-AC-03 | Kecepatan baca dapat digeser
  Geser Kecepatan baca dari 0,5 sampai 2 kali.
  -> Ayat panjang berubah dari sekitar 9,7 detik menjadi 2,4 detik.
     Dzikir pendek tetap paling cepat 2 detik agar tidak berkedip.

TC-AC-04 | Batas bawah diterapkan sesudah pengali
  Percepat menjadi 2 kali pada dzikir pendek.
  -> Tetap 2 detik. Bila batas bawah diterapkan sebelum pengali,
     dzikir pendek akan berkedip terlalu cepat untuk diikuti mata.

TC-AC-05 | Sorotan manual
  Matikan Sorotan maju sendiri, lalu ketuk layar.
  -> Sorotan maju satu ayat setiap ketukan. Pada segmen dzikir
     berayat tunggal, ketukan tetap menaikkan penghitung.

TC-AC-06 | Menampilkan ayat bertahap
  Pilih satu, dua, atau tiga ayat sekaligus.
  -> Hanya ayat dalam jendela itu yang terlihat. Yang lain
     disembunyikan dengan visibility, bukan display, sehingga tinggi
     halaman tidak berubah dan posisi gulir tidak melompat.

TC-AC-07 | Menampilkan semua sekaligus
  -> Seluruh ayat terlihat, yang sedang dibaca tetap tersorot dan yang
     sudah lewat diredupkan.

TC-AC-08 | Arab, latin, dan terjemahan sejajar
  Nyalakan ketiganya.
  -> Ketiganya berada dalam satu blok per ayat, sehingga sorotan dan
     penampilan bertahap bekerja pada ketiganya sekaligus.

TC-AC-09 | Pengulangan dzikir maju sendiri
  Biarkan dzikir 33 kali berjalan pada laju otomatis.
  -> Penghitung naik tiap putaran, bergetar pelan, dan pada hitungan
     terakhir berhenti sejenak sebelum berpindah segmen.

TC-AC-10 | Profil lama tidak rusak
  Buka dengan profil yang dibuat versi sebelumnya.
  -> Kunci laju baca terisi otomatis dari bawaan, setelan lain tetap.

=====================================================================
AD. MENGHENTIKAN EVENT DAN PENANDA HIDUP
=====================================================================
TC-AD-01 | Pelaksana menghentikan event berjalan
  Tekan Hentikan event pada panel kelola atau layar pelaksanaan.
  -> Status menjadi closed, ended_at terisi, peserta dan progresnya
     TETAP tersimpan, dan slotnya tidak dilepas. Berbeda dari
     membatalkan, yang berarti event tidak jadi dilaksanakan.

TC-AD-02 | Peserta menerima pemberitahuan
  -> Setiap peserta terdaftar menerima pesan berisi rata-rata progres
     jamaah.

TC-AD-03 | Menghentikan dua kali ditolak
  -> Ditolak dengan keterangan bahwa event tidak sedang berlangsung.

TC-AD-04 | Bukan pelaksana tidak dapat menghentikan
  -> Ditolak, dan statusnya tidak berubah.

TC-AD-05 | Tombol tindakan di bawah nomor event
  Buka daftar event pada layar sempit.
  -> Tombol Ikuti event atau Masuk ke bacaan berada tepat di bawah
     nomor. Pada ponsel, kolom paling kanan berada di ujung gulir
     mendatar dan praktis tidak terlihat.

TC-AD-06 | Tiga kolom penerima doa
  Isi Permintaan dari, Hubungan, dan Penerima doa.
  -> Ketiganya tersimpan dan ditampilkan sebagai tabel tiga kolom.

TC-AD-07 | Pemohon kosong terisi otomatis
  Kosongkan kolom Permintaan dari.
  -> Terisi nama pengguna yang mencatat, karena dialah pemohonnya.

TC-AD-08 | Lampu hijau hanya berkedip bila ada yang membaca
  -> Lampu muncul di samping jumlah yang sedang membaca dan di samping
     nama peserta yang aktif. Lampu yang selalu menyala tidak memberi
     tahu apa pun.

TC-AD-09 | Kedipan dihentikan bagi yang meminta pengurangan gerak
  -> Animasinya mati, titik hijaunya tetap ada sehingga maknanya tidak
     hilang.

TC-AD-10 | Progres tiap peserta terlihat dan disegarkan
  -> Daftar peserta menampilkan bilah progres masing-masing beserta
     keterangan sedang membaca, pernah membaca, atau belum mulai.
     Disegarkan berkala, tetapi hanya halaman pertamanya agar posisi
     gulir pembaca tidak melompat.

TC-AD-11 | Total peserta ikut pembacaan
  -> Ditampilkan terpisah dari yang sedang membaca. Yang ini
     menghitung siapa saja yang pernah membaca, termasuk yang sedang
     menutup layar sejenak.

=====================================================================
AE. SETELAN YANG SALING MENIMPA
=====================================================================
TC-AE-01 | Nilai site menahan perubahan global
  Ubah event.session_pagi_start menjadi 03:00 pada Konfigurasi Global
  sementara Konfigurasi Site masih 06:00.
  -> Formulir Buat Event tetap menampilkan 06:00. Nilai site memang
     selalu menang; yang keliru bukan perilakunya, melainkan tidak
     adanya pemberitahuan.

TC-AE-02 | Halaman global memberi tahu berapa yang tidak berlaku
  -> Muncul peringatan berisi jumlah setelan yang ditimpa site, dan
     tiap barisnya ditandai beserta nilai yang benar-benar dipakai.

TC-AE-03 | Halaman site menerangkan perannya
  -> Menerangkan bahwa nilainya menimpa global, disertai nilai global
     sebagai pembanding pada baris yang berbeda.

TC-AE-04 | Tombol Pakai nilai ini
  Tekan tombol pada baris yang ditimpa.
  -> Nilai site disamakan dengan nilai global, tercatat pada audit,
     dan formulir Buat Event langsung mengikuti: Pagi (03:00-10:00)
     dengan 85 pilihan waktu.

TC-AE-05 | Baris site tidak dihapus, hanya disamakan
  -> Kode yang mengharapkan kunci itu ada pada tingkat site tetap
     menemukannya.

=====================================================================
AF. PENERIMA DOA, PETA, DAN TAB PANEL
=====================================================================
TC-AF-01 | Kolom pemohon dihapus dari layar
  Buka bagian Penerima Doa.
  -> Hanya ada Penerima doa dan Hubungan, bersebelahan. Pemohon selalu
     diisi nama pengguna yang menekan tombol, karena dialah pemohonnya;
     menanyakannya hanya menambah langkah tanpa menambah makna.

TC-AF-02 | Formulir di atas, daftar di bawah
  -> Yang sudah ditambahkan muncul di bawah formulir, bukan di atasnya.

TC-AF-03 | Bukan pembuat event dapat menitipkan nama
  Sebagai peserta biasa, tambahkan penerima doa.
  -> Tersimpan atas nama peserta tersebut.

TC-AF-04 | Peta mengirim jumlah yang sedang membaca per kelompok
  -> Setiap kelompok memuat medan active. Dihitung langsung dari
     peserta, bukan disimpan di tabel kelompok, karena angkanya berubah
     tiap menit sementara kelompoknya jarang berubah.

TC-AF-05 | Peta sebaran diredupkan
  -> Ubin peta ditampilkan abu-abu terang, sehingga penanda hijau
     berkedip menjadi satu-satunya yang berwarna.

TC-AF-06 | Pemilih lokasi TIDAK diredupkan
  Buka halaman melengkapi data atau konfirmasi lokasi.
  -> Peta tetap berwarna penuh, karena di sini pengguna justru perlu
     mengenali jalan dan sungai untuk menempatkan penanda.

TC-AF-07 | Penanda kelompok berkedip hanya bila ada yang membaca
  -> Kelompok dengan pembaca aktif berwarna hijau dan berkedip;
     yang tidak berwarna abu-abu diam.

TC-AF-08 | Tab Jamaah dan Peta berfungsi
  Tekan kedua tab, termasuk di ponsel.
  -> Panelnya terbuka dan datanya dimuat. Sebelumnya reader.js hanya
     mengikat empat nama tab secara harfiah, sehingga kedua tab itu
     tidak pernah dibuka. Gejalanya tersamar oleh bug atribut hidden
     yang membuat semua panel tampil sekaligus.

TC-AF-09 | Tab dibaca dari DOM
  Tambahkan tombol tab baru pada tampilan.
  -> Langsung berfungsi tanpa menyentuh reader.js.

TC-AF-10 | Batas jumlah event dapat diatur
  Ubah event.max_events_per_30d dari 2 menjadi 5.
  -> Pengguna yang sebelumnya tertahan dapat mendaftarkan lagi.

TC-AF-11 | Nilai 0 berarti tanpa batas
  Isi 0 pada max_events_per_30d dan max_active_events_per_user.
  -> Pengaman jumlah dimatikan seluruhnya. Nol dipilih sebagai penanda
     tanpa batas karena mengosongkan kolom isian akan tersimpan sebagai
     nol juga; bila nol berarti tidak boleh sama sekali, pengelola yang
     mengosongkan kolom akan mengunci seluruh penggunanya tanpa sadar.

TC-AF-12 | Pesan penolakan menyebut setelannya
  Sebagai pengelola, capai batas lalu buka Buat Event.
  -> Pesan menyebut nama kunci setelan, nilainya sekarang, tautan ke
     Konfigurasi, dan pengingat bahwa nilai Site menimpa Global.

TC-AF-13 | Peserta biasa tidak melihat kunci setelan
  -> Hanya diberi tahu bahwa batas ditetapkan pengelola.

=====================================================================
AG. EVENT TERBATAS UNTUK PESERTA UMUM
=====================================================================
TC-AG-01 | Peserta biasa dapat membuka halaman event terbatas
  Sebagai peran Peserta, buka /event/terbatas.
  -> HTTP 200. Sebelumnya 403, karena kewenangan event_private hanya
     diberikan kepada pelaksana dan pengelola.

TC-AG-02 | Menu tampil di bilah samping
  -> Menu Event Terbatas muncul pada kelompok EVENT.

TC-AG-03 | Peserta biasa dapat membuat event terbatas
  -> Terbentuk dengan event_type terbatas dan dirinya sebagai
     pelaksana.

TC-AG-04 | Tidak memakai slot harian
  Periksa event_slots setelah pembuatan.
  -> Kosong. Inilah alasan membukanya aman: event terbatas tidak
     mengurangi kesempatan jamaah lain mengadakan tahlil serentak pada
     dua slot harian milik site.

TC-AG-05 | Undangan utama dibuat otomatis
  -> Satu undangan berlabel Undangan utama terbentuk bersama eventnya.

TC-AG-06 | Pelaksana dapat menerbitkan undangan tambahan
  -> Tersimpan beserta batas pemakaiannya.

TC-AG-07 | Orang lain tidak dapat menerbitkan undangan event itu
  Sebagai peserta lain, kirim permintaan penerbitan undangan.
  -> Ditolak. Jumlah undangan tidak bertambah. Kewenangan baru hanya
     membuka pintu masuk; penjagaan di dalam tetap berdasarkan
     kepemilikan.

TC-AG-08 | Daftar hanya menampilkan event sendiri
  -> Event terbatas milik orang lain tidak terlihat.

TC-AG-09 | Kelengkapan data tetap diminta
  Sebagai peserta yang datanya belum lengkap, buka /event/terbatas.
  -> Dialihkan ke halaman Lengkapi Data. Undangannya memang tertutup,
     tetapi yang mengadakan tetap perlu dapat dihubungi bila acaranya
     ditinggalkan.

TC-AG-10 | Batas event terbatas menghormati nilai nol
  Isi 0 pada event.max_active_limited_events.
  -> Tanpa batas, sama seperti batas event umum.

=====================================================================
AH. MENERIMA DAN MENOLAK UNDANGAN
=====================================================================
TC-AH-01 | Dua pilihan ditampilkan sama besar
  Buka tautan undangan.
  -> Tombol Ikut dan Lain kali berdampingan dengan lebar sama.
     Undangan doa bukan tempat menggiring orang; yang tidak dapat
     hadir pun berhak menutupnya dengan tenang.

TC-AH-02 | Keduanya tampil meski belum masuk
  Buka sebagai tamu.
  -> Kedua tombol tetap ada. Menyembunyikannya di balik tombol Masuk
     membuat orang menutup tab sebelum tahu bahwa ia diundang.

TC-AH-03 | Ikut sebagai tamu mengarahkan ke halaman masuk
  -> Dialihkan ke /login, dan tujuan aslinya disimpan.

TC-AH-04 | Sesudah masuk kembali sendiri lalu tercatat
  Masuk dengan akun apa pun, termasuk Google.
  -> Diarahkan kembali ke tautan undangan, keikutsertaan tercatat, dan
     pemakaian undangan bertambah satu.

TC-AH-05 | Pemberitahuan terkirim ke dua pihak
  -> Peserta menerima konfirmasi, pelaksana menerima kabar bahwa
     undangannya diterima.

TC-AH-06 | Menekan Ikut dua kali tidak menggandakan
  -> Peserta tetap satu dan pemakaian undangan tetap satu.

TC-AH-07 | Lain kali tidak menuntut masuk
  Tekan Lain kali sebagai tamu.
  -> Halaman ucapan tampil, tercatat pada audit, dan tidak ada peserta
     yang bertambah. Memaksa orang membuat akun hanya untuk menyatakan
     tidak ikut adalah permintaan yang tidak masuk akal, dan hasilnya
     ia akan menutup tab begitu saja sehingga pelaksana tidak pernah
     tahu apa pun.

TC-AH-08 | Menolak tidak menghanguskan tautan
  -> Undangan masih dapat dibuka lagi selama belum kedaluwarsa,
     sehingga orang tetap dapat berubah pikiran.

TC-AH-09 | Daftar event terbatas punya tombol tindakan
  Buka Event Terbatas.
  -> Tiap baris menampilkan status, jumlah peserta, dan tombol
     Batalkan atau Hapus sesuai keadaannya. Sebelumnya daftar itu
     sama sekali tanpa tindakan, sehingga tidak ada yang dapat ditekan.

TC-AH-10 | Batas 24 jam tidak berlaku pada event terbatas
  Batalkan event terbatas yang mulai dua jam lagi.
  -> Berhasil. Batas itu dibuat untuk melindungi slot harian agar
     tidak menganggur; event terbatas tidak memakai slot sama sekali,
     sehingga memaksa pemiliknya meminta bantuan pengelola hanya untuk
     membatalkan acara keluarganya sendiri tidak melindungi siapa pun.

TC-AH-11 | Hapus permanen event terbatas
  Hapus event terbatas yang belum pernah dibaca siapa pun.
  -> Event, undangan, peserta, dan antrean pemberitahuannya hilang.
     Jejaknya tercatat pada audit sebelum barisnya dihapus.

TC-AH-12 | Event yang sudah menjadi riwayat ibadah ditolak
  Hapus event yang pesertanya pernah membaca.
  -> Ditolak. Yang tersedia hanya membatalkan, karena menghapusnya
     akan menghilangkan catatan bahwa mereka pernah beribadah bersama.

TC-AH-13 | Hanya pelaksana yang dapat menghapus
  Sebagai pengguna lain, kirim permintaan penghapusan.
  -> Ditolak, event tetap ada.

=====================================================================
AI. PENYEDERHANAAN MENU, WAKAF, DAN PWA
=====================================================================
TC-AI-01 | Tombol duplikat dibuang
  Buka Ikut Event.
  -> Tidak ada lagi tombol Buat Event dan Event Terbatas, karena
     keduanya sudah menjadi menu tersendiri.

TC-AI-02 | Nama menu diperjelas
  -> Ikut Event, Buat Event Publik, Buat Event Terbatas.

TC-AI-03 | Bilah atas tidak tumpang tindih di ponsel
  Buka pada layar 360 piksel.
  -> Nama site disembunyikan, nama aplikasi menyusut, dan tombol
     Keluar tetap terlihat. Sebelumnya seluruh isinya nowrap tanpa satu
     pun yang boleh menyusut, sehingga nama site menimpa nama aplikasi
     dan Keluar terdorong keluar layar.

TC-AI-04 | Kartu dasbor wakaf
  -> Berbunyi "Berwakaf melalui uang untuk mashlahat".

TC-AI-05 | Teks akad dapat diatur
  Ubah wakaf.akad_teks pada Konfigurasi.
  -> Halaman wakaf mengikuti. Kalimat akad adalah pernyataan hukum
     yang mengikat; yang berwenang mengubahnya nazhir dan penasihat
     syariah, bukan pengembang, sehingga tidak sepantasnya menunggu
     rilis aplikasi.

TC-AI-06 | Kartu Wakaf Emas dibuang
  -> Tidak lagi tampil.

TC-AI-07 | Kartu Wakaf Lainnya dapat diisi sampai tiga program
  Isi wakaf.program1_desc sampai program3_link.
  -> Yang terisi ditampilkan beserta tombol tautannya; yang kosong
     tidak muncul sama sekali.

TC-AI-08 | Catatan laporan program
  -> Tercantum bahwa laporan tiap program dilihat di platform
     masing-masing. Menyalin laporannya ke sini justru menyesatkan,
     karena angkanya akan tertinggal dari sumbernya.

TC-AI-09 | Pintasan manifest menunjuk rute yang ada
  -> /event, /baca, /transparansi. Sebelumnya menunjuk /event-publik
     yang bukan halaman untuk pengguna yang sudah masuk.

TC-AI-10 | Penanda pemasangan iOS
  -> Terdapat apple-mobile-web-app-capable dan status bar translucent.
     Safari tidak membaca manifest untuk hal ini, sehingga tanpa
     penanda itu aplikasi terpasang tetap menampilkan bilah alamat.

TC-AI-11 | Area aman perangkat berponi
  -> Bilah atas dan isi halaman menghormati env(safe-area-inset).

TC-AI-12 | Sasaran sentuh minimal 44 piksel
  -> Tombol, menu, dan isian memenuhi ukuran itu pada layar sempit.

TC-AI-13 | Isian tidak memicu perbesaran otomatis iOS
  -> Ukuran huruf isian 16 piksel pada layar sempit.

TC-AI-14 | Ajakan memasang tidak mengganggu
  -> Muncul sebagai bilah bawah setelah beberapa detik, bukan jendela
     yang menutupi layar. Bila ditutup, tidak muncul lagi 30 hari.

TC-AI-15 | Peta terisi tanpa menunggu penjadwal
  Kosongkan location_buckets, lalu buka peta sebaran event berjalan.
  -> Kelompok tetap terbentuk, dihitung langsung dari baris peserta.
     Pada hosting bersama penjadwal kerap tidak berjalan andal, dan
     peta yang selalu kosong lebih buruk daripada peta yang kasar.

TC-AI-16 | Titik tengah diturunkan dari kunci kelompok
  Periksa kelompok -7.0_110.4.
  -> Menghasilkan lat -7,0 dan lng 110,4. Koordinat presisi peserta
     tidak pernah dibaca apalagi dikirim ke peramban.

TC-AI-17 | Aturan kelompok kecil tetap berlaku
  -> Kelompok berisi 3 orang menampilkan nama kota; yang berisi 1 orang
     tidak.

TC-AI-18 | Lampu aktif dihitung per kelompok
  -> Kelompok dengan pembaca aktif menampilkan jumlahnya, dan penanda
     hijaunya berkedip.

TC-AI-19 | Peserta tanpa kelompok dilengkapi saat membaca
  Kosongkan geo_bucket seorang peserta, lalu kirim progres.
  -> Terisi kembali dari profilnya. Peserta yang bergabung sebelum
     melengkapi titik lokasi akan selamanya tidak muncul di peta bila
     tidak diperbaiki pada saat ia terbukti sedang membaca.

TC-AI-20 | Peta disegarkan tiap 12 detik
  -> Lampu yang menandai orang sedang membaca kehilangan artinya bila
     baru berubah setengah menit kemudian.

=====================================================================
AJ. PENATAAN LAYAR PELAKSANAAN
=====================================================================
TC-AJ-01 | Tombol penyelaras hanya muncul bila berguna
  Buka bacaan saat posisi Anda sama dengan imam.
  -> Tombol tidak tampil. Sebelumnya ia selalu tampil selama event
     berlangsung, termasuk ketika sudah sejajar, sehingga orang tidak
     pernah mengerti apa maksudnya.

TC-AJ-02 | Labelnya menyebut selisih
  Imam di segmen 5, pembaca di segmen 1.
  -> Tombol berbunyi "Imam di depan 4 bagian · Samakan", sehingga
     maksudnya terbaca dari tombolnya sendiri.

TC-AJ-03 | Imam belum menandai apa pun
  -> Tombol tidak tampil, karena tidak ada yang dapat diikuti.

TC-AJ-04 | Menekan Samakan memindahkan bacaan
  -> Bacaan berpindah ke bagian imam dan tombolnya hilang sampai
     posisinya kembali berbeda.

TC-AJ-05 | Bilah kendali tersusun, tidak bertumpuk
  Buka pada layar 360 piksel.
  -> Keterangan mode, kendali bacaan, dan tindakan pelaksana berada
     pada baris masing-masing. Sebelumnya ketiganya diposisikan mutlak
     pada bilah yang sama sehingga saling menimpa di ponsel.

TC-AJ-06 | Penghitung dzikir tidak menimpa apa pun
  -> Jaraknya dihitung dari tinggi bilah kendali melalui variabel,
     bukan angka tebakan.

TC-AJ-07 | Tombol Hentikan diberi nama Akhiri
  -> Lebih jelas maksudnya, dan konfirmasinya menyebut bahwa bacaan
     diakhiri untuk semua peserta.

TC-AJ-08 | Penjelasan tersedia di tab Jamaah
  -> Menerangkan Tandai Imam dan Samakan, termasuk bahwa bacaan
     peserta tidak pernah dipindahkan sendiri.

TC-AJ-09 | Tombol Google tidak melimpah keluar kartu
  Buka halaman masuk pada layar 360 piksel.
  -> Tombol muat di dalam kartu dan rata tengah. Sebelumnya lebarnya
     dipatok 340 piksel tetap, sehingga pada ponsel lebih lebar
     daripada kartunya sendiri.

TC-AJ-10 | Lebar mengikuti kartu
  -> Dihitung dari lebar pembungkus sebelum pustaka Google dimuat,
     dibatasi 200 sampai 400 piksel sesuai yang diterima Google.

TC-AJ-11 | Digambar ulang saat layar diputar
  Putar perangkat dari tegak ke mendatar.
  -> Tombol digambar ulang mengikuti lebar baru. Perubahan kecil
     diabaikan agar tidak berkedip saat papan ketik muncul.

TC-AJ-12 | Halaman daftar diperlakukan sama
  -> Memakai pembungkus dan perhitungan lebar yang sama.

=====================================================================
AK. KONSISTENSI DESAIN
=====================================================================
Dijalankan dengan: python3 cli/cek-desain.py

TC-AK-01 | Tidak ada tag dengan dua atribut class
  -> Nol. Peramban hanya membaca atribut class yang pertama, sehingga
     tag semacam itu diam-diam kehilangan sebagian gayanya.

TC-AK-02 | Tidak ada kelas yang dipakai tanpa gaya
  -> ev-summary dan input.pct kini didefinisikan. Sebelumnya keduanya
     tampil seadanya mengikuti aturan bawaan peramban.

TC-AK-03 | Warna memakai variabel
  -> Merah bahaya, emas, dan putih memakai variabel. Sebelumnya
     ditulis mentah sampai 27 kali, sehingga mengubah satu nuansa
     berarti menyisir seluruh berkas.

TC-AK-04 | Titik henti responsif seragam
  -> 620 dan 720 piksel dipakai konsisten. Sebelumnya 620, 640, 720,
     dan 760 bercampur tanpa alasan.

TC-AK-05 | Tidak ada duplikasi selektor di luar media query
  -> Penimpaan di dalam media query tetap ada dan memang seharusnya;
     itu cara kerja CSS, bukan duplikasi.

TC-AK-06 | Seluruh gambar memiliki atribut alt
  -> Terpenuhi.

TC-AK-07 | Seluruh halaman tetap terbuka sesudah perapian
  -> 37 halaman diperiksa, semuanya 200.

TC-AK-08 | Masuk dengan Google berada paling atas
  Buka halaman masuk.
  -> Urutannya logo, judul, tombol Google, pemisah, lalu bagian User ID
     yang terlipat. Hampir seluruh pengguna memakai Google; kolom kata
     sandi hanya dipakai pengelola.

TC-AK-09 | Papan ketik tidak muncul sendiri
  -> Tidak ada autofocus. Papan ketik yang terbuka sebelum halaman
     sempat dilihat justru menutupi pilihan yang ada.

TC-AK-10 | Kartu dirapatkan ke atas pada layar sempit
  -> Rata tengah vertikal dilepas di bawah 620 piksel. Ketika papan
     ketik muncul, bagian tengah kartu justru terdorong ke baliknya.

TC-AK-11 | Tinggi mengikuti area yang benar-benar terlihat
  -> Memakai dvh, bukan hanya vh. Satuan vh tidak menyusut saat papan
     ketik muncul, sehingga halaman mengira dirinya masih setinggi
     layar penuh dan menolak digulung.

TC-AK-12 | Isian tergulung sendiri bila tertutup papan ketik
  Sentuh kolom kata sandi pada ponsel.
  -> Tergulung ke tengah area terlihat, beserta labelnya. Hanya
     dilakukan bila isian memang tertutup.

TC-AK-13 | Bagian User ID dan kata sandi terlipat
  -> Tersedia di balik ringkasan yang dapat dibuka, sehingga yang
     jarang dipakai tidak menghalangi yang sering dipakai.

=====================================================================
AL. TAMPILAN HALAMAN WAKAF DAPAT DIATUR
=====================================================================
TC-AL-01 | Tiga saklar tersedia
  Sistem > Konfigurasi, kelompok wakaf.
  -> tampil_wakaf_uang, tampil_wakaf_lainnya, tampil_aliran_dana.
     Seluruhnya bernilai 1 secara bawaan, sehingga pemasangan yang
     sudah berjalan tidak berubah setelah migrasi.

TC-AL-02 | Menyembunyikan bagian Wakaf Uang
  Isi 0 pada tampil_wakaf_uang.
  -> Formulir nominal beserta akadnya tidak lagi tampil. Berguna bagi
     site yang belum menunjuk nazhir: menampilkan formulir yang belum
     siap dipakai lebih buruk daripada tidak menampilkannya, karena
     orang telanjur mengisi lalu tidak tahu uangnya ke mana.

TC-AL-03 | Menyembunyikan Wakaf Lainnya dan aliran dana
  -> Keduanya hilang secara terpisah.

TC-AL-04 | Seluruh bagian dimatikan
  -> Halaman menampilkan keterangan bahwa tidak ada program yang
     ditampilkan, beserta tempat menyalakannya kembali. Halaman kosong
     tanpa penjelasan akan disangka rusak.

TC-AL-05 | Kartu Wakaf Saya dan Hasil Wakaf dibuang dari dasbor
  -> Tidak lagi tampil. Menu bilah samping tetap ada, sehingga
     riwayat dan transparansi tetap terjangkau.

TC-AL-06 | Isi tidak melebar keluar layar ponsel
  Buka halaman wakaf pada layar 360 piksel.
  -> Tidak ada teks yang terpotong di tepi kanan. Deretan pilihan
     nominal digulir mendatar sebagai satu blok, bukan memaksa
     seluruh halaman ikut bergeser.

TC-AL-07 | Tautan mendaftar terlihat sejak layar pertama
  Buka halaman masuk.
  -> Tautan Daftar sekarang berada di luar bagian yang terlipat. Yang
     belum punya akun dan tidak memakai Google tidak akan menemukan
     jalan masuk bila tautannya bersembunyi di balik ringkasan yang
     harus dibuka lebih dulu.

TC-AL-08 | Halaman daftar terbuka
  -> HTTP 200.

TC-AL-09 | Kartu Total Wakaf Terhimpun dibuang dari halaman depan
  -> Digantikan ucapan Ahlan wa Sahlan beserta penjelasan singkat
     tentang event publik dan terbatas. Pada pemasangan yang baru
     berjalan angkanya nol, dan membuka halaman depan dengan Rp 0
     membuat aplikasi tampak sepi padahal belum sempat dipakai.

TC-AL-10 | Transparansi tetap terjangkau
  -> Tautan Lihat transparansi wakaf tetap ada pada kartu yang sama.

=====================================================================
AM. ALAMAT TRANSPARANSI DAPAT DIARAHKAN
=====================================================================
TC-AM-01 | Kosong berarti halaman bawaan
  Biarkan wakaf.link_transparansi kosong.
  -> Seluruh tautan mengarah ke /transparansi seperti sebelumnya.

TC-AM-02 | Diisi alamat luar
  Isi dengan alamat platform nazhir.
  -> Tautan pada halaman depan, halaman wakaf, layar pelaksanaan,
     bilah publik, dan menu bilah samping seluruhnya mengikuti.

TC-AM-03 | Tautan luar dibuka pada tab baru
  -> Memakai target blank beserta rel noopener noreferrer, sehingga
     halaman tujuan tidak dapat menyentuh tab asalnya.

TC-AM-04 | Menu menandai tautan yang membawa keluar
  -> Diberi tanda panah kecil, agar pengguna tahu ia akan
     meninggalkan aplikasi sebelum menekannya.

TC-AM-05 | Halaman transparansi bawaan tetap dapat dibuka
  -> Tetap 200. Pengalihan hanya mengubah tautannya, bukan menghapus
     halamannya, sehingga catatan lama tetap terjangkau.

TC-AM-06 | Logikanya satu tempat
  -> Ditulis sebagai fungsi transparansi_url. Tautannya muncul di lima
     tempat; menyalin logikanya ke tiap tempat berarti suatu hari
     empat ikut berubah dan satu tertinggal.

TC-AM-07 | Nama kunci link_transparansi
  Buka Konfigurasi kelompok wakaf.
  -> Terdapat link_transparansi. Kunci lama transparansi_url tidak
     lagi ada; dua kunci untuk satu keperluan selalu berakhir dengan
     salah satunya terlupakan dan menyesatkan orang yang mengubahnya.

TC-AM-08 | Nilai lama berpindah, bukan hilang
  Isi transparansi_url lalu jalankan migrasi 020.
  -> Nilainya berpindah ke link_transparansi dan kunci lama dihapus.
     Nilai tingkat site ikut dipindahkan.

TC-AM-09 | Diisi https://goldenwakaf.id
  -> Seluruh tautan Transparansi mengarah ke sana dan dibuka pada tab
     baru.

TC-AM-10 | Dikosongkan kembali
  -> Kembali ke halaman transparansi bawaan aplikasi.

TC-AM-11 | Kartu wakaf disederhanakan
  Buka dasbor.
  -> Hanya tertulis Berwakaf melalui uang untuk mashlahat. Kalimat
     Wakaf Uang dan Emas dibuang, karena wakaf emas memang sudah tidak
     ditangani aplikasi ini sejak kartunya dihapus dari halaman wakaf.

TC-AM-12 | Tujuan kartu dapat diarahkan
  Isi Wakaf_Mashlahat_melalui_Uang dengan alamat platform nazhir.
  -> Kartu menuju ke sana, dibuka pada tab baru, disertai tanda panah
     keluar.

TC-AM-13 | Kosong berarti halaman bawaan
  -> Kartu menuju /wakaf seperti sebelumnya.

TC-AM-14 | Halaman wakaf bawaan tetap terbuka
  -> Tetap 200 meski kartunya diarahkan ke luar, sehingga pengelola
     masih dapat memeriksanya.

TC-AM-15 | Jalan kembali ke halaman depan
  Buka halaman masuk, daftar, dan lupa sandi.
  -> Ketiganya memiliki tautan Kembali ke halaman depan di bawah, dan
     logonya dapat ditekan untuk tujuan yang sama.

TC-AM-16 | Diletakkan di layout, bukan di satu halaman
  -> Orang yang tersesat ke halaman lupa sandi juga butuh jalan pulang,
     bukan hanya yang berada di halaman masuk.

TC-AM-17 | Logo dapat ditekan
  -> Orang terbiasa menekan logo untuk kembali ke awal. Membiarkannya
     sebagai gambar mati menutup jalan keluar yang paling lumrah
     dicari.

=====================================================================
AN. PENYEDERHANAAN DAFTAR EVENT
=====================================================================
TC-AN-01 | Event terbatas milik orang lain tidak bocor
  Sebagai peserta yang tidak diundang, buka daftar event.
  -> Event terbatas itu tidak tampil pada tab mana pun. Sebelumnya
     kueri daftar tidak menyaring event_type sama sekali, sehingga
     event terbatas milik siapa pun ikut terlihat. Undangan yang dapat
     dilihat tanpa diundang bukan lagi undangan.

TC-AN-02 | Tiga tab menyaring satu daftar
  -> Semua event, Akan dihadiri, Belum dihadiri. Jumlah tiap tab
     tertera, sehingga tab kosong diketahui sebelum ditekan.

TC-AN-03 | Event terbatas yang diikuti tampil pada Akan dihadiri
  -> Bagi peserta keduanya sama saja: acara yang sudah ia sanggupi.
     Memisahkannya ke halaman lain membuat orang mengira undangannya
     hilang.

TC-AN-04 | Tombol menyesuaikan keadaan
  -> Belum ikut menampilkan Gabung. Sudah ikut menampilkan Sudah
     gabung. Sedang berlangsung menampilkan Hadir sekarang.

TC-AN-05 | Daftar berupa kartu, bukan tabel
  Buka pada layar 360 piksel.
  -> Tidak ada gulir mendatar, dan tombolnya melebar penuh di bawah
     keterangan. Tabel enam kolom mendorong tombol ke ujung kanan yang
     tidak terlihat.

TC-AN-06 | Dua kartu dasbor digabung
  -> Menjadi satu kartu Event berisi dua angka sekaligus, menuju tab
     Akan dihadiri bila memang ada isinya. Keduanya dulu menuju daftar
     yang sama dan hanya berbeda penyaringnya.

TC-AN-07 | Buat Event satu pintu, dua tab
  -> Halaman Buat Event menawarkan Event Umum dan Event Terbatas lewat
     tab. Menu bilah samping tidak lagi mengulang percabangan itu.

TC-AN-08 | Tab menyesuaikan kewenangan
  Sebagai pengguna tanpa kewenangan event terbatas.
  -> Hanya tab Event Umum yang tampil.

=====================================================================
AO. PENYEDERHANAAN TAMPILAN LANJUTAN
=====================================================================
TC-AO-01 | Dasbor menjadi empat kartu
  -> Event, Buat Event, Berwakaf, Pesan Baru. Kartu Tandai Kehadiran
     dibuang; keterangan event terdekat menempel pada kartu Event.
     Kartu terpisah dulu menuju halaman rincian dan membuat orang
     mengira itu tombol membuat event.

TC-AO-02 | Kartu Buat Event tanpa angka
  -> Hanya bertuliskan Buat Event. Angka 30 hari dibuang karena bukan
     jumlah, melainkan batas yang tidak perlu menonjol.

TC-AO-03 | Panah kembali ke beranda
  Buka halaman selain beranda pada layar sempit.
  -> Muncul panah di sebelah logo. Pada ponsel, bilah samping
     tersembunyi di balik tombol menu, sehingga jalan pulang semula
     memerlukan dua ketukan.

TC-AO-04 | Panah tidak muncul di beranda
  -> Tombol yang tidak menuju ke mana-mana hanya membingungkan.

TC-AO-05 | Kartu event dipimpin nama pelaksana
  -> Susunannya pelaksana, lalu hari-tanggal-jam, lalu bacaan. Nomor
     event dibuang dari daftar; yang dicari orang saat memilih adalah
     siapa yang memimpin dan kapan acaranya.

TC-AO-06 | Daftar event publik tanpa kolom nomor
  -> Kolomnya Pelaksana, Waktu, Bacaan, Kota, Peserta, Status.

TC-AO-07 | Format waktu seragam
  -> Hari, tanggal, dan jam dalam satu baris: Rabu 26/08/2026 19:00.
     Ditulis sebagai satu fungsi karena bentuk ini muncul di lima
     tempat; menyalinnya berarti suatu hari salah satunya berbeda
     sendiri.

TC-AO-08 | Sesudah bergabung, langsung diminta menitipkan nama
  -> Diarahkan ke halaman penitipan nama. Inilah saat orang paling
     mungkin melakukannya: ia baru menyanggupi hadir dan sedang
     memikirkan acaranya.

TC-AO-09 | Peringatan muncul sebelum menyimpan
  -> Tertulis bahwa nama dibacakan hanya bila ia ikut hadir, dan
     dibacakan oleh yang hadir, bukan oleh aplikasi. Ditempatkan
     sebelum tombol agar terbaca saat ia masih dapat memutuskan.

TC-AO-10 | Menambah nama tidak memindahkan halaman
  -> Tetap di langkah itu, sehingga nama berikutnya dapat ditambahkan
     tanpa berpindah. Pesan simpan mengulang syarat kehadirannya.

TC-AO-11 | Jenis event pada tab Akan dihadiri
  Buka tab Akan dihadiri yang memuat event publik dan terbatas.
  -> Di bawah nama pelaksana tertulis "Event publik · terbuka untuk
     siapa saja" atau "Event terbatas · hanya pemegang undangan",
     dibedakan warnanya agar terbaca sekilas.

TC-AO-12 | Label tidak muncul pada tab lain
  -> Tab Semua event dan Belum dihadiri seluruhnya berisi event
     publik, sehingga label yang selalu sama hanya menjadi kebisingan.

=====================================================================
AP. MEMBAGIKAN TAUTAN EVENT
=====================================================================
TC-AP-01 | Tombol Bagikan di samping Kelola
  Buka daftar Event yang Saya Daftarkan.
  -> Tiap baris memiliki tombol Kelola dan Bagikan berdampingan.

TC-AP-02 | Event umum dibagikan sebagai alamat rincian
  -> https://.../event/{id}

TC-AP-03 | Event terbatas dibagikan sebagai TAUTAN UNDANGAN
  -> https://.../undangan/{token}. Alamat rincian hanya dapat dibuka
     orang yang sudah menjadi peserta, sehingga membagikannya justru
     menyesatkan: penerima menekan tautan lalu ditolak.

TC-AP-04 | Undangan yang sudah habis atau kedaluwarsa
  Event terbatas tanpa undangan yang masih berlaku.
  -> Tombol Bagikan nonaktif, disertai keterangan saat disorot.
     Membagikan tautan yang pasti ditolak lebih buruk daripada tidak
     membagikan.

TC-AP-05 | Papan bagi bawaan dipakai bila tersedia
  Tekan Bagikan pada ponsel.
  -> Papan bagi sistem terbuka. Di situlah WhatsApp dan aplikasi lain
     sudah terdaftar, dan orang sudah hafal tampilannya. Membuat
     daftar aplikasi sendiri berarti menebak apa yang terpasang di
     perangkat orang lain.

TC-AP-06 | Cadangan untuk peramban tanpa papan bagi
  -> Muncul dua pilihan: Salin tautan dan Kirim lewat WhatsApp.

TC-AP-07 | Salin tautan memberi umpan balik
  -> Tombol berubah menjadi Tautan disalin selama beberapa saat.

TC-AP-08 | Peramban tanpa clipboard API tetap dapat menyalin
  -> Memakai cara lama execCommand, dan bila itu pun gagal, tautannya
     ditampilkan agar dapat disalin sendiri.

TC-AP-09 | Ajakan memuat waktu dan nomor event
  -> Misalnya "Undangan tahlil berjamaah - Kamis 27/08/2026 20:00
     (EVT-...)", sehingga penerima tahu isinya sebelum menekan tautan.

TC-AP-10 | Tiga tombol pada Event Terbatas Saya
  -> Batalkan, Hapus, dan Bagikan berdampingan pada tiap baris.

TC-AP-11 | Bagikan memakai tautan undangan
  -> https://.../undangan/{token}, bukan alamat rincian yang akan
     menolak penerima.

TC-AP-12 | Undangan habis membuat tombol nonaktif
  Event dengan undangan yang pemakaiannya sudah penuh.
  -> Tombol Bagikan nonaktif disertai keterangan.

TC-AP-13 | Konfirmasi menyebut akibatnya
  Tekan Batalkan.
  -> Menerangkan bahwa event tidak jadi dilaksanakan, peserta diberi
     tahu, tautan undangan berhenti berlaku, dan catatan pesertanya
     tetap tersimpan.

TC-AP-14 | Konfirmasi hapus membedakan diri dari batalkan
  Tekan Hapus.
  -> Menerangkan bahwa seluruhnya hilang dan tidak dapat dikembalikan,
     serta menyarankan Batalkan bila yang dimaksud hanya membatalkan
     acaranya. Dua tindakan yang akibatnya sejauh ini berbeda tidak
     boleh dikonfirmasi dengan kalimat yang mirip.

=====================================================================
AQ. KONFIRMASI SETELAH MENERIMA UNDANGAN
=====================================================================
TC-AQ-01 | Login Google menghormati tujuan tersimpan
  Tekan Ikut pada tautan undangan sebagai tamu, lalu masuk dengan
  Google.
  -> Kembali ke tautan undangan itu. Sebelumnya baris pengarahan
     selalu menuju beranda, sehingga undangannya hilang tanpa jejak
     dan pengguna tidak punya cara mengetahui bahwa ia belum
     terdaftar.

TC-AQ-02 | Tujuan hanya sekali pakai
  -> Dibersihkan setelah dipakai, agar tidak terbawa ke sesi
     berikutnya.

TC-AQ-03 | Tujuan luar ditolak
  Isi sesi dengan alamat berawalan dua garis miring.
  -> Diabaikan, dikembalikan ke beranda. Nilai sesi pun tidak
     dianggap tepercaya bila bentuknya tidak masuk akal.

TC-AQ-04 | Halaman konfirmasi tersendiri
  Terima undangan.
  -> Muncul halaman berisi tanda centang, kalimat bahwa keikutsertaan
     sudah tercatat, serta pelaksana, waktu, bacaan, nomor, dan
     jenisnya. Pesan sekilas di atas halaman rincian mudah terlewat di
     antara peta, daftar peserta, dan panel progres.

TC-AQ-05 | Menyebut jenisnya
  -> Untuk event terbatas tertulis "doa terbatas" dan "Terbatas, hanya
     pemegang undangan".

TC-AQ-06 | Tiga jalan lanjut
  -> Titipkan nama yang didoakan, Lihat rincian event, dan Daftar yang
     akan saya hadiri.

TC-AQ-07 | Halaman itu hanya berarti bila memang terdaftar
  Buka sebagai pengguna yang belum terdaftar.
  -> Dialihkan, tidak menampilkan konfirmasi palsu.