Daily Taqwa
Tamper-resistant prayer attendance system for ~2,000 OIKN government employees at Masjid Negara IKN
Fullstack Developer
Apr – Jun 2026
Di halaman ini
Permasalahan
OIKN (Otorita Ibu Kota Nusantara) membutuhkan cara berbasis bukti untuk mendorong dan memverifikasi kehadiran shalat ~2.000 pegawai di Masjid Negara IKN. Absensi kertas bisa diisi mundur. Check-in digital sederhana bisa dipalsukan dari luar masjid. Pimpinan HR juga membutuhkan visibilitas tren kehadiran lintas direktorat, bukan sekadar daftar kepatuhan per individu.
Taruhannya lebih tinggi dari sistem absensi biasa: waktu shalat singkat, check-in serentak melonjak dalam beberapa menit di sekitar adzan, dan persyaratan lokasi harus benar-benar tahan terhadap pemalsuan — bukan sekadar "sulit dipalsukan," tetapi sulit dipalsukan secara sengaja oleh orang yang memang berniat melakukannya.
Pendekatan
Satu backend, dua client — dan hanya satu yang boleh check-in
GPS dari browser tidak bisa dipercaya. Pembacaan navigator.geolocation tidak memberi cara untuk membuktikan bahwa ia berasal dari perangkat sungguhan, dan aplikasi "fake GPS" gratis atau override devtools dapat mengalahkan geofence berbasis web sebaik apa pun validasi sisi server. Maka arsitektur produksi sengaja dipisah. Aplikasi mobile native adalah satu-satunya client yang berwenang mengirim check-in — ia melakukan penangkapan liveness dan pembacaan GPS dengan deteksi mock-location di level OS, sesuatu yang secara fundamental tidak bisa dilakukan website. Portal web Next.js tidak pernah mengekspos check-in langsung ke pengguna akhir; ia menyajikan jadwal shalat, leaderboard tergamifikasi, profil, catatan rilis, dan panel admin lengkap. Keduanya berbicara ke Django REST API yang sama, yang menjadi satu-satunya sumber kebenaran untuk setiap aturan.
Server sebagai otoritas waktu dan identitas
Waktu shalat dihitung di sisi server menggunakan library Python praytimes, di-cache di Redis, dan divalidasi ulang pada saat setiap permintaan check-in. Client tidak pernah mengirimkan timestamp yang mempengaruhi validasi. Detail penting: IKN beroperasi pada WITA (UTC+8), sehingga check-in Subuh pukul 05:00 WITA menjadi 21:00 UTC di hari kalender sebelumnya — helper get_wita_date() diterapkan secara konsisten pada semua constraint database yang menggunakan kunci tanggal untuk mencegah bug kolisi yang senyap.
Layanan check-in atomik
Seluruh logika check-in berjalan dalam satu blok @transaction.atomic: konsumsi nonce, validasi jendela waktu shalat, pemeriksaan geofence GPS (Haversine dengan radius yang dapat dikonfigurasi), pemeriksaan kecepatan antar check-in, validasi liveness wajah, dan pembuatan catatan absensi. Constraint UNIQUE(user_id, date, prayer) di level database adalah penjaga keras terhadap race condition — layanan menangkap IntegrityError dan mengembalikan respons "sudah check-in" yang bersih. Pembaruan agregat (harian, bulanan, tahunan, dan per-direktorat) terjadi dalam transaksi yang sama, sehingga tidak pernah menyimpang dari catatan absensi. Nonce sekali pakai dengan TTL 2 menit, diterbitkan tepat sebelum check-in, memblokir replay payload valid dari perangkat lain atau jendela waktu yang berbeda.
SSO dual-path melalui satu Keycloak
Kedua client terautentikasi melalui instance Keycloak OIKN, tetapi dengan dua jenis grant berbeda dari satu codebase. Portal web menggunakan alur redirect PKCE standar via mozilla-django-oidc. Mobile menggunakan Direct Access Grant — mengirimkan kredensial ke Keycloak, menerima id_token, lalu menukarnya di endpoint backend untuk token SimpleJWT. Klaim Keycloak (NIP, unit_kerja, gender) dipetakan ke model user lokal dengan resolusi eselon fuzzy, termasuk mengoreksi NIP yang datang dengan format float dari beberapa sistem HR dan menerima nomor non-standar PPPK/militer.
Leaderboard, riwayat, dan realita HR
Lapisan gamifikasi memiliki empat varian leaderboard: bulanan individual (terpisah pria/wanita), tahunan, khusus Subuh (shalat yang paling sulit dihadiri), dan agregat per-kedeputian — tiga besar mendapat podium, dan peringkat pengguna saat ini disematkan di bawah jika ia berada di luar sepuluh besar. Grid riwayat bulanan memberi kode warna pada kelima slot shalat harian, dengan detail saat diketuk menampilkan foto, timestamp, dan poin. Di sekitar inti ini, peluncuran memunculkan kebutuhan yang tidak tercakup spesifikasi awal: karena Keycloak tidak menyediakan klaim gender, pengguna dapat mengoreksi sendiri gender dan direktorat dari profil mereka — dan sinkronisasi OIDC belajar untuk berhenti menimpa koreksi manual itu pada login berikutnya. Perintah backfill CSV yang mengimpor catatan kertas sebelumnya dibungkus dalam halaman unggah web admin sehingga HR tidak pernah butuh akses shell ke VM, dan timestamp login web/mobile dilacak terpisah agar admin dapat memantau adopsi aplikasi mobile.
Hasil
Daily Taqwa telah dirilis ke produksi di infrastruktur GCP internal OIKN, dengan CI mendorong image Docker ke GHCR pada setiap merge ke main. Aplikasi mobile native berjalan langsung dan menjadi satu-satunya kanal untuk presensi sesungguhnya; portal web di domain internalnya menjalankan permukaan admin dan peringkat terhadap API yang sama. Sistem bertahan di bawah lonjakan Dzuhur puncak — hingga 500 check-in serentak dalam lima menit — tanpa race condition, berkat row-level locking dan constraint unik di level database. Cakupan backend tumbuh jauh melampaui PRD awal sepanjang jalan: SSO Keycloak menggantikan auth lokal saja, pencocokan wajah sengaja diturunkan menjadi liveness-only untuk Phase 1 demi menghindari build dlib yang berat, dan lapisan perkakas HR — unggah backfill web, layanan mandiri profil, aktivitas login terpisah per platform, halaman catatan rilis in-app — ditambahkan untuk merespons kebutuhan peluncuran yang nyata. Pencocokan wajah penuh di sisi server tetap menjadi item utama Phase 2. Repositori bersifat privat, di bawah organisasi OIKN.
- ~2,000
- ~500
- 9
- 85
Punya proyek serupa?
Jika Anda butuh sistem yang dibangun dengan ketelitian yang sama — scope jelas, eksekusi solid — mari bicara.
Mulai proyek