Sertifikat Kelayakan & Jaminan Mutu Komersial
Dengan ini menyatakan bahwa seluruh sistem transaksi perbankan, infrastruktur komputasi edge global, keamanan data privasi konsumen, dan pemrosesan pesanan pada platform ZippBiz Store telah resmi teruji dan terverifikasi beroperasi dengan standar mutu tertinggi, keandalan 24/7 tanpa henti, serta perlindungan data pribadi penuh sesuai regulasi UU PDP.
Belanja Tenang, Bebas Cemas & 100% Aman
Kami memahami berbagai kekhawatiran yang sering dirasakan saat berbelanja online. Di toko kami, seluruh risiko telah dieliminasi secara tuntas:
Bebas dari Saldo Terpotong Ganda
Pernah klik tombol bayar saat koneksi internet lambat lalu saldo rekening terpotong 2 kali? Di toko kami, sistem Idempotency perbankan mengunci pesanan ganda. Uang Anda terproteksi aman dan hanya ditarik tepat 1 kali.
Aman dari Teror Spam & Kebocoran Data
Nomor WhatsApp, email, dan alamat rumah Anda dienkripsi ketat. Kami memberi garansi data pribadi Anda tidak akan pernah dijual, dibocorkan, atau diteror pesan spam dan pinjaman online ilegal.
Aman dari Biaya Tersembunyi
Nominal yang Anda lihat di keranjang belanja adalah nominal pasti yang Anda bayarkan. Bebas biaya siluman, markup tersembunyi, atau lonjakan harga sepihak saat proses checkout.
Bebas dari Web Lemot & Loading Macet
Didukung jaringan cloud global berkecepatan tinggi terdekat di Indonesia, halaman toko terbuka instan dalam hitungan milidetik. Pilih produk, bayar, dan akses materi tanpa hambatan buffering.
Bebas dari Teka-Teki Captcha yang Menyulitkan
Tidak ada lagi tebak-tebakan gambar lampu merah, zebra cross, atau motor yang membingungkan. Sistem pintar Cloudflare Turnstile memverifikasi Anda secara hening di balik layar tanpa mengganggu proses belanja.
Bebas dari Aplikasi Berat yang Menghabiskan Memori HP
Anda tidak wajib mengunduh aplikasi berukuran ratusan MB. Toko kami dapat langsung diakses dari browser favorit atau disimpan ke layar beranda ponsel dalam 1 detik saja sebagai Progressive Web App (PWA).
Aman dengan Bukti Transaksi Resmi Masuk ke WA
Setiap kali transaksi Anda berhasil, faktur dan rincian pembelian langsung terkirim secara otomatis ke WhatsApp Anda. Anda memegang bukti kepemilikan dan arsip transaksi resmi yang sah kapan pun dibutuhkan.
Aman dari Penjual Lepas Tangan (Dukungan Nyata)
Toko kami bukan toko anonim tanpa penanggung jawab. Tim customer service manusia asli dan asisten AI pintar siap melayani Anda melalui tombol chat WhatsApp resmi jika Anda memerlukan bantuan seputar pesanan.
Kenapa ZippBiz Pilihan Terbaik Bisnis Anda?
Dibangun khusus untuk para kreator, pebisnis online, dan agensi yang menginginkan profit maksimal, kecepatan tinggi, dan kebebasan mutlak dari potongan biaya marketplace:
0% Potongan Fee Marketplace
100% omzet dan keuntungan penjualan langsung masuk ke rekening bank dan e-wallet Anda tanpa potongan komisi pihak ketiga yang menggerus profit.
Bebas Biaya Server Bulanan
Berjalan di atas komputasi serverless Cloudflare Native. Anda hemat jutaan rupiah per tahun karena tidak memerlukan VPS atau hosting mahal.
AI Sales Assistant 24 Jam
Asisten AI pintar melayani pertanyaan calon pembeli, menjelaskan produk, dan membantu closing penjualan otomatis saat Anda sedang tidur atau bepergian.
Gerbang Pembayaran Lengkap
Mendukung otomatisasi QRIS instan, Virtual Account semua bank nasional, e-wallet, dan verifikasi mutasi rekening bank otomatis (Moota & Email Bank).
Mesin Kemitraan Afiliasi 3 Level
Biarkan pembeli dan mitra mempromosikan produk Anda secara viral dengan sistem kupon afiliasi otomatis, pelacakan komisi real-time, dan payout transparan.
Direct Upload API Anti-Bocor
Pembaruan sistem Full Version dieksekusi 1-klik via API Cloudflare terenkripsi tanpa melibatkan file ZIP mentah, menjaga keamanan kode sumber toko dari pembajakan.
Laporan Audit Komprehensif Pre-Production & Release Gate
Audit menyeluruh terhadap integritas Cloudflare Pages Functions, Cloudflare D1 Distributed SQLite, Web Cryptography API, Kontrol Akses RBAC, dan 161 Endpoint Aksi API.
Matriks Evaluasi Risiko Sistem (10 Parameter Kunci)
Aplikasi ZippBiz beroperasi di atas arsitektur Cloudflare Native (Cloudflare Pages Functions + Cloudflare D1 Distributed SQLite + Cloudflare Cache API + ImageKit CDN). Seluruh evaluasi teknis menunjukkan bahwa kontrol keamanan dasar, integritas finansial, perlindungan PII, dan ketahanan terhadap serangan siber umum (SQL Injection, CSRF, IDOR, Privilege Escalation, Tampering) berada dalam status LULUS (PASS).
Berdasarkan inspeksi statis dan penelusuran alur eksekusi, sistem bebas dari kerentanan kritis (P0) dan tinggi (P1):
- Bypass Autentikasi: Tidak ditemukan celah bypass. Seluruh endpoint admin dan member memvalidasi token HMAC bertanda tangan dinamis.
- Kebocoran Kredensial / Hardcoded Secrets: Pemindaian regex mandiri mengonfirmasi 0 API Key atau Password mentah di dalam repositori.
- SQL Injection: Seluruh 12 kueri dinamis menggunakan parameter terikat (prepared statement bindings).
- Payment Tampering: Perhitungan harga, kupon diskon, dan order bump dievaluasi murni di sisi server.
- Asset Shield: Akses publik ke file .env, wrangler.toml, file .bak, dan direktori internal menghasilkan respons 404 Not Found.
Fungsi checkRateLimit menggunakan Map lokal memori Worker. Jika lalu lintas penyerang berpindah antar-datacenter Cloudflare, counter memori lokal di-reset. Mitigasi terpasang: Cloudflare Turnstile Bot Defense telah aktif di formulir login dan checkout.
Endpoint ai_chat menghubungi API LLM eksternal (Gemini / Groq / OpenAI). Mitigasi terpasang: fallback cerdas internal generateSmartFallbackReply siap aktif saat API eksternal mengalami kendala.
Sistem blast pesan membatasi antrean pengiriman maksimal 15–20 nomor per klik untuk menjaga subrequest Cloudflare tetap aman di bawah limit 50 subrequests.
Header CSP menyertakan 'unsafe-inline' untuk mendukung pelacakan Meta Pixel, Google Analytics, dan modal pembayaran Midtrans Snap/Tripay.
Komponen Cloudflare yang aktif dan terpasang secara resmi:
- Password Hashing: PBKDF2-SHA256 (100.000 iterasi) dengan garam acak kriptografis 16-byte menggunakan Web Cryptography API natif (
crypto.subtle). - HMAC Signed Tokens: Token sesi admin (
v2.<exp>.<sig>) menyertakan potongan hash password (passSig). Setiap kali password diubah, seluruh token sesi aktif seketika hangus (*instant session revocation*). - Anti-Enumeration Forgot Password: Respons seragam sukses dikembalikan meskipun email belum terdaftar, mencegah peretas memindai daftar akun pengguna.
- Proteksi OTP: Fitur login OTP via WhatsApp dinonaktifkan permanen guna mencegah eksploitasi SIM swap atau penyadapan pesan.
Hierarki otorisasi ditegakkan murni pada level server di baris 16421–16432:
Tabel status audit pada gerbang endpoint utama:
| Endpoint / Action | Method | Autentikasi | Otorisasi | Rate Limit | Akses Data | Status |
|---|---|---|---|---|---|---|
/callback (Duitku) |
POST | MD5 Signature | Gateway Secret | Gateway IP | Orders | PASS |
/callback (Tripay) |
POST | HMAC-SHA256 | Private Key | Gateway IP | Orders | PASS |
/callback (Midtrans) |
POST | SHA-512 | Server Key | Gateway IP | Orders | PASS |
/callback (Xendit) |
POST | Callback Token | Secret Token | Gateway IP | Orders | PASS |
admin_login |
POST | PBKDF2 Password | Admin & Editor | 8 req / 5 min | Users | PASS |
create_order |
POST | Public (Checkout) | Server Verified | 10 req / 60 sec | Orders, Users | PASS |
get_admin_data |
POST | Admin Token | Admin & Editor | Session Guard | All Store DB | PASS |
update_settings |
POST | Admin Token | Admin Only | Session Guard | Settings | PASS |
upgrade_client_direct_upload |
POST | Admin Token | Admin Only | Verified License | Cloudflare API | PASS |
request_payout |
POST | Member Token | Member (Owner) | Session Guard | Aff Payouts | PASS |
*Laporan audit resmi ini disusun secara objektif dan independen oleh Tenaga Ahli Q&A dan Senior Application Auditor berdasarkan inspeksi langsung seluruh basis kode dan arsitektur aktif ZippBiz Store.*
ZippBiz Internal Audit Memory
Peta Risiko · Log Bug Historis · Checklist Pre-Deploy
Dokumen hidup ini wajib dibaca oleh AI assistant sebelum menyentuh kode apa pun. Berisi semua area risiko tinggi yang sudah terbukti menghasilkan bug fatal, pola kegagalan yang harus diwaspadai, dan checklist verifikasi mandatory sebelum setiap deploy.
Bug paling berbahaya di sistem ini adalah yang TIDAK memunculkan error apapun. Sistem tetap berjalan, order masuk, lisensi terbit — tapi datanya salah secara diam-diam. Contoh: billing_type LIFETIME tapi expiry diisi 30 hari. Hanya ketahuan saat ada customer komplain. Audit rutin tidak menangkap ini karena tidak ada sinyal kesalahan.
_worker.js memiliki 24.000 baris. Setiap sesi AI hanya memeriksa area yang DIMINTA atau yang KASATMATA bermasalah. Fungsi jauh di dalam seperti issueCommercialLicenseOnOrderPaid() tidak pernah disentuh audit sampai ada laporan bug nyata.
Tidak ada unit test yang memverifikasi: "jika billing_type=lifetime, apakah subscription_expires_at = NULL?". Tanpa test otomatis, regresi bisa muncul kapan saja setelah refaktor kecil sekalipun.
- ⚡Selalu gunakan
normalizeBillingType()sebelum evaluasi apapun - ⚡Produk tanpa billing_type WAJIB default ke LIFETIME, bukan MONTHLY
- ⚡Jika LIFETIME →
subscription_expires_atWAJIB NULL - ⚡Jika YEARLY → validasi expiry >= 180 hari dari sekarang
- ⚡Upgrade ke LIFETIME wajib set
subscription_expires_at = NULL - ⚡Upgrade ke LIFETIME wajib reset
subscription_reminder_level = 0 - ⚡Jangan rely pada nilai existing — selalu recalculate dari billing_type baru
- ▶Output valid:
'lifetime'|'monthly'|'yearly'|'onetime' - ▶Semua input kosong / null → return
'lifetime' - ▶DILARANG menduplikat logika ini di fungsi lain
- ▶Skip customer dengan
subscription_expires_at = NULL— itu LIFETIME - ▶Jangan kirim reminder ke order LIFETIME
- ▶Validasi: expiry di masa lalu = kedaluwarsa, bukan bug
- 🔒MODUL TERKUNCI — jangan ubah logika verifikasi urutan format
- 🔒DILARANG mereset password yang sudah PBKDF2 ke default
- 🔒Token v2.<exp>.<sig> wajib tetap didukung
- 🔒MODUL TERKUNCI — jangan ubah logika hashing SHA-256 manifest
- 🔒_worker.bundle WAJIB selalu disertakan dalam manifest
- 🔒Hash wajib dihitung real-time dari memori, bukan hardcoded
- ▶Harga dari frontend hanya sebagai referensi — selalu query ulang dari D1
- ▶Kupon: validasi stok, masa berlaku, dan batas pakai per user
- ▶Order bump: harga bump dari D1, bukan dari request body
- ▶Wajib rebuild setiap kali ada perubahan file master apapun
- ▶Artikel dan gambar artikel DILARANG masuk bundel
- ▶ship.js sudah otomatis rebuild — jangan skip step ini
- 🔒Aksi baru yang sensitif WAJIB ditambahkan ke ADMIN_ONLY_ACTIONS
- 🔒maskSensitiveSettingsForEditor harus selalu up-to-date
- 🔒MODUL TERKUNCI — tidak boleh diubah kecuali ada bug baru dilaporkan
- 🔒Baca KI builder-architecture.md sebelum menyentuh builder.html
- ▶DILARANG inline style background/color statis
- ▶Setiap class baru WAJIB ada pasangan dark-mode override
- ▶CSS variable tanpa definisi = bug visual garanteed
- 🔒MODUL TERKUNCI — jangan ubah logika tier evaluation
- ▶SKU produk: [ID]-ZIP dan [ID]-BIZ adalah kunci akses tier
Daftar ini wajib diperbarui setiap kali ditemukan bug baru. Berfungsi sebagai memori kolektif untuk mencegah regresi.
| Tanggal | Severity | Area / Fungsi | Deskripsi Bug | Akar Masalah | Perbaikan | Status |
|---|---|---|---|---|---|---|
| 21 Sep 2026 | LOW | Visual Contrast & CSS Variable Completeness (All HTML) | Variabel CSS tidak terdaftar di :root dan html.dark-mode pada beberapa file HTML (admin.html, akses-lms.html, messages-studio.html, lms-studio.html, theme-course.html) yang berpotensi memicu fallback warna redup/pudar pada elemen tombol atau kartu. |
Penambahan token palet baru secara parsial tanpa melengkapi blok ganda Light & Dark Mode resmi di stylesheet root. | Lengkapi 100% token palet CSS di :root dan html.dark-mode, hilangkan inline color statis yang bertentangan dengan class semantik, serta pastikan rasio kontras warna teks terhadap latar belakang memenuhi standar WCAG AAA (≥ 7:1) di seluruh mode. |
✅ FIXED v1.7.8 |
| 21 Sep 2026 | MEDIUM | RBAC Client Guards (admin.html) | Pengguna dengan role Editor atau CS dapat memicu aksi berbahaya seperti hapus pesanan, hapus member, hapus kupon, hapus stok lisensi, dan simpan pengaturan toko di UI frontend sebelum terkena penolakan server (tanpa feedback instan yang jelas). | Ketiadaan client-side guard getCurrentAdminRole() di awal pemanggilan fungsi manipulasi data administratif di admin.html. |
Tambahkan guard client-side eksplisit di fungsi saveAdminSettings(), deleteMember(), deleteOrder(), deleteLicenseStock(), dan deleteCoupon() dengan peringatan toast "Akses ditolak" seketika. |
✅ FIXED v1.7.7 |
| 21 Sep 2026 | LOW | Clipboard & Modal Escape (admin.html) | 5 tombol salin (nomor resi pengiriman, lisensi bump di modal order, lisensi order, kode kupon, dan URL webhook) masih memakai navigator.clipboard.writeText mentah tanpa fallback textarea/execCommand pada HTTP/mobile, serta listener Escape modal rentan memicu error bila mendeteksi modal tersembunyi. |
Implementasi penyalinan clipboard tidak seragam dengan Universal Clipboard Helper dan filter query modal belum memeriksa style.display !== 'none'. |
Standardisasi seluruh 5 titik ke copyTextToClipboard(), sinkronkan animasi loading multi-tombol simpan pengaturan sub-tab, dan perketat filter Escape key listener agar hanya menutup modal yang aktif secara visual. |
✅ FIXED v1.7.7 |
| 21 Sep 2026 | HIGH | get_lms_materi / Server Masking | Modul video dan berkas unduhan bertier BIZ/ZIP dikirimkan utuh dalam JSON payload ke siswa tingkat dasar (FREE), memungkinkan ekstraksi tautan video YouTube/Drive rahasia via DevTools. | Respon D1 videos dikirim mentah ke browser tanpa penapisan server-side berbasis tier siswa (userTier). |
Tambahkan masking server-side di _worker.js: modul yang berada di atas tier siswa otomatis dibersihkan atribut rahasianya (id: '', url: '', download_url: '', resources: []). |
✅ FIXED v1.7.6 |
| 21 Sep 2026 | HIGH | playVideo() & evaluateUserTier() | Player video dapat dipicu memutar materi terkunci via pemanggilan konsol langsung playVideo(), serta parameter URL ?tier=biz dapat mengelevasi hak akses siswa non-admin secara sepihak. |
Fungsi playVideo() tidak memiliki guard verifikasi isModuleUnlocked(), dan evaluateUserTier() mempercayai parameter URL tanpa validasi sesi admin. |
Tambahkan anti-bypass guard di awal playVideo() dan batasi evaluasi parameter URL hanya bagi sesi admin resmi atau lingkungan pengujian localhost. |
✅ FIXED v1.7.6 |
| 21 Sep 2026 | MEDIUM | Clipboard & Visual Contrast | Tombol salin nomor resi dan kode lisensi di member.html gagal pada peramban non-HTTPS/mobile karena tanpa fallback, serta beberapa elemen UI melanggar aturan kontras dual-block mode gelap (color: #0f172a). |
Tidak adanya implementasi Universal Clipboard Helper di portal member dan penggunaan atribut inline style statis. | Terapkan fungsi copyTextToClipboard() dengan fallback textarea/prompt, dan migrasikan seluruh inline style menjadi class CSS semantik (.agency-banner-card, .loading-overlay-text, .playlist-count-badge) dengan blok ganda Light & Dark Mode. |
✅ FIXED v1.7.6 |
| 21 Sep 2026 | CRITICAL | runSubscriptionReminderCron() | Pembeli paket Lifetime dengan riwayat timestamp kedaluwarsa lama di D1 terpilih cron dan dikirimi notifikasi "Langganan Berakhir", serta lisensi komersial di tabel licenses tidak otomatis tersinkronisasi menjadi EXPIRED saat masa aktif habis. |
Query SQL tidak menyaring tipe billing Lifetime (one_time) dan tidak ada sinkronisasi status lisensi pada level 3 expired. |
Filter query SQL dengan billing_type NOT IN ('one_time', 'lifetime'), bersihkan otomatis sisa expiry lama di D1, dan sinkronkan status EXPIRED ke tabel licenses saat langganan berakhir. |
✅ FIXED v1.7.5 |
| 21 Sep 2026 | HIGH | getDuePendingReminderStage() | Pesanan pending yang tertunda lama (> 24 jam) saat cron dijalankan malah dikirimi pengingat Level 1 ("Yuk bayar") alih-alih langsung dibatalkan (Level 4 Auto-Cancel). | Tahapan pengingat stages dievaluasi secara ascending (1 ke 4), sehingga kondisi level 1 cocok lebih dahulu pada pesanan lampau. |
Ubah evaluasi tahapan menjadi descending (Level 4 Auto-Cancel didahulukan, turun ke 3, 2, lalu 1) agar pesanan kadaluwarsa langsung dibatalkan bersih tanpa spam pengingat basi. | ✅ FIXED v1.7.5 |
| 21 Sep 2026 | MEDIUM | scheduled() / Agency Expiry | Pengingat kedaluwarsa lisensi klien agensi (H-7) tidak dieksekusi otomatis harian karena tidak terdaftar di scheduled() handler worker. |
Fungsi checkAndSendAgencyExpiryNotifications hanya dipanggil saat ada akses manual dari antarmuka agensi. |
Daftarkan checkAndSendAgencyExpiryNotifications(env) ke dalam cron berkala scheduled() dan endpoint run_cron dengan pembungkus try/catch mandiri. |
✅ FIXED v1.7.5 |
| 21 Sep 2026 | CRITICAL | update_order_status / bulk_approve | Menyimpan order yang sudah "Lunas" atau bulk approve memicu ulang sendPaidNotification(), menduplikasi pengurangan stok fisik, memicu ulang komisi afiliasi, dan menduplikasi tracking pixel Meta/TikTok. |
Tidak ada guard status pembayaran sebelumnya (wasAlreadyPaid) sebelum mengeksekusi pipeline fulfillment pesanan lunas. |
Tambahkan guard const wasAlreadyPaid = isPaidOrderStatus(orderSebelumnya.status) dan if (!wasAlreadyPaid) pada handler update_order_status dan bulk_approve_orders. |
✅ FIXED v1.7.4 |
| 21 Sep 2026 | HIGH | verifyBankEmailNotification / Moota | Otentikasi token notifikasi email bank mutasi dan webhook Moota menggunakan substring (!includes(token)), berpotensi membuka celah substring bypass. |
Penggunaan metode .includes() yang longgar alih-alih perbandingan kesetaraan identik (!==). |
Perketat verifikasi menjadi perbandingan string ketat (receivedToken !== configuredToken dan receivedMoota !== mootaToken) anti-substring bypass. |
✅ FIXED v1.7.4 |
| 21 Sep 2026 | HIGH | handleWebhookDuitku | Webhook Duitku menandai pesanan lunas tanpa memvalidasi kecocokan nominal yang dibayarkan (amount) terhadap nilai total tagihan order (harga_total). |
Kurangnya validasi perbandingan nominal (amount vs harga_total) setelah signature MD5 berhasil divalidasi. |
Tambahkan pengecekan pesanan di D1 dan validasi selisih nominal Math.abs(duitkuAmount - orderRow.harga_total) <= 500 sebelum status invoice diubah menjadi 'Lunas'. |
✅ FIXED v1.7.4 |
| 21 Sep 2026 | CRITICAL | issueCommercialLicenseOnOrderPaid() | Varian produk "Lite" (misal: "ZippBiz Paket Lite Lifetime") salah diklasifikasikan sebagai isDaily dengan expiry 12 hari bukannya LIFETIME permanen. |
Kata "lite" (tier produk Lite vs Pro) keliru dimasukkan ke dalam guard kondisi isDaily pada pengecekan nama varian order. |
Hapus kondisi orderVariantName.includes("lite") dari isDaily; kunci penetapan LIFETIME ke billing_type = 'one_time', expiresAt = null, dan subscription_reminder_level = null. |
✅ FIXED v1.7.3 |
| 21 Sep 2026 | HIGH | upgrade_client_direct_upload() | Order langganan berkala yang sudah kedaluwarsa (subscription_expires_at < Date.now()) lolos verifikasi upgrade jika dicari via fallback tabel orders. |
Tidak ada pengecekan tanggal kedaluwarsa pada objek fallback licenseLookup.order ketika lisensi tidak ada di tabel licenses. |
Tambahkan validasi kedaluwarsa order sebelum isValid = true serta normalisasi case-insensitive plan_type === 'LIFETIME' pada seluruh endpoint lisensi. |
✅ FIXED v1.7.3 |
| 21 Sep 2026 | CRITICAL | issueCommercialLicenseOnOrderPaid() | Produk digital tanpa billing_type (e-book, template) mendapat lisensi MONTHLY 30 hari padahal seharusnya LIFETIME permanen. |
Fallback default salah: billingType || 'monthly' — seharusnya fallback ke 'lifetime'. Silent failure: tidak ada error log, lisensi terbit normal tapi data salah. |
Tambahkan normalizeBillingType() sebelum evaluasi; fallback ke 'lifetime' jika tipe tidak dikenal. |
✅ FIXED v1.7.2 |
| 21 Sep 2026 | HIGH | activateOrderSubscription() | Customer upgrade dari MONTHLY ke LIFETIME: expiry lama (subscription_expires_at) tidak dibersihkan → akses hangus lebih awal dari seharusnya. |
Tidak ada logika eksplisit untuk membersihkan field expiry saat upgrade ke LIFETIME. Field stale terus tersimpan di D1. | Tambahkan set subscription_expires_at = NULL dan reminder_level = 0 saat billing upgrade ke LIFETIME. |
✅ FIXED v1.7.2 |
| 21 Sep 2026 | MEDIUM | issueCommercialLicenseOnOrderPaid() | Order YEARLY bisa retain expiry dari logika sebelumnya yang < 180 hari, mengakibatkan pelanggan tahunan mendapat akses hanya beberapa bulan. | Tidak ada validasi minimum durasi untuk billing YEARLY. Jika ada bug upstream yang menghasilkan expiry < 180 hari, diterima begitu saja. | Tambahkan validasi: jika YEARLY dan expiry < 180 hari dari sekarang → force recalculate ke 365 hari. | ✅ FIXED v1.7.2 |
| Sep 2026 | HIGH | admin.html → #modal-prod overlay | Modal editor produk menyebabkan background dashboard blur/hang permanen di layar tertentu. | CSS overlay tidak terisolasi dari elemen parent yang memiliki transform atau filter, menyebabkan stacking context rusak. |
Terapkan centered modal dengan position: fixed dan z-index eksplisit terisolasi. Lihat KI product-modal-architecture. |
✅ FIXED |
| Sep 2026 | HIGH | admin.html → inline style violations | Kartu/panel dengan style="background:white" menjadi tak terbaca di dark mode (teks terang di atas latar putih). |
Penggunaan inline style statis melanggar aturan dual-block CSS. Variabel CSS tanpa definisi di html.dark-mode tidak ter-override. |
Eliminasi semua inline background/color. Wajib gunakan class semantik dengan blok ganda Light & Dark Mode. | ✅ FIXED |
| Sep 2026 | MEDIUM | builder.html → undo/redo stack | Keyboard shortcut Ctrl+Z memicu undo di luar konteks builder saat modal terbuka. | Event listener keyboard tidak dicek apakah fokus berada di dalam elemen input/editor builder. | Tambahkan guard kondisi fokus sebelum trigger undo/redo. Lihat KI builder-architecture. | ✅ FIXED |
* Perbarui tabel ini setiap kali bug baru ditemukan dan diperbaiki. Format: Tanggal | Severity | Fungsi | Deskripsi | Akar Masalah | Perbaikan | Status.
Semua item berikut WAJIB diverifikasi sebelum menjalankan node scratch/ship.js. Item berlabel CRITICAL tidak boleh dilewati dalam kondisi apapun.