Keutuhan Aplikasi Konsep dan Praktik dalam Upaya menciptakan aplikasi Anti Virus dengan kode coding oleh Junirullah.docx
1. Membangun dan Mempertahankan Keutuhan
Aplikasi dengan Baik dan Benar
Oleh: Junirullah
I. Pendahuluan: Memahami Keutuhan Aplikasi di Era Digital
Dalam lanskap digital yang terus berkembang, perangkat lunak telah menjadi tulang
punggung hampir setiap aspek kehidupan modern. Mulai dari aplikasi seluler yang
digunakan sehari-hari hingga sistem informasi korporat yang kompleks, keandalan
dan fungsionalitas aplikasi sangat bergantung pada integritasnya. Laporan ini akan
menguraikan definisi fundamental dari keutuhan aplikasi dan menyoroti signifikansinya
yang krusial dalam konteks bisnis dan keamanan siber.
Definisi dan Konsep Dasar Keutuhan Aplikasi
Pengembangan perangkat lunak merupakan sebuah proses yang kompleks dan
berlapis, mencakup tahapan perencanaan, desain, pengkodean, pengujian, dan
pemeliharaan.1
Proses ini bertujuan untuk menciptakan solusi yang tidak hanya
memenuhi kebutuhan pengguna tetapi juga meningkatkan efisiensi, produktivitas, dan
mendorong inovasi teknologi.2
Dalam kerangka proses inilah konsep keutuhan aplikasi
harus dipahami secara menyeluruh.
Secara fundamental, keutuhan dalam komputasi merujuk pada jaminan bahwa data
tetap akurat, konsisten, dan tidak diubah sepanjang siklus hidupnya.3
Ini adalah prinsip
krusial yang memastikan informasi dapat diandalkan dan dipercaya, mulai dari saat
data dibuat, disimpan, hingga ditransmisikan.3
Dalam keamanan informasi, integritas
adalah salah satu dari tiga pilar utama dalam CIA Triad (Confidentiality, Integrity,
Availability), yang mendasari semua upaya keamanan siber.4
Memperluas definisi integritas data, keutuhan aplikasi mencakup keandalan
fungsionalitas, konsistensi logika, dan ketahanan terhadap modifikasi tidak sah, baik
yang disengaja maupun tidak disengaja.4
Ini berarti aplikasi harus berfungsi persis
seperti yang dirancang, tanpa kerusakan, perilaku tak terduga, atau kompromi yang
dapat memengaruhi operasionalnya.5
Keamanan aplikasi secara spesifik didefinisikan
sebagai upaya terkoordinasi untuk memperkuat perlindungan aplikasi dari manipulasi
tidak sah selama seluruh tahap siklus hidupnya, dari perancangan hingga pengujian.6
Penting untuk memahami bahwa keutuhan aplikasi merupakan atribut kualitas yang
lebih luas daripada sekadar integritas data. Meskipun integritas data memastikan
keakuratan dan konsistensi data yang disimpan atau ditransmisikan, keutuhan aplikasi
mencakup kebenaran fungsional dan perilaku sistem secara keseluruhan. Jika kode
aplikasi diubah secara tidak sah, atau logikanya cacat, meskipun data yang diproses
mungkin secara individual "akurat," keutuhan aplikasi secara keseluruhan akan
terganggu karena dapat menghasilkan output yang salah, memproses informasi
dengan cara yang tidak benar, atau bahkan dieksploitasi oleh pihak tidak bertanggung
2. jawab. Oleh karena itu, pencapaian keutuhan aplikasi memerlukan pendekatan multi-
dimensi yang mencakup kualitas kode, kebenaran fungsional, dan langkah-langkah
keamanan yang ketat. Ini adalah prasyarat untuk aplikasi yang dapat diandalkan dan
dipercaya.
Pentingnya Keutuhan Aplikasi dalam Konteks Bisnis dan Keamanan Siber
Dampak bisnis dari keutuhan aplikasi sangatlah fundamental. Aplikasi dan sistem yang
memiliki keutuhan tinggi dan berfungsi dengan benar secara signifikan dapat
meningkatkan efisiensi operasional, mengoptimalkan proses bisnis, menghemat waktu
dan sumber daya, serta memfasilitasi pengambilan keputusan yang lebih baik.2
Aplikasi yang andal dan konsisten memungkinkan organisasi untuk beroperasi dengan
lancar, mengurangi hambatan, dan memanfaatkan data secara maksimal untuk
strategi bisnis. Sebaliknya, setiap kompromi terhadap keutuhan aplikasi dapat
menyebabkan penundaan operasional yang parah, peningkatan biaya perbaikan yang
substansial, dan kerugian bisnis yang signifikan.8
Misalnya, kesalahan input data yang
tidak divalidasi dapat menyebar ke seluruh sistem, merusak laporan, dan
menyebabkan keputusan bisnis yang keliru, yang pada akhirnya memakan waktu dan
biaya besar untuk diperbaiki.
Selain itu, keutuhan adalah pilar keamanan siber yang tak tergantikan.4
Pelanggaran
integritas dapat mengakibatkan konsekuensi serius, termasuk pencurian, korupsi, atau
penyelundupan data.3
Hal ini dapat berujung pada kebocoran kekayaan intelektual,
terungkapnya informasi pribadi pelanggan dan karyawan, dan bahkan hilangnya dana
perusahaan.10
Keutuhan aplikasi bukan sekadar daftar periksa teknis, melainkan keharusan bisnis
yang kritis. Ketika keutuhan aplikasi terganggu, kemampuannya untuk memenuhi janji
(seperti efisiensi dan produktivitas) akan terpengaruh secara langsung, dan
kepercayaan pengguna atau pemangku kepentingan akan terkikis. Jika data tidak
dapat diandalkan atau fungsionalitas tidak dapat diprediksi, bisnis tidak dapat
beroperasi secara efektif. Hal ini pada akhirnya menyebabkan kerugian finansial yang
signifikan, masalah hukum akibat ketidakpatuhan, dan kerusakan reputasi yang parah.
Oleh karena itu, keutuhan merupakan persyaratan fundamental untuk operasi digital
yang berkelanjutan dan sukses, karena secara langsung mendukung kepercayaan,
kepatuhan regulasi, dan keberlanjutan jangka panjang dari setiap layanan atau produk
digital.
II. Membangun Keutuhan Sejak Awal: Peran Siklus Hidup
Pengembangan Perangkat Lunak (SDLC)
Mencapai keutuhan aplikasi bukanlah upaya pasca-produksi yang dapat ditambahkan
di akhir, melainkan harus diintegrasikan secara intrinsik ke dalam setiap fase Siklus
Hidup Pengembangan Perangkat Lunak (SDLC). Pendekatan proaktif ini memastikan
bahwa keutuhan dibangun ke dalam arsitektur dan kode inti aplikasi sejak awal,
meminimalkan risiko dan biaya perbaikan di kemudian hari.
3. Integrasi Keutuhan dalam Setiap Tahapan SDLC
Tujuan utama dari SDLC adalah untuk mengurangi risiko proyek secara signifikan dan
memastikan kualitas perangkat lunak yang tinggi.11
Hal ini dicapai dengan membagi
proses pengembangan menjadi tahapan-tahapan yang jelas dan terstruktur,
memungkinkan kontrol yang lebih baik, manajemen risiko yang efektif, dan hasil yang
lebih dapat diprediksi.11
Setiap fase dalam SDLC memiliki kontribusi kritis terhadap keutuhan aplikasi:
● Perencanaan (Planning): Tahap awal ini melibatkan perumusan tujuan yang jelas
dan spesifik, identifikasi sumber daya yang diperlukan, penyusunan jadwal rinci,
dan analisis menyeluruh terhadap potensi risiko.11
Perencanaan yang matang di
fase ini sangat penting untuk memastikan bahwa setiap langkah pengembangan
dapat dijalankan dengan efisien dan sesuai dengan kebutuhan yang telah
ditetapkan, termasuk kebutuhan integritas dan keamanan.
● Analisis Kebutuhan (Requirement Analysis): Pada fase ini, tujuan dan hasil
yang ingin dicapai dari pengembangan perangkat lunak dirumuskan secara rinci.
Berbagai pemangku kepentingan dilibatkan untuk mengumpulkan dan
mengevaluasi semua kebutuhan, baik fungsional maupun non-fungsional. Hasil
analisis ini didokumentasikan dalam Software Requirements Specification (SRS),
yang berfungsi sebagai acuan utama dan memastikan pemahaman yang sama
tentang cakupan, fitur, dan kinerja perangkat lunak, termasuk persyaratan
integritas data dan fungsional.11
Mendefinisikan persyaratan integritas secara
eksplisit pada tahap ini adalah langkah fundamental.
● Desain (Design): Setelah kebutuhan ditetapkan, tim proyek menyusun desain
arsitektur dan komponen perangkat lunak secara rinci. Ini mencakup struktur
sistem, antarmuka pengguna yang intuitif, dan desain basis data yang efisien.11
Proses desain bertujuan untuk memastikan semua aspek teknis dan fungsional
perangkat lunak, termasuk mekanisme untuk menjaga integritas data (misalnya,
batasan basis data, validasi input) dan integritas fungsional (misalnya, arsitektur
modular yang mengurangi ketergantungan dan potensi kegagalan beruntun),
tercermin dengan jelas sebelum masuk ke fase pengembangan.
● Pengembangan (Development): Fase ini melibatkan penulisan kode sumber
berdasarkan desain yang telah disetujui. Tim pengembang membangun fitur-fitur
utama, mengintegrasikan berbagai komponen, dan memastikan semua elemen
perangkat lunak bekerja sesuai rencana.11
Praktik pengkodean yang aman (secure
coding practices) dan penulisan kode berkualitas tinggi sangat penting di sini
untuk mencegah kerentanan yang dapat mengganggu integritas, seperti
bug atau celah keamanan.
● Pengujian (Testing): Setelah pengembangan, perangkat lunak diuji secara
menyeluruh untuk memastikan berfungsi sesuai spesifikasi dan bebas dari bug
atau kesalahan. Pengujian ini mencakup unit testing, integration testing, dan
system testing, yang semuanya berkontribusi pada verifikasi keutuhan fungsional
dan data.11
Tahap ini secara aktif mencari ketidaksesuaian atau cacat yang dapat
mengancam keutuhan.
● Pemeliharaan (Maintenance): Setelah peluncuran, perangkat lunak memerlukan
pemeliharaan berkelanjutan untuk memperbaiki bug, meningkatkan kinerja, dan
menyesuaikan dengan perubahan kebutuhan pengguna atau lingkungan.1
Fase ini
krusial untuk mempertahankan keutuhan aplikasi dalam jangka panjang, karena
4. sistem yang tidak dipelihara rentan terhadap degradasi dan kerentanan baru.
Pembagian proses pengembangan menjadi tahapan yang jelas dalam SDLC secara
konsisten bertujuan untuk mengurangi risiko proyek dan memastikan perangkat lunak
berkualitas tinggi. Hal ini menunjukkan bahwa keutuhan bukanlah tambahan opsional,
melainkan properti yang dibangun secara inheren sejak langkah pertama. Dengan
mendefinisikan persyaratan dengan jelas, merancang arsitektur yang kuat, melakukan
pengkodean yang aman, dan menguji secara ketat dalam setiap fase, potensi masalah
keutuhan diidentifikasi dan dimitigasi secara proaktif, bukan secara reaktif setelah
penerapan. Pendekatan ini mengubah paradigma dari "memperbaiki masalah
keutuhan" menjadi "mencegah masalah keutuhan." SDLC yang diimplementasikan
dengan baik berfungsi sebagai mekanisme pertahanan proaktif, menanamkan
keutuhan ke dalam DNA aplikasi, yang jauh lebih hemat biaya dan lebih dapat
diandalkan daripada mencoba menambal kerentanan setelah peluncuran.
Metodologi Pengembangan yang Mendukung Keutuhan
Pilihan metodologi pengembangan perangkat lunak juga berperan penting dalam cara
keutuhan aplikasi dikelola dan dipertahankan.
● Agile: Pendekatan ini lebih fleksibel, memungkinkan perubahan sepanjang proses
pengembangan dan menekankan kolaborasi tim.1
Prioritas utamanya adalah
kepuasan pengguna yang dicapai dengan terus-menerus menghadirkan fitur yang
berfungsi dengan baik, teruji, dan diprioritaskan.12
Fleksibilitas ini memungkinkan
adaptasi cepat terhadap persyaratan integritas yang berubah atau ancaman baru
yang mungkin muncul selama siklus pengembangan.
● DevOps: Metodologi ini mengintegrasikan pengembangan dan operasi untuk
meningkatkan efisiensi dan kecepatan dalam pengiriman perangkat lunak.1
DevOps secara inheren mendukung praktik pengujian berkelanjutan (
Continuous Testing), yang sangat penting untuk menjaga keutuhan dalam
lingkungan pengiriman yang cepat dan sering.8
● Low-Code/No-Code: Alat-alat ini memungkinkan pengguna non-teknis untuk
membuat aplikasi dengan sedikit atau tanpa pengkodean, secara signifikan
mempercepat proses pengembangan.1
Meskipun mempercepat, penting untuk
memastikan bahwa platform Low-Code/No-Code yang digunakan memiliki
mekanisme bawaan yang kuat untuk menjamin integritas kode yang dihasilkan
dan keamanan aplikasi, karena transparansi dan kontrol atas kode mungkin
berkurang.
● Perbandingan dengan Waterfall: Metode Waterfall dikenal sebagai metode
tradisional yang menjadi dasar dari banyak metode baru.12
Namun, metode ini
dikenal kurang fleksibel; perubahan atau kesalahan di tengah proses
mengharuskan memulai dari awal, yang dapat menghambat respons terhadap
masalah integritas yang baru ditemukan atau persyaratan yang berevolusi.12
Agile
muncul sebagai respons terhadap kekakuan Waterfall, menekankan tanggapan
terhadap perubahan dan fokus pada perangkat lunak yang berfungsi.12
Scrum,
sebagai gabungan struktur tradisional dan fleksibilitas Agile, juga mendukung
keutuhan melalui kolaborasi dan iterasi terus-menerus.12
Perbandingan antara metodologi ini menunjukkan bahwa pilihan metodologi bukan
hanya tentang manajemen proyek, tetapi juga merupakan keputusan strategis tentang
bagaimana keutuhan aplikasi akan dikelola. Sementara Waterfall bertujuan untuk
5. integritas melalui perencanaan awal yang kaku dan sekuensial, metodologi modern
seperti Agile dan DevOps mencapainya melalui lingkaran umpan balik yang
berkelanjutan, pengembangan iteratif, dan pengujian terintegrasi. Kemampuan untuk
menanggapi perubahan dan terus menghadirkan fitur yang berfungsi dengan baik
dalam Agile, serta efisiensi dan kecepatan yang didukung oleh pengujian
berkelanjutan dalam DevOps, berpotensi menghasilkan aplikasi yang lebih tangguh
dan adaptif terhadap ancaman atau cacat yang muncul dalam lingkungan yang
dinamis. Namun, pendekatan Low-Code/No-Code memperkenalkan dimensi baru
dalam tantangan keutuhan, karena kode dasar yang dihasilkan mungkin kurang
transparan atau fitur keamanan yang kuat, sehingga memerlukan mekanisme validasi
dan jaminan kualitas yang berbeda.
III. Strategi Pengujian Komprehensif untuk Memastikan Keutuhan
Fungsional dan Data
Pengujian adalah fase krusial dalam siklus hidup pengembangan perangkat lunak yang
secara langsung memverifikasi dan menjamin keutuhan aplikasi. Pendekatan
pengujian yang komprehensif, mencakup berbagai jenis pengujian dan praktik
berkelanjutan, sangat penting untuk mengidentifikasi dan memperbaiki cacat sebelum
aplikasi mencapai pengguna akhir.
Jenis-jenis Pengujian dan Kontribusinya terhadap Keutuhan
Berbagai jenis pengujian bekerja secara sinergis untuk memastikan keutuhan aplikasi
dari berbagai perspektif:
● Unit Testing: Pengujian ini melibatkan pemeriksaan setiap unit kode secara
terpisah untuk memastikan bahwa masing-masing unit berfungsi dengan benar.13
Tujuannya adalah untuk mengidentifikasi masalah sejak dini dalam siklus
pengembangan, sebelum kode diintegrasikan dengan bagian lain dari aplikasi. Ini
adalah fondasi untuk keutuhan fungsional, memastikan bahwa blok bangunan
terkecil dari aplikasi sudah benar.
● Integration Testing: Pengujian integrasi berfokus pada bagaimana unit-unit
kode yang berbeda bekerja bersama. Tujuannya adalah untuk memastikan bahwa
semua bagian dari aplikasi berinteraksi dengan benar dan tidak ada masalah
integrasi yang tidak terduga yang dapat mengganggu keutuhan sistem secara
keseluruhan.13
Pengujian ini penting karena masalah sering muncul di antarmuka
antara komponen.
● Automated Testing: Strategi ini memanfaatkan alat pengujian untuk
mengeksekusi skenario pengujian secara otomatis.13
Ini secara signifikan
menghemat waktu dan upaya dalam pengujian, serta memastikan bahwa
pengujian dapat diulang dengan cepat dan konsisten setiap kali aplikasi
dimodifikasi atau diperbarui, menjaga keutuhan fungsionalitas setelah perubahan
tanpa memperkenalkan regresi.
● Code Review: Melibatkan pemeriksaan manual kode oleh anggota tim
pengembangan lain.13
Ini membantu menemukan kesalahan atau potensi masalah
yang mungkin terlewat oleh pengujian otomatis, memberikan masukan untuk
6. perbaikan kode, dan memastikan bahwa kode memenuhi standar dan praktik
terbaik yang ditetapkan, yang secara langsung berkontribusi pada keutuhan
struktural dan keamanan kode.
● Refactoring: Proses ini melibatkan perbaikan kode dan struktur aplikasi tanpa
mengubah fungsionalitas eksternalnya. Tujuannya adalah untuk meningkatkan
kualitas kode, membuatnya lebih mudah dipelihara dan dimengerti.13
Refactoring
membantu mencegah masalah seperti "Ice Cream Cone – Anti Pattern" yang
menunjukkan ketergantungan berlebihan, sehingga meningkatkan keutuhan
arsitektur dan keberlanjutan aplikasi.
● Validation Testing: Pengujian ini dilakukan pada tahap akhir siklus hidup
pengembangan perangkat lunak. Tujuannya adalah untuk memastikan bahwa
aplikasi memenuhi persyaratan dan tujuan bisnis yang telah ditetapkan.13
Ini
adalah verifikasi tingkat tinggi bahwa aplikasi secara keseluruhan memenuhi
ekspektasi pengguna dan bisnis, yang merupakan indikator utama keutuhan
fungsionalnya dari perspektif pengguna akhir.
Pendekatan pengujian yang berlapis ini memastikan bahwa keutuhan diverifikasi pada
berbagai granularitas. Unit testing menangkap kesalahan fundamental pada
komponen terkecil, integration testing memastikan komponen bekerja sama dengan
baik, dan validation testing mengkonfirmasi bahwa seluruh sistem memenuhi tujuan
yang dimaksudkan, yang merupakan ukuran utama keutuhan fungsionalnya.
Automated testing dan code review bertindak sebagai akselerator dan gerbang
kualitas di seluruh lapisan ini. Strategi pengujian yang komprehensif bukan hanya
tentang menemukan bug; ini tentang secara sistematis membangun dan
memverifikasi integritas dari awal. Setiap jenis pengujian berkontribusi pada aspek
integritas yang berbeda, menciptakan jaring pengaman yang kuat. Mengabaikan
lapisan apa pun dapat meninggalkan celah integritas yang kritis.
Pentingnya Pengujian Berkelanjutan (Continuous Testing)
Pengujian berkelanjutan adalah praktik penting dalam metodologi pengembangan
modern seperti Agile dan DevOps. Pengujian ini dipertahankan sebagai kode di
samping kode aplikasi dan sering dijalankan sebagai bagian dari paradigma pengujian
berkelanjutan.8
Manfaat kunci pengujian berkelanjutan untuk keutuhan aplikasi meliputi:
● Mempercepat Pengembangan Perangkat Lunak: Dengan alat pengujian
otomatis, pengembang dapat menguji dan menerapkan perbaikan saat mereka
membuat kode, tanpa menunggu umpan balik dari teknisi QA. Ini mempersingkat
waktu ke pasar dan meningkatkan responsivitas terhadap permintaan fitur.8
● Mengurangi Biaya Remediasi: Bug perangkat lunak dan masalah kinerja dapat
menyebabkan kerugian bisnis dan biaya besar. Pengujian berkelanjutan
memungkinkan identifikasi, pemantauan, dan pelaporan masalah di seluruh Siklus
Hidup Pengembangan Perangkat Lunak (SDLC). Menemukan masalah perangkat
lunak lebih awal dalam pipeline pengembangan secara signifikan mengurangi
biaya dan sumber daya remediasi, karena memperbaiki bug di awal jauh lebih
murah daripada di lingkungan produksi.8
● Meningkatkan Kualitas Kode: Pengujian berkelanjutan membantu
mempertahankan konsistensi kode di seluruh proyek yang berbeda. Kode sumber
yang terstruktur dengan baik lebih mudah dipahami, memiliki lebih sedikit bug,
7. dan mengonsumsi lebih sedikit sumber daya komputasi. Selain itu, kode dapat
digunakan kembali dengan lebih percaya diri setelah diuji secara ketat untuk bug,
fungsionalitas, dan masalah kinerja, yang secara langsung meningkatkan
keutuhan kode.8
● Meningkatkan Kolaborasi Tim: Pengujian berkelanjutan memberikan visibilitas
yang jelas ke dalam pengujian perangkat lunak yang dilakukan di setiap tahap
pengembangan. Tim pengembangan, QA, dan operasional dapat mengambil
pendekatan yang lebih proaktif dalam menemukan bug perangkat lunak di
lingkungan pengujian, daripada beroperasi secara terpisah. Ketika terintegrasi
dalam CI/CD, modul perangkat lunak yang berbeda dapat diuji dan hasilnya
dikomunikasikan secara bersamaan.8
● Meningkatkan Pengalaman Pelanggan: Dengan strategi pengujian yang kuat,
organisasi dapat mengantisipasi kemungkinan masalah dan merencanakan
tanggapan saat merilis perubahan perangkat lunak baru. Kerangka pengujian
berkelanjutan memungkinkan simulasi skenario yang mungkin dan antisipasi
potensi masalah, sehingga menghindari rilis yang cacat yang dapat mengurangi
harapan pelanggan. Masalah yang terdeteksi dari pengujian dapat diatasi
sebelum perangkat lunak dilepaskan ke lingkungan produksi, yang pada akhirnya
menghasilkan pengalaman perangkat lunak yang menarik secara konsisten dan
menjaga keutuhan fungsional dari perspektif pengguna.8
Pengujian berkelanjutan mengubah jaminan integritas dari fungsi penjaga gerbang
statis menjadi bagian integral dan berkelanjutan dari proses pengembangan.
Kemampuan untuk menguji dan memperbaiki saat kode sedang ditulis berarti bahwa
masalah integritas ditangani hampir secara real-time, mencegahnya menumpuk dan
menjadi masalah besar yang mahal. Ini menunjukkan bahwa integritas bukanlah
keadaan tetap tetapi properti dinamis yang harus terus-menerus divalidasi dan
disesuaikan dengan perubahan kode, persyaratan, dan lingkungan. Lingkaran umpan
balik yang berkelanjutan ini sangat penting untuk mempertahankan integritas dalam
lanskap perangkat lunak yang berkembang pesat, di mana pengujian batch tradisional
akan terlalu lambat dan mahal. Ini menumbuhkan budaya di mana kualitas dan
integritas adalah tanggung jawab setiap orang, bukan hanya tim QA.
Tabel: Perbandingan Strategi Pengujian dan Kontribusinya terhadap Keutuhan
Jenis Pengujian Fokus Utama Tujuan Keutuhan
(Aspek yang Dijaga)
Tahap SDLC (Kapan
Dilakukan)
Unit Testing Setiap unit kode
secara terpisah
Fungsionalitas
individual, kebenaran
logika unit
Pengembangan
Integration Testing Interaksi antar unit
kode
Interaksi komponen
yang benar, tidak ada
masalah integrasi
Pengembangan
Automated Testing Eksekusi skenario
pengujian otomatis
Konsistensi
fungsionalitas
setelah perubahan,
Pengembangan,
Pengujian
8. efisiensi pengujian
Code Review Pemeriksaan manual
kode oleh tim
Kualitas kode,
kepatuhan standar,
identifikasi masalah
tersembunyi,
keutuhan struktural
dan keamanan
Pengembangan
Refactoring Perbaikan struktur
dan kualitas kode
tanpa mengubah
fungsionalitas
Keberlanjutan,
pemeliharaan,
keutuhan arsitektur
Pengembangan,
Pemeliharaan
Validation Testing Pemenuhan
persyaratan dan
tujuan bisnis
Kesesuaian aplikasi
dengan ekspektasi
pengguna dan bisnis,
keutuhan
fungsionalitas
keseluruhan
Pengujian Akhir
IV. Validasi Data dan Penanganan Kesalahan: Pilar Keutuhan Data
Aplikasi
Keutuhan aplikasi sangat bergantung pada kualitas data yang diprosesnya. Validasi
data memastikan bahwa data yang masuk ke dalam sistem adalah benar dan
konsisten, sementara penanganan kesalahan yang efektif menjamin bahwa aplikasi
tetap stabil dan berfungsi dengan baik bahkan ketika terjadi kondisi tak terduga.
Tujuan dan Metode Validasi Data
Validasi data adalah proses pemeriksaan atau penilaian terhadap data yang
dimasukkan ke dalam sistem atau aplikasi untuk memastikan bahwa data tersebut
akurat, relevan, dan dapat dipertanggungjawabkan.9
Tujuan utamanya meliputi:
● Menghindari Kesalahan Input Data: Mencegah pengguna memasukkan data
yang tidak sesuai dengan kriteria yang ditetapkan, seperti memasukkan angka ke
kolom teks atau tanggal yang tidak valid.9
Ini adalah langkah pertama dalam
menjaga kebersihan data.
● Memastikan Konsistensi Data: Membantu memastikan bahwa data yang
dimasukkan konsisten dengan aturan yang sudah ditetapkan, baik dalam format,
tipe data, maupun hubungan antar data.9
Misalnya, memastikan format alamat
email yang benar atau nomor telepon hanya berisi digit.
● Menjaga Integritas Data: Memastikan bahwa data yang disimpan dalam basis
data tetap tidak rusak dan tidak terdistorsi, sehingga data dapat diandalkan untuk
analisis atau pengambilan keputusan lebih lanjut.9
Ini adalah kunci untuk
9. mempertahankan kepercayaan pada informasi.
● Meningkatkan Kualitas Data: Validasi berperan dalam meningkatkan kualitas
data secara keseluruhan, menyediakan fondasi yang lebih kuat untuk analisis dan
keputusan yang akurat dan dapat dipercaya.9
● Mengurangi Biaya dan Waktu: Mengurangi penundaan dalam proses bisnis dan
biaya yang diperlukan untuk memperbaiki masalah yang disebabkan oleh
kesalahan data dengan mengidentifikasinya sedini mungkin.9
Metode validasi umum yang digunakan untuk mencapai tujuan tersebut meliputi:
● Validasi Format: Memastikan data yang dimasukkan sesuai dengan format yang
diinginkan (misalnya, format email "nama@domain.com", tanggal, atau nomor
telepon).9
● Validasi Tipe Data: Memastikan input data cocok dengan tipe data yang
diharapkan (misalnya, hanya angka yang dapat dimasukkan ke kolom numerik).9
● Validasi Batasan Nilai (Value Range Validation): Memastikan data yang
dimasukkan berada dalam rentang nilai tertentu (misalnya, usia antara 0 dan 150
tahun, atau persentase kenaikan gaji maksimum 3%).9
● Validasi Keberadaan Data (Existence Check): Memastikan bahwa bidang wajib
tidak dibiarkan kosong (misalnya, nama atau alamat).9
● Validasi Keunikan Data (Uniqueness Check): Memastikan bahwa data yang
dimasukkan tidak duplikat (misalnya, alamat email atau nomor identifikasi dalam
sistem pendaftaran pengguna).9
● Validasi Logika: Memastikan hubungan antara data dalam satu entitas atau antar
entitas lain mematuhi aturan logis yang ditetapkan (misalnya, tanggal lahir tidak
boleh lebih lambat dari tanggal saat ini).9
● Validasi Integritas Referensial: Digunakan untuk memastikan bahwa data yang
dimasukkan ke dalam sistem memiliki referensi yang valid di tempat lain (misalnya,
dalam basis data relasional, data di tabel anak merujuk ke data yang valid di tabel
induk).9
Penerapan praktis validasi data sangat berguna ketika berbagi buku kerja dan ingin
memastikan data yang dimasukkan konsisten dan akurat.14
Ini dapat diterapkan pada
sel yang sudah ada data di dalamnya, dengan perangkat lunak seperti Excel yang
dapat melingkari data yang tidak valid untuk memudahkan identifikasi dan perbaikan.14
Validasi data bertindak sebagai penjaga gerbang awal untuk integritas data. Dengan
menolak data yang tidak valid atau berpotensi berbahaya pada titik masuk, validasi
data mencegah informasi yang rusak atau tidak dapat dipercaya masuk ke dalam
sistem. Ini secara langsung menjaga integritas seluruh kumpulan data dan semua
proses selanjutnya yang bergantung padanya. Ini adalah langkah keamanan proaktif
yang fundamental, yang tidak hanya meningkatkan pengalaman pengguna dengan
memandu input yang benar, tetapi juga mencegah serangkaian kegagalan integritas
yang dapat terjadi akibat data yang buruk menyebar ke seluruh sistem. Ini secara
efektif mengurangi masalah "sampah masuk, sampah keluar" (garbage in, garbage
out), yang sangat penting untuk pengambilan keputusan yang andal dan kinerja
sistem yang optimal.
Peran Penanganan Kesalahan (Error Handling) dalam Stabilitas dan Keandalan
Aplikasi
10. Penanganan kesalahan melibatkan implementasi mekanisme untuk mendeteksi,
mendiagnosis, dan mengatasi kesalahan secara sistematis, memastikan stabilitas dan
keandalan perangkat lunak.5
Intinya, penanganan kesalahan adalah tentang mencegah
masalah tak terduga agar tidak menyebabkan program
crash atau menghasilkan output yang salah.5
Manfaat kunci penanganan kesalahan untuk keutuhan fungsional meliputi:
● Mencegah Kegagalan Program: Memberikan cara bagi pengembang untuk
menangkap dan menyelesaikan kesalahan secara efektif, baik dengan
mengoreksinya secara otomatis atau memberi tahu pengguna agar dapat
mengambil tindakan yang sesuai.5
● Melindungi Data: Ketika kesalahan pemrograman terjadi, penanganan kesalahan
yang tepat dapat mencegah kerusakan data atau perilaku yang tidak diinginkan,
menjaga integritas informasi yang sedang diproses.5
● Umpan Balik Pengguna yang Informatif: Meningkatkan pengalaman pengguna
dengan menyediakan pesan kesalahan yang bermakna dan instruksi yang jelas
untuk resolusi, meminimalkan frustrasi pengguna dan membimbing mereka
kembali ke jalur yang benar.5
● Peningkatan Kualitas Kode: Berkontribusi pada kekokohan dan kualitas
keseluruhan perangkat lunak, mengurangi waktu henti dan kebutuhan perbaikan
bug yang sering.5
● Debugging dan Perbaikan yang Efisien: Memfasilitasi proses debugging melalui
mekanisme logging yang mencatat informasi tentang kesalahan, memberikan
wawasan berharga untuk perbaikan di masa mendatang.5
● Pemulihan yang Anggun (Graceful Recovery): Merancang aplikasi untuk
menangani kesalahan dengan anggun berarti menyediakan opsi fallback atau
solusi alternatif jika memungkinkan (misalnya, menampilkan data cache jika query
basis data gagal).15
Ini menjaga aplikasi tetap fungsional meskipun ada masalah
minor.
Penerapan dan praktik terbaik dalam penanganan kesalahan melibatkan penggunaan
blok try-catch untuk menangani pengecualian spesifik, menyediakan pesan kesalahan
yang informatif, mencatat kesalahan untuk debugging dan pemantauan berkelanjutan,
serta merancang untuk pemulihan yang anggun.15
Pengelolaan data yang baik di sisi
backend juga dapat meminimalkan risiko kesalahan input data yang kemudian harus
ditangani oleh mekanisme penanganan kesalahan.16
Ancaman terhadap keutuhan aplikasi juga dapat berasal dari kesalahan manusia.
Kesalahan umum yang dilakukan oleh pengguna atau administrator, seperti
penggunaan kata sandi yang lemah, mengakses Wi-Fi publik tanpa perlindungan,
mengunduh perangkat lunak dari sumber tidak resmi, menyimpan informasi login di
browser tanpa perlindungan, atau mengklik tautan phishing, dapat membuka celah
keamanan yang secara langsung atau tidak langsung memengaruhi integritas aplikasi
dan data.17
Penanganan kesalahan yang kuat dapat membantu memitigasi dampak
dari kesalahan tersebut.
Penanganan kesalahan yang efektif sangat penting untuk kepercayaan pengguna dan
waktu operasional sistem. Ini menunjukkan bahwa sementara validasi data melindungi
data pada saat entri, penanganan kesalahan melindungi integritas fungsional aplikasi
selama eksekusi. Ini adalah tentang bagaimana sistem bereaksi ketika terjadi
kesalahan, memastikan bahwa bahkan dalam menghadapi kondisi tak terduga (seperti
11. bug, operasi tidak valid, atau kegagalan eksternal), aplikasi tidak runtuh melainkan
mempertahankan keadaan yang dapat digunakan dan melindungi data dasarnya. Ini
mengubah potensi kegagalan sistem menjadi insiden yang dapat dikelola, menjaga
pengalaman pengguna dan mencegah kehilangan data atau korupsi yang mungkin
terjadi selama crash yang tidak terkontrol. Ini adalah komponen kunci dari ketahanan
aplikasi dan praktik pengembangan perangkat lunak yang matang.
V. Memperkuat Keutuhan Melalui Keamanan Siber: Enkripsi dan
Kontrol Akses
Keutuhan aplikasi tidak dapat dipisahkan dari strategi keamanan siber yang kuat.
Enkripsi dan kontrol akses adalah dua pilar fundamental yang secara langsung
berkontribusi pada perlindungan data dan fungsionalitas aplikasi dari akses tidak sah
dan modifikasi yang merusak.
Peran Enkripsi dalam Melindungi Kerahasiaan dan Integritas Data
Enkripsi adalah proses mengubah data asli (plaintext) menjadi bentuk yang tidak
dapat dibaca (ciphertext) menggunakan kode atau algoritma matematika, sehingga
hanya pihak yang memiliki kunci dekripsi yang benar yang dapat mengakses dan
membaca data tersebut.18
Tujuan utamanya adalah melindungi kerahasiaan
informasi.19
Namun, selain menjaga kerahasiaan, enkripsi memainkan peran vital dalam menjaga
integritas data dengan mencegah modifikasi tidak sah.3
Jika data yang terenkripsi
diubah, bahkan sedikit, tanpa kunci yang benar, data tersebut akan menjadi tidak
dapat dibaca atau rusak saat didekripsi, secara efektif mengindikasikan adanya
pelanggaran integritas.4
Ini melindungi data dari aktor jahat yang ingin melakukan
penipuan atau pemerasan, atau mengubah dokumen penting.20
Enkripsi diterapkan secara luas untuk mengamankan komunikasi internet (misalnya,
melalui SSL/TLS), melindungi data yang disimpan di perangkat (enkripsi disk penuh),
dan mengamankan lalu lintas data melalui jaringan (misalnya, VPN).18
Ini juga
diterapkan untuk melindungi transaksi finansial, komunikasi email dan pesan, serta
data perusahaan yang sensitif.18
Terdapat beberapa jenis enkripsi yang umum digunakan, termasuk Enkripsi Simetris
(menggunakan kunci yang sama untuk enkripsi dan dekripsi, seperti AES dan DES),
Enkripsi Asimetris (menggunakan pasangan kunci publik dan privat, seperti RSA), dan
Enkripsi Hybrid (menggabungkan kelebihan keduanya, seperti TLS).19
Jenis lain seperti
Base64, RC4, SHA, dan MD5 juga disebutkan dalam konteks perlindungan data
digital.22
Enkripsi berfungsi sebagai kontrol keamanan dua tujuan. Meskipun asosiasi utamanya
adalah dengan kerahasiaan, sifat intrinsiknya yang membuat data tidak dapat
digunakan setelah perubahan atau korupsi yang tidak sah menjadikannya mekanisme
yang kuat, meskipun tidak langsung, untuk memastikan integritas data. Enkripsi secara
12. pasif menjaga integritas karena data yang dirusak tanpa kunci yang benar akan
menjadi tidak dapat dibaca, sehingga secara efektif dilindungi dari perubahan tidak
sah yang bermakna. Selain itu, enkripsi juga secara aktif menandakan pelanggaran
integritas karena setiap upaya untuk memodifikasi data terenkripsi tanpa kunci yang
tepat akan membuatnya tidak berguna. Hal ini membuatnya sangat diperlukan untuk
data kritis sepanjang siklus hidupnya, baik saat istirahat (at rest), dalam transit (in
transit), dan bahkan selama pemrosesan.
Kontrol Akses: Mengatur Siapa yang Dapat Mengakses dan Memodifikasi
Aplikasi/Data
Kontrol akses adalah elemen inti keamanan yang mengatur siapa yang diizinkan untuk
mengakses aplikasi, data, dan sumber daya tertentu, serta dalam kondisi apa.10
Tujuannya adalah untuk menjaga informasi rahasia, seperti data pelanggan dan
kekayaan intelektual, dari pencurian oleh pelaku kejahatan atau pengguna tidak sah
lainnya.3
Ini juga mengurangi risiko eksfiltrasi data oleh karyawan dan mencegah
masuknya ancaman berbasis web.10
Dalam bentuk paling sederhana, kontrol akses melibatkan pengidentifikasian
pengguna berdasarkan kredensial mereka (misalnya, kata sandi, PIN, token keamanan,
pindaian biometrik) dan autentikasi (memverifikasi identitas pengguna).10
Setelah
identitas diautentikasi, kebijakan kontrol akses memberikan tingkat akses yang sesuai
berdasarkan konteks seperti perangkat, lokasi, dan peran.10
Autentikasi multifaktor
(MFA) menambahkan lapisan keamanan tambahan dengan mengharuskan pengguna
diverifikasi melalui lebih dari satu metode.10
Kontrol akses secara langsung menjaga integritas data dengan mengawasi siapa yang
dapat mengakses dan memanipulasi data dalam suatu sistem.3
Kontrol ini menetapkan
batasan yang mencegah perubahan tidak sah, memastikan bahwa hanya pengguna
tepercaya yang dapat berinteraksi dengan data.3
Melalui penegakan izin dan
pembatasan, kontrol akses berfungsi sebagai pengaman, menjaga keakuratan dan
keandalan informasi sensitif.3
Terdapat empat jenis utama kontrol akses:
● Kontrol Akses Sesuai Kebijaksanaan (Discretionary Access Control - DAC):
Pemilik objek dalam sistem yang terlindungi memberikan akses kepada pengguna
sesuai kebijaksanaan mereka sendiri.10
● Kontrol Akses Wajib (Mandatory Access Control - MAC): Otoritas pusat
mengatur dan membuat tingkatan hak akses yang meluas secara seragam, umum
di pemerintahan dan militer.10
● Kontrol Akses Berbasis Peran (Role-Based Access Control - RBAC): Hak
akses diberikan berdasarkan fungsi bisnis yang ditentukan, bukan identitas
individu, untuk memberikan data yang hanya diperlukan pengguna untuk
pekerjaan mereka.10
● Kontrol Akses Berbasis Atribut (Attribute-Based Access Control - ABAC):
Akses diberikan secara fleksibel berdasarkan kombinasi atribut dan kondisi
lingkungan, seperti waktu dan lokasi, menjadi model kontrol akses yang paling
menyeluruh.10
Kontrol akses adalah fondasi untuk mencegah perubahan tidak sah di seluruh sistem,
13. tidak hanya pada data. Dengan menerapkan kebijakan yang ketat mengenai siapa
yang dapat mengakses sumber daya, aplikasi dapat memastikan bahwa hanya
pengguna yang berwenang dengan peran dan izin yang tepat yang dapat melakukan
modifikasi atau mengakses informasi sensitif. Ini secara sistematis melindungi
keutuhan aplikasi secara keseluruhan dengan mengurangi risiko manipulasi internal
atau eksternal yang tidak sah, yang dapat merusak fungsionalitas atau data. Oleh
karena itu, kontrol akses merupakan komponen penting dari strategi keamanan yang
komprehensif untuk menjaga integritas sistemik.
VI. Ancaman, Kerentanan, dan Mitigasi untuk Keutuhan Aplikasi
Meskipun upaya proaktif dalam SDLC dan penerapan kontrol keamanan sangat
penting, lingkungan digital yang dinamis selalu menghadirkan ancaman dan
kerentanan baru. Memahami ancaman ini dan memiliki strategi mitigasi yang efektif
adalah kunci untuk mempertahankan keutuhan aplikasi secara berkelanjutan.
Ancaman Keamanan Siber Umum (OWASP Top 10)
OWASP Top 10 adalah dokumen kesadaran standar bagi pengembang dan keamanan
aplikasi web. Ini merepresentasikan konsensus luas tentang risiko keamanan paling
kritis terhadap aplikasi web dan diakui secara global sebagai langkah pertama menuju
pengkodean yang lebih aman.23
Organisasi didorong untuk mengadopsi dokumen ini
untuk meminimalkan risiko dalam aplikasi web mereka.23
Beberapa ancaman yang secara langsung memengaruhi integritas aplikasi,
sebagaimana diidentifikasi dalam OWASP Top 10 (versi 2021), meliputi:
● Software and Data Integrity Failures (A08:2021): Kategori baru ini berfokus
pada pembaruan perangkat lunak, data kritis, dan pipeline CI/CD yang digunakan
tanpa memverifikasi integritas.24
Ini juga mencakup
insecure deserialization, yang memungkinkan penyerang mengeksekusi kode dari
jarak jauh dalam sistem.24
● Broken Access Control (A01:2021): Kelemahan ini memungkinkan penyerang
mendapatkan akses ke akun pengguna atau fungsionalitas yang tidak sah, bahkan
sebagai administrator, yang dapat menyebabkan modifikasi data atau konfigurasi
yang tidak sah.24
● Cryptographic Failures (A02:2021): Kegagalan dalam penggunaan enkripsi,
seperti algoritma yang lemah, kunci yang buruk, atau manajemen kunci yang tidak
aman, dapat menyebabkan data sensitif terekspos atau dimanipulasi.24
● Insecure Design (A04:2021): Kurangnya desain keamanan yang memadai dapat
meninggalkan celah yang memungkinkan penyerang memanipulasi aplikasi atau
data.24
● Security Misconfiguration (A05:2021): Kesalahan konfigurasi pada server,
aplikasi, atau komponen pendukung dapat menciptakan kerentanan yang dapat
dieksploitasi untuk mengganggu integritas.24
● Vulnerable and Outdated Components (A06:2021): Penggunaan komponen
perangkat lunak yang rentan, tidak didukung, atau usang dapat menjadi titik
14. masuk bagi penyerang untuk mengkompromikan sistem.24
● Poor Code Quality (DA8 - Desktop App Security Top 10): Masalah terkait
kurangnya praktik pengkodean yang aman, seperti memory leaks atau buffer
overflows, dapat memungkinkan penyerang untuk merekayasa balik aplikasi atau
mengeksploitasi pemrosesan aplikasi.26
● Injections (DA1 - Desktop App Security Top 10): Terjadi ketika input yang tidak
tepercaya diteruskan ke interpreter sebagai bagian dari query atau perintah,
memungkinkan penyerang mengeksekusi perintah arbitrer atau mengumpulkan
data tidak sah.26
Strategi Mitigasi dan Kesiapsiagaan
Untuk mengatasi ancaman-ancaman ini dan menjaga keutuhan aplikasi, diperlukan
strategi mitigasi yang komprehensif dan kesiapsiagaan yang matang:
● Pencegahan Proaktif: Implementasi kontrol akses yang ketat, pembaruan
perangkat lunak secara teratur dengan patch keamanan, penggunaan enkripsi
untuk data sensitif, dan penerapan sistem deteksi intrusi adalah langkah-langkah
penting untuk mencegah pelanggaran integritas.3
Ini juga mencakup praktik
pengkodean yang aman untuk mencegah
bug yang dapat meningkatkan risiko keamanan.4
● Kerangka Kerja Keamanan Siber (NIST): Kerangka kerja seperti NIST
Cybersecurity Framework dapat digunakan oleh organisasi untuk mengevaluasi
sistem dan infrastruktur teknologi informasi yang digunakan untuk menjaga
keamanan teknologi dan sistem informasi dari ancaman siber.27
Ini membantu
dalam mengidentifikasi, melindungi, mendeteksi, merespons, dan memulihkan dari
insiden keamanan.
● Pengujian Keamanan Aplikasi (Application Security Testing):
○ IAST (Interactive Application Security Testing): Solusi seperti IAST dapat
membantu mendeteksi kerentanan seperti deserialization flaws, cross-site
request forgery, atau penyimpanan data sensitif yang tidak aman.24
○ Penetration Testing: Pengujian penetrasi dapat berfungsi sebagai suplemen
manual untuk aktivitas IAST, membantu mendeteksi kontrol akses yang tidak
disengaja atau masalah lain yang mungkin terlewat oleh alat otomatis.24
● Tanda Tangan Digital dan Checksum:
○ Tanda Tangan Digital (Digital Signatures): Tanda tangan digital
tersertifikasi menjamin keaslian, keutuhan, dan nirsangkal dokumen
elektronik.28
Jika terjadi perubahan pada dokumen yang ditandatangani
dengan tanda tangan digital tersertifikasi, tanda tangan tersebut tidak lagi
sah, yang membantu mencegah modifikasi data yang tidak sah.28
Tanda
tangan digital menggunakan enkripsi untuk menandatangani data,
memastikan bahwa setiap modifikasi tidak sah akan membatalkan tanda
tangan.4
○ Checksums: Checksum adalah nilai unik yang dihasilkan dari data untuk
memverifikasi integritasnya.3
Dengan menerapkan algoritma (
cryptographic hash function) pada data, checksum dibuat.29
Jika data diubah,
bahkan sedikit, nilai
checksum akan berubah, menunjukkan potensi korupsi atau perusakan.3
Checksum sering digunakan untuk memverifikasi integritas file selama
transmisi atau penyimpanan, seperti unduhan perangkat lunak.29
15. Mitigasi yang efektif terhadap ancaman integritas memerlukan pendekatan multi-
lapisan terhadap keutuhan. Ini berarti menggabungkan kontrol teknis (seperti enkripsi
dan kontrol akses), praktik pengembangan yang aman (seperti pengkodean aman dan
pengujian berkelanjutan), dan pemantauan berkelanjutan. Tidak ada satu pun solusi
yang cukup; sebaliknya, pertahanan yang kuat dibangun dari kombinasi strategi yang
bekerja sama untuk menciptakan penghalang yang tangguh terhadap ancaman.
Selain itu, kesiapsiagaan adalah bagian integral dari manajemen integritas.
Mengantisipasi dan mempersiapkan diri untuk pelanggaran (misalnya, melalui rencana
pemulihan bencana atau respons insiden) adalah krusial untuk pemulihan yang cepat
dan mempertahankan kelangsungan bisnis. Meskipun tujuan utamanya adalah
mencegah pelanggaran, realitas lanskap ancaman menunjukkan bahwa insiden dapat
terjadi. Oleh karena itu, memiliki kemampuan untuk mendeteksi, merespons, dan
memulihkan secara efisien setelah serangan atau kegagalan adalah kunci untuk
meminimalkan dampak dan dengan cepat mengembalikan aplikasi ke keadaan yang
utuh, yang pada akhirnya memperkuat integritas bahkan setelah insiden terjadi.
VII. Perbandingan Pendekatan Pengembangan dan Implikasinya
terhadap Keutuhan
Pilihan arsitektur dan platform pengembangan aplikasi memiliki implikasi signifikan
terhadap cara keutuhan aplikasi ditangani dan dipertahankan.
Arsitektur Mikroservis vs. Monolitik
● Arsitektur Monolitik: Aplikasi monolitik tradisional dibangun sebagai unit tunggal
yang terpadu, di mana semua komponen terhubung erat dan berbagi sumber
daya serta data.32
Dalam arsitektur monolitik, semua fungsi aplikasi terintegrasi
dalam satu kesatuan, membuatnya lebih sederhana untuk dikelola pada tahap
awal.33
Namun, pendekatan ini dapat menimbulkan tantangan dalam penskalaan,
deployment, dan pemeliharaan aplikasi, terutama seiring dengan meningkatnya
kompleksitas aplikasi.32
Jika satu bagian dari aplikasi mengalami masalah, seluruh
aplikasi bisa terpengaruh, yang membatasi skalabilitas dan meningkatkan risiko
kegagalan.33
● Arsitektur Mikroservis: Sebaliknya, arsitektur mikroservis memecah aplikasi
menjadi bagian-bagian kecil dan independen yang disebut microservice.33
Setiap
microservice berfungsi secara terpisah dan dapat dikembangkan, diuji, dan
dikelola secara mandiri.33
Microservice bersifat mandiri, dengan kode, data, dan dependensinya sendiri.32
Mereka berkomunikasi satu sama lain melalui API.33
Pendekatan ini menawarkan
beberapa keunggulan dalam hal ketahanan: jika satu
microservice gagal, hal tersebut tidak akan berdampak pada seluruh aplikasi.32
Ini
memungkinkan tim pengembang untuk bekerja secara paralel dan meningkatkan
resiliensi.33
Implikasi terhadap keutuhan sangat berbeda antara kedua arsitektur ini. Dalam
arsitektur monolitik, keutuhan aplikasi ditangani dengan memiliki semua komponen
16. dalam satu tempat, yang membuatnya lebih mudah dikelola pada tahap awal. Namun,
hal ini juga berarti bahwa kegagalan satu komponen dapat memengaruhi seluruh
aplikasi karena ketergantungan yang erat.32
Sebaliknya, dalam arsitektur mikroservis,
keutuhan aplikasi ditangani melalui prinsip independensi, di mana setiap
microservice dapat dikembangkan dan dikerjakan secara terpisah.33
Meskipun ini
meningkatkan ketahanan dan skalabilitas, mengelola banyak layanan bisa menjadi
rumit, dan menjaga konsistensi data antar layanan yang terdistribusi bisa menjadi
tantangan tersendiri.33
Pilihan arsitektur secara fundamental membentuk bagaimana integritas dikelola.
Dalam monolitik, integritas adalah tanggung jawab terpusat, di mana satu codebase
dan deployment berarti satu titik kegagalan yang potensial untuk seluruh sistem. Di
sisi lain, mikroservis menawarkan integritas yang terlokalisasi pada tingkat layanan
individu, yang berarti kegagalan satu layanan tidak serta-merta meruntuhkan seluruh
aplikasi. Namun, hal ini memerlukan mekanisme yang kuat untuk menjaga integritas
transaksi dan konsistensi data di seluruh layanan yang terdistribusi, serta manajemen
yang kompleks untuk memastikan komunikasi antar-layanan yang aman dan andal.
Pengembangan Aplikasi Web vs. Mobile (Native/Hybrid)
Perbedaan utama antara aplikasi web dan aplikasi native adalah di mana mereka
berjalan. Aplikasi web dapat diakses dari peramban desktop atau perangkat seluler,
sementara aplikasi native diunduh dan diinstal di perangkat.34
● Aplikasi Web:
○ Aksesibilitas & Jangkauan: Lebih unggul dalam menjangkau audiens yang
lebih luas karena dukungan multi-perangkat dan optimasi mesin pencari
(SEO).36
○ Fungsionalitas: Terbatas pada interaksi yang didukung peramban dan
mungkin tidak dapat mengakses fitur perangkat keras internal seperti kamera
atau GPS secara maksimal.34
○ Pembaruan: Pembaruan dapat dilakukan secara real-time dan pengguna
tidak perlu mengunduh ulang atau menginstal pembaruan, membuat
pemeliharaan lebih sederhana.35
○ Performa: Umumnya lebih lambat dan kurang responsif dibandingkan aplikasi
native karena ketergantungan pada peramban dan transfer data dari server.34
○ Keamanan: Dikembangkan dengan pendekatan keamanan yang berbeda, dan
mungkin kurang dilengkapi alat keamanan dibandingkan aplikasi mobile.36
● Aplikasi Mobile (Native/Hybrid):
○ Fungsionalitas: Aplikasi native memungkinkan pengguna berinteraksi dengan
fitur perangkat keras internal dan sistem operasi, seperti pelacakan lokasi,
mikrofon, kamera, dan fitur keamanan biometrik.34
○ Pengalaman Pengguna: Cenderung memberikan pengalaman yang jauh
lebih baik karena dapat menyesuaikan diri dengan karakteristik pengguna dan
menawarkan personalisasi serta interaksi langsung.34
○ Performa: Menawarkan performa yang lebih baik, lebih cepat, responsif, dan
interaktif karena diinstal langsung di perangkat dan dapat memanfaatkan
akselerasi perangkat keras.34
○ Pembaruan: Setiap pembaruan baru berarti pengguna harus mengunduh dan
menginstal ulang aplikasi, yang bisa merepotkan dan sering ditunda.36
17. ○ Keamanan: Dilengkapi dengan berbagai alat keamanan yang membuatnya
lebih aman, dan keamanan serta perlindungan data menjadi prioritas utama.35
API Integritas Play, misalnya, membantu memverifikasi bahwa tindakan
pengguna atau permintaan
server adalah asli dan merupakan bagian dari strategi anti-penyalahgunaan.38
Pertimbangan keutuhan sangat dipengaruhi oleh pilihan platform. Aplikasi mobile
(terutama native) cenderung menawarkan integritas fungsional yang lebih tinggi
karena integrasi mendalam dengan perangkat keras dan sistem operasi, serta
performa yang superior. Namun, mereka menghadapi tantangan dalam manajemen
pembaruan dan distribusi, yang dapat memengaruhi keutuhan jika pengguna tidak
memperbarui aplikasi. Aplikasi web, di sisi lain, menawarkan pembaruan terpusat dan
aksesibilitas cross-platform yang lebih mudah, yang dapat menyederhanakan
pemeliharaan integritas kode di sisi server. Namun, mereka mungkin memiliki
keterbatasan dalam mengakses fitur perangkat dan performa, yang dapat
memengaruhi keutuhan pengalaman pengguna.
Pilihan platform pengembangan menentukan tantangan integritas yang spesifik. Untuk
aplikasi mobile, menjaga keutuhan berarti fokus pada keamanan perangkat-spesifik,
manajemen pembaruan aplikasi yang efektif, dan memastikan kompatibilitas dengan
berbagai versi OS dan perangkat. Untuk aplikasi web, fokusnya bergeser ke integritas
di sisi server (keamanan backend, validasi data), keamanan peramban, dan
memastikan konsistensi pengalaman pengguna di berbagai peramban dan perangkat.
Oleh karena itu, strategi untuk mempertahankan keutuhan harus disesuaikan secara
khusus dengan karakteristik dan batasan platform yang dipilih.
VIII. Kesimpulan dan Rekomendasi
Keutuhan aplikasi adalah fondasi krusial bagi keberhasilan operasional dan keamanan
dalam lanskap digital modern. Laporan ini telah menguraikan bahwa keutuhan
melampaui sekadar integritas data; ia mencakup keandalan fungsionalitas, konsistensi
logika, dan ketahanan terhadap modifikasi tidak sah, menjadikannya atribut kualitas
holistik yang esensial. Keutuhan aplikasi secara langsung memengaruhi efisiensi
bisnis, pengambilan keputusan, dan melindungi dari kerugian finansial serta reputasi
akibat pelanggaran keamanan siber.
Pencapaian keutuhan aplikasi memerlukan pendekatan multi-dimensi yang
terintegrasi di seluruh Siklus Hidup Pengembangan Perangkat Lunak (SDLC). Setiap
fase SDLC, mulai dari perencanaan hingga pemeliharaan, memainkan peran vital
dalam membangun keutuhan sejak awal, mengubah paradigma dari perbaikan reaktif
menjadi pencegahan proaktif. Metodologi pengembangan modern seperti Agile dan
DevOps, dengan penekanan pada fleksibilitas, kolaborasi, dan pengujian
berkelanjutan, mendukung adaptasi dinamis terhadap ancaman integritas yang terus
berkembang.
Strategi pengujian yang komprehensif, mulai dari unit testing hingga validation
testing, membentuk jaring pengaman berlapis yang memverifikasi integritas pada
berbagai granularitas. Pengujian berkelanjutan, khususnya, menjadi mekanisme
adaptasi integritas yang dinamis, memungkinkan identifikasi dan perbaikan masalah
hampir secara real-time, yang sangat penting dalam lingkungan pengembangan yang
18. cepat.
Validasi data berfungsi sebagai garis pertahanan pertama untuk integritas data,
mencegah informasi yang tidak akurat atau berbahaya masuk ke dalam sistem.
Sementara itu, penanganan kesalahan yang efektif adalah mekanisme resiliensi yang
menjaga stabilitas fungsional aplikasi, memastikan aplikasi tetap beroperasi dan
melindungi data bahkan dalam kondisi tak terduga.
Aspek keamanan siber, terutama enkripsi dan kontrol akses, adalah pilar tak
terpisahkan dalam menjaga keutuhan. Enkripsi tidak hanya melindungi kerahasiaan
tetapi juga secara pasif dan aktif menjaga integritas data dengan membuatnya tidak
dapat digunakan jika dimodifikasi secara tidak sah. Kontrol akses, di sisi lain, adalah
fondasi integritas sistemik, yang secara ketat mengatur siapa yang dapat mengakses
dan memodifikasi sumber daya aplikasi, mencegah perubahan yang tidak sah.
Terakhir, pilihan arsitektur (mikroservis vs. monolitik) dan platform (web vs. mobile)
secara fundamental memengaruhi bagaimana keutuhan dikelola, membutuhkan
strategi yang disesuaikan untuk mengatasi tantangan unik masing-masing.
Rekomendasi:
Berdasarkan analisis ini, untuk membangun dan mempertahankan keutuhan aplikasi
dengan baik dan benar, direkomendasikan langkah-langkah berikut:
1. Integrasi Keutuhan Sejak Awal SDLC: Pastikan persyaratan integritas
didefinisikan secara eksplisit pada fase perencanaan dan analisis kebutuhan.
Desain arsitektur harus mencakup mekanisme untuk menjaga integritas data dan
fungsional.
2. Adopsi Metodologi Adaptif: Prioritaskan penggunaan metodologi Agile dan
DevOps yang mendukung pengembangan iteratif, kolaborasi tim, dan pengujian
berkelanjutan. Untuk platform Low-Code/No-Code, pastikan mekanisme jaminan
integritas bawaan platform dievaluasi dan dimanfaatkan sepenuhnya.
3. Implementasi Strategi Pengujian Berlapis dan Berkelanjutan: Terapkan
kombinasi unit testing, integration testing, code review, automated testing,
refactoring, dan validation testing. Integrasikan pengujian berkelanjutan dalam
pipeline CI/CD untuk deteksi dini dan remediasi masalah integritas.
4. Perkuat Validasi Data dan Penanganan Kesalahan: Terapkan validasi data
yang ketat di semua titik input untuk mencegah data yang tidak valid masuk ke
sistem. Kembangkan mekanisme penanganan kesalahan yang robust untuk
memastikan stabilitas aplikasi, pemulihan yang anggun, dan umpan balik yang
informatif kepada pengguna, serta melindungi data dari korupsi selama eksekusi.
5. Prioritaskan Keamanan Siber: Terapkan enkripsi end-to-end untuk data sensitif,
baik saat istirahat maupun dalam transit, untuk menjaga kerahasiaan dan
integritas. Implementasikan kontrol akses berbasis peran (RBAC) atau atribut
(ABAC) yang ketat untuk memastikan hanya pengguna yang berwenang yang
dapat mengakses dan memodifikasi sumber daya aplikasi.
6. Patuhi Standar Keamanan dan Mitigasi Ancaman: Gunakan panduan
keamanan yang diakui seperti OWASP Top 10 dan kerangka kerja seperti NIST
Cybersecurity Framework untuk mengidentifikasi dan memitigasi kerentanan
umum. Lakukan pengujian keamanan aplikasi secara teratur (misalnya, IAST,
penetration testing).
7. Manfaatkan Alat Verifikasi Integritas: Gunakan tanda tangan digital dan
checksum untuk memverifikasi keutuhan file, codebase, dan pembaruan
perangkat lunak, memastikan bahwa tidak ada modifikasi tidak sah yang terjadi.
19. 8. Sesuaikan Strategi dengan Arsitektur dan Platform: Pahami implikasi
keutuhan dari pilihan arsitektur (monolitik vs. mikroservis) dan platform (web vs.
mobile), dan sesuaikan strategi pengembangan, pengujian, dan keamanan untuk
mengatasi tantangan spesifik yang muncul dari pilihan tersebut.
Dengan menerapkan rekomendasi ini secara komprehensif, organisasi dapat secara
signifikan meningkatkan keutuhan aplikasi mereka, membangun kepercayaan
pengguna, mengurangi risiko operasional, dan memastikan keberlanjutan bisnis dalam
lingkungan digital yang kompetitif.
Karya yang dikutip
1. Pengembangan Perangkat Lunak, diakses Agustus 7, 2025, https://kd-
cibiru.upi.edu/index.php/component/content/article/pengembangan-perangkat-
lunak?catid=29&Itemid=101
2. Software Development: Pengertian, Manfaat, Proses, Jenis, Dan ..., diakses
Agustus 7, 2025, https://proxsisgroup.com/insights/software-development%3A-
pengertian%2C-manfaat%2C-proses%2C-jenis%2C-dan-contohnya
3. Exploring Integrity: Key Principles and Applications | Lenovo US, diakses Agustus
7, 2025, https://www.lenovo.com/us/en/glossary/what-is-integrity/
4. What is Integrity in Information Security: Integrity Models, Threats and Prevention
- GeeksforGeeks, diakses Agustus 7, 2025,
https://www.geeksforgeeks.org/ethical-hacking/information-security-integrity/
5. Everything You Need to Know When Assessing Error Handling Skills - Alooba,
diakses Agustus 7, 2025,
https://www.alooba.com/skills/concepts/automationscripting-346/error-handling/
6. Apa itu Keamanan Siber? - Penjelasan tentang Keamanan Siber - AWS, diakses
Agustus 7, 2025, https://aws.amazon.com/id/what-is/cybersecurity/
7. Cyber Security: Definisi, Sejarah, Jenis dan Ancaman-nya - Vida, diakses Agustus
7, 2025, https://vida.id/id/blog/cyber-security-adalah
8. Apa Itu Pengujian Berkelanjutan? - Penjelasan Pengujian ... - AWS, diakses Agustus
7, 2025, https://aws.amazon.com/id/what-is/continuous-testing/
9. Validasi Data: Pengertian, Tujuan, Metode, dan Pentingnya dalam ..., diakses
Agustus 7, 2025, https://tesis.id/blog/validasi-data-pengertian-tujuan-metode-
dan-pentingnya-dalam-dunia-teknologi/
10. Apa itu Access Control? | Microsoft Security, diakses Agustus 7, 2025,
https://www.microsoft.com/id-id/security/business/security-101/what-is-access-
control
11. SDLC adalah Proses Penting: Fase Software Development Life Cycle, diakses
Agustus 7, 2025, https://dti-jkt.telkomuniversity.ac.id/software-development-life-
cycle-sdlc/
12. √ 6 Metode Pengembangan Perangkat Lunak Paling Populer, diakses Agustus 7,
2025, https://badoystudio.com/metode-pengembangan-perangkat-lunak/
13. 5+ Strategi Pengujian Aplikasi yang Efektif! Developer Harus Tahu!, diakses
Agustus 7, 2025, https://arkatama.id/5-strategi-pengujian-aplikasi-yang-efektif-
developer-harus-tahu/
14. Selengkapnya tentang validasi data - Dukungan Microsoft, diakses Agustus 7,
2025, https://support.microsoft.com/id-id/office/selengkapnya-tentang-validasi-
data-f38dee73-9900-4ca6-9301-8a5f6e1f0c4c
15. What are the best practices for error handling and graceful error recovery in web
application development? - GTCSYS, diakses Agustus 7, 2025,
https://gtcsys.com/faq/what-are-the-best-practices-for-error-handling-and-
graceful-error-recovery-in-web-application-development/
16. Rancang Bangun Backend Sistem Pemantauan Dokumen Akreditasi
Menggunakan Kerangka Kerja Laravel Berbasis RESTful API - E-Journal UNDIP,
diakses Agustus 7, 2025,
https://ejournal3.undip.ac.id/index.php/jtk/article/download/38320/30535
17. Keamanan Digital Bisa Runtuh Hanya Karena Satu Kesalahan Sepele -
20. Djkn.kemenkeu.go.id, diakses Agustus 7, 2025,
https://www.djkn.kemenkeu.go.id/kpknl-samarinda/baca-artikel/17780/
Keamanan-Digital-Bisa-Runtuh-Hanya-Karena-Satu-Kesalahan-Sepele.html
18. Peran Enkripsi dalam Keamanan Siber - Cyber Raksa, diakses Agustus 7, 2025,
https://raksacyber.co.id/peran-enkripsi-dalam-keamanan-siber/
19. Enkripsi Data: Menjaga Keamanan Informasi di Era Digital - PT Teltics Media,
diakses Agustus 7, 2025, https://teltics.com/blog/enkripsi-data-menjaga-
keamanan-informasi-di-era-digital
20. What is encryption and how does it work? - Google Cloud, diakses Agustus 7,
2025, https://cloud.google.com/learn/what-is-encryption
21. Protect Data with Encryption - UCI Information Security - UC Irvine, diakses
Agustus 7, 2025, https://www.security.uci.edu/how-to/encryption/
22. Enkripsi: Pengertian, Manfaat dan Cara Aktifkan untuk Lindungi Data -
Cermati.com, diakses Agustus 7, 2025, https://www.cermati.com/artikel/enkripsi-
pengertian-manfaat-dan-cara-aktifkan-untuk-lindungi-data
23. OWASP Top Ten, diakses Agustus 7, 2025, https://owasp.org/www-project-top-
ten/
24. What Is the OWASP Top 10 and How Does It Work? | Black Duck, diakses Agustus
7, 2025, https://www.blackduck.com/glossary/what-is-owasp-top-10.html
25. OWASP Top Ten: 2021 Edition - Sucuri, diakses Agustus 7, 2025,
https://sucuri.net/guides/owasp_top_10_2021_edition/
26. OWASP Desktop App Security Top 10, diakses Agustus 7, 2025,
https://owasp.org/www-project-desktop-app-security-top-10/
27. PERANCANGAN KERANGKA KERJA KEAMANAN SIBER MENGGUNAKAN NIST
CYBERSECURITY FRAMEWORK DAN CIS CONTROLS CASE STUDY - SiMANTU,
diakses Agustus 7, 2025,
https://simantu.pu.go.id/personal/img-post/199002252019031003/post/
20230727143959__F__SIMANTU_199002252019031003_Vicky_Mahendra.pdf
28. KENAPA HARUS MEMAKAI TANDA TANGAN ELEKTRONIK ..., diakses Agustus 7,
2025, https://diskominfo.tasikmalayakota.go.id/artikel/kenapa-harus-memakai-
tanda-tangan-elektronik/
29. What is a Checksum & How to Use One | NinjaOne, diakses Agustus 7, 2025,
https://www.ninjaone.com/blog/what-is-a-checksum/
30. Ensuring Integrity of Data Files with Checksums - How-to Cards, diakses Agustus
7, 2025, https://howto.lcsb.uni.lu/external/integrity/checksum/
31. 8. How to check file integrity by validating checksums - FAIR Cookbook, diakses
Agustus 7, 2025,
https://faircookbook.elixir-europe.org/content/recipes/findability/checksum-
validate.html
32. Apa itu Arsitektur Microservice? | Google Cloud, diakses Agustus 7, 2025,
https://cloud.google.com/learn/what-is-microservices-architecture?hl=id
33. Perbandingan Arsitektur Microservices dan Monolithic: Mana yang ..., diakses
Agustus 7, 2025, https://www.idn.id/perbandingan-arsitektur-microservices-dan-
monolithic-mana-yang-tepat-untuk-proyek-anda/
34. Aplikasi Web vs. Aplikasi Native vs. Aplikasi Hibrida - Perbandingan ..., diakses
Agustus 7, 2025, https://aws.amazon.com/id/compare/the-difference-between-
web-apps-native-apps-and-hybrid-apps/
35. Web app vs native app: Which one is better for your project? - Hostinger, diakses
Agustus 7, 2025, https://www.hostinger.com/tutorials/web-app-vs-native-app
36. Website VS Aplikasi Mobile: Mana yang lebih baik ketika memulai ..., diakses
Agustus 7, 2025, https://id.timedoor.net/blogs/Website-VS-Aplikasi-Mobile-
Mana-yang-lebih-baik-ketika-memulai-bisnis/
37. Web developer vs. app developer explained - Merge Rocks, diakses Agustus 7,
2025, https://merge.rocks/blog/web-developer-vs-app-developer-explained
38. Overview of the Play Integrity API - Android Developers, diakses Agustus 7, 2025,
https://developer.android.com/google/play/integrity/overview
Lampiran untuk aplikasi ANTI VIRUS yang dibuat oleh: Junirullah
21. <!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PEMBUAT.com Antivirus - Jaringan Global</title>
<!-- Memuat Tailwind CSS CDN untuk styling yang mudah dan responsif -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Menggunakan Google Font Inter untuk tampilan modern dan profesional -->
<link href="https://fonts.googleapis.com/css2?
family=Inter:wght@300;400;600;700;800&display=swap" rel="stylesheet">
<!-- Memuat Google Font Noto Naskh Arabic untuk tulisan Arab -->
<link href="https://fonts.googleapis.com/css2?
family=Noto+Naskh+Arabic:wght@400;700&display=swap" rel="stylesheet">
<!-- Memuat Chart.js untuk grafik -->
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!-- Memuat Tone.js untuk efek suara -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.min.js"></script>
<style>
/* Custom colors for the new theme */
:root {
--dark-blue: #1a202c;
--accent-blue: #4299e1;
--accent-purple: #805ad5;
--text-light: #e2e8f0;
--text-muted: #a0aec0;
--card-bg: rgba(26, 32, 44, 0.85); /* Slightly transparent dark blue */
--button-bg: #2d3748;
--button-hover: #4a5568;
--safe-green: #38a169;
--threat-red: #e53e3e;
--warning-orange: #dd6b20;
--notification-red: #e53e3e;
--pro-gold: #fbd38d; /* Golden color for Pro elements */
}
body {
font-family: 'Inter', sans-serif;
background: linear-gradient(to bottom right, #000000, #1a202c, #2d3748); /* Dark
gradient background */
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
position: relative;
color: var(--text-light); /* Default text color */
overflow-x: hidden; /* Prevent horizontal scroll */
}
/* Subtle network background pattern */
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml;utf8,<svg width="100%" height="100%"
viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg"><defs><pattern id="grid"
width="10" height="10" patternUnits="userSpaceOnUse"><path d="M 10 0 L 0 0 L 0 10"
fill="none" stroke="%232d3748" stroke-width="0.2" /></pattern></defs><rect width="100%"
height="100%" fill="url(%23grid)" /></svg>');
opacity: 0.1; /* Very subtle */
z-index: -1;
}
/* Container for the shield effect around Arabic text */
.arabic-text-container {
22. position: relative;
width: 100%; /* Full width */
max-width: 800px; /* Limit max width for desktop */
margin: 0 auto 20px auto; /* Center and add margin */
padding: 10px; /* Padding inside the frame */
box-sizing: border-box; /* Include padding in width */
display: flex;
justify-content: center;
align-items: center;
}
/* Base style for the Arabic text at the very top */
.arabic-text {
font-family: 'Noto Naskh Arabic', serif; /* Use Noto Naskh Arabic font */
font-size: 2.5rem; /* Large font size */
font-weight: 700;
color: var(--pro-gold); /* Default for non-pro or initial state */
text-shadow: 0 0 10px rgba(251, 211, 141, 0.5); /* Subtle glow effect */
text-align: center; /* Center the text */
position: relative; /* Needed for z-index */
z-index: 2; /* Ensure text is above border effects */
padding: 10px 20px; /* Padding inside the text area */
}
@media (max-width: 768px) {
.arabic-text {
font-size: 1.8rem; /* Smaller font on mobile */
margin-bottom: 15px;
}
}
/* Keyframes for shimmering animation */
@keyframes shimmer {
0% { background-position: -200% 0; }
100% { background-position: 200% 0; }
}
/* PRO version specific styles for arabic text */
.arabic-text-container.pro-active .arabic-text {
background: linear-gradient(90deg, #f0e68c 0%, #ffd700 25%, #f0e68c 50%, #ffd700
75%, #f0e68c 100%);
background-size: 200% auto;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: shimmer 3s infinite linear;
text-shadow: 0 0 15px rgba(255, 215, 0, 0.8), 0 0 25px rgba(255, 215, 0, 0.6);
}
/* Shield Frame (using pseudo-element for border effect) */
.arabic-text-container.pro-active::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: linear-gradient(90deg, #f0e68c 0%, #ffd700 25%, #f0e68c 50%, #ffd700
75%, #f0e68c 100%);
background-size: 200% auto;
animation: shimmer 3s infinite linear;
z-index: 1;
/* Create shield shape using clip-path */
clip-path: polygon(
50% 0%, /* Top center */
95% 10%, /* Top right point (adjusted for a wider top) */
100% 50%, /* Mid right point */
95% 90%, /* Bottom right point (adjusted for a wider bottom) */
50% 100%, /* Bottom center point */
5% 90%, /* Bottom left point */
0% 50%, /* Mid left point */
5% 10% /* Top left point */
41. </button>
<button class="action-button-base scan-button-item" onclick="startScan('Laptop');
playClingSound();">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path
d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2
2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></svg>
L a p t o p
</button>
<button class="action-button-base scan-button-item" onclick="startScan('Notebook');
playClingSound();">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path
d="M20 18H4c-1.1 0-2 .9-2 2v2h20v-2c0-1.1-.9-2-2-2zM22 6v10c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-
2V6c0-1.1.9-2 2-2h16c1.1 0 2 .9 2 2zM4 6h16v10H4V6z"/></svg>
N o t e b o o k
</button>
<button class="action-button-base scan-button-item" onclick="startScan('Jaringan');
playClingSound();">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12 3c-4.97 0-9 4.03-9 9s4.03 9 9 9 9-4.03 9-9-4.03-9-9-9zm0 16c-
3.87 0-7-3.13-7-7s3.13-7 7-7 7 3.13 7 7-3.13 7-7 7zm-1-5h2v2h-2zm0-4h2v3h-2zm0-4h2v3h-
2z"/>
</svg>
J a r i n g a n
</button>
</div>
<!-- Bagian Perisai Antivirus -->
<div class="shield-section">
<h2 class="text-xl font-semibold text-text-light mb-3 flex items-center justify-center">
<svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path
d="M12 1L3 5v6c0 5.55 3.84 10.74 9 12 5.16-1.26 9-6.45 9-12V5l-9-4zm0 10.99h7c-.53 4.12-
3.28 7.79-7 8.94V12H5V6.3l7-3.11v8.8z"/></svg>
Perisai Antivirus
</h2>
<p class="text-text-muted mb-4">Aktifkan atau nonaktifkan perlindungan
real-time.</p>
<button id="shield-toggle-button" class="shield-button" onclick="toggleShield();
playClingSound();">Aktifkan Perisai</button>
<p id="shield-status" class="status-text">Perisai: Nonaktif</p>
</div>
</div>
<!-- Panel Kanan: Hasil Pemindaian dan Status -->
<div class="right-panel w-full lg:w-2/3 flex flex-col gap-4">
<div class="current-scan-card" id="current-scan-card">
<h3 id="current-scan-title">Pilih Pemindaian untuk Memulai</h3>
<p id="current-scan-status">Tidak ada pemindaian yang sedang berjalan.</p>
<!-- Area untuk animasi pemindaian -->
<div class="scan-animation-area" id="scan-animation-area">
<div class="scan-line"></div>
<div class="scan-nodes">
<div class="node"></div>
<div class="node"></div>
<div class="node"></div>
<div class="node"></div>
<div class="node"></div>
</div>
</div>
<!-- Area untuk grafik -->
<div class="chart-container">
<canvas id="threatLevelChart"></canvas>
</div>
</div>
<!-- Bagian Detail Masalah dan Pilihan Penyelesaian -->
<div class="detailed-threat-results" id="detailed-threat-results">
<h4 class="text-center">Detail Masalah</h4>
<div id="threat-list-container">
<!-- Detail ancaman akan dimasukkan di sini oleh JavaScript -->
</div>
42. <button class="recover-all-threats-button" id="detailed-recover-all-button"
onclick="recoverAllThreats(); playClingSound();">Pulihkan Semua</button>
</div>
<!-- Bagian Laporan Aplikasi & Tindakan (Baru) -->
<div class="application-reports-section" id="application-reports-section">
<h4 class="text-center">Laporan Aplikasi & Tindakan</h4>
<div id="report-content" class="flex flex-col gap-3">
<p class="text-text-muted text-center">Tidak ada laporan terbaru.</p>
</div>
</div>
<!-- Bagian Notifikasi Aplikasi (Inline - BARU) -->
<div class="inline-notifications-section" id="inline-notifications-section">
<h4 class="text-center">Notifikasi Anda</h4>
<div id="inline-notification-list" class="flex flex-col gap-3">
<!-- Notifikasi akan dimuat di sini oleh JavaScript -->
<p class="text-text-muted text-center" id="no-inline-notifications-message">Tidak
ada notifikasi baru.</p>
</div>
</div>
<!-- Bagian Donasi -->
<div class="donate-section" id="donate-section">
<h3 class="text-xl sm:text-2xl font-bold text-warning-orange mb-4">Donasi & Beli
Versi Pro Rp.78.600,-/Tahun</h3>
<p class="text-text-muted mb-4 text-sm sm:text-base">Dukung pengembangan
PEMBUAT.com Antivirus atau dapatkan fitur lengkap dengan membeli versi Pro!</p>
<div class="bank-info">
<p class="font-semibold text-text-light">Tujuan pembayaran kepada Owner
PEMBUAT.com Antivirus :</p>
<p><strong>BANK BRI</strong></p>
<p><strong>NO. REK : 0192-01-162209-50-7</strong></p>
<p><strong>AN. JUNIRULLAH</strong></p>
</div>
<p class="text-text-muted mt-4 mb-2 text-sm sm:text-base">Kirim Bukti Pembayaran
Melalui WhatsApp: <a href="https://wa.me/6282164715377" target="_blank" class="text-green-
400 hover:text-green-300 transition-colors"><span>+62821 - 6471 - 5377</span></a></p>
<p class="text-text-muted mt-4 text-xs sm:text-sm">Maka Setelah Bukti Transfer
dikirim melalui nomor tersebut, Lalu Team PEMBUAT.com Antivirus akan mengirimkan Aplikasi
Pro. PEMBUAT.com Antivirus Versi.FULL.JALiN.KB.PRO kepada Anda untuk dapat langsung
Anda Aktifkan melalui browser di semua perangkat teknologi yang Anda gunakan.</p>
<p class="text-text-muted mt-2 text-xs sm:text-sm">Atas dukungannya semua kami
ucapkan terima kasih.</p>
</div>
<!-- Bagian Dukungan -->
<div class="support-section" id="support-section">
<h3 class="text-xl sm:text-2xl font-bold text-accent-blue mb-4">Dapatkan Dukungan
untuk PEMBUAT Antivirus</h3>
<p class="text-text-muted mb-4 text-sm sm:text-base">
PEMBUAT Antivirus Gratis adalah perangkat lunak keamanan esensial kami untuk
menghentikan malware, spyware, dan ransomware tanpa memperlambat PC Anda.
</p>
<h4 class="text-lg font-semibold text-text-light mt-6 mb-3 text-left">Penggunaan
Dasar</h4>
<ul class="mb-4">
<li>
<strong class="text-text-light">PEMBUAT Premium Security dan PEMBUAT
Antivirus untuk Windows - FAQ</strong>
<span class="text-sm text-text-muted block mt-1">Dapatkan jawaban cepat untuk
pertanyaan umum tentang fitur keamanan premium dan dasar PEMBUAT Antivirus di Windows.
Temukan solusi untuk pertanyaan umum terkait instalasi, konfigurasi, dan pemecahan
masalah.</span>
</li>
<li>
43. <strong class="text-text-light">Menginstal PEMBUAT Antivirus Gratis</strong>
<span class="text-sm text-text-muted block mt-1">Panduan langkah demi
langkah yang mudah diikuti untuk pemasangan PEMBUAT Antivirus Free di perangkat Anda.
Pastikan instalasi yang benar untuk perlindungan maksimal sejak awal.</span>
</li>
<li>
<strong class="text-text-light">Pelajari lebih lanjut tentang pemindaian virus di
PEMBUAT Antivirus</strong>
<span class="text-sm text-text-muted block mt-1">Pahami berbagai jenis
pemindaian yang tersedia (cepat, penuh, kustom) dan cara kerjanya untuk perlindungan optimal
terhadap ancaman.</span>
</li>
<li>
<strong class="text-text-light">Menyesuaikan pengaturan untuk PEMBUAT
Antivirus Core Shields</strong>
<span class="text-sm text-text-muted block mt-1">Konfigurasi perisai inti
PEMBUAT (Perisai File, Perisai Web, Perisai Email) untuk perlindungan real-time yang
disesuaikan dengan kebutuhan dan gaya penggunaan Anda.</span>
</li>
<li>
<strong class="text-text-light">PEMBUAT Firewall - Memulai</strong>
<span class="text-sm text-text-muted block mt-1">Panduan awal untuk
mengamankan koneksi jaringan Anda. Pelajari cara mengontrol lalu lintas masuk dan keluar
untuk mencegah akses tidak sah.</span>
</li>
</ul>
<h4 class="text-lg font-semibold text-text-light mt-6 mb-3 text-left">Langganan dan
Pembelian</h4>
<ul class="mb-4">
<li>
<strong class="text-text-light">Menemukan nomor ID pesanan PEMBUAT
Anda</strong>
<span class="text-sm text-text-muted block mt-1">Cara mudah menemukan ID
pesanan Anda yang diperlukan untuk dukungan teknis, perpanjangan langganan, atau
manajemen akun.</span>
</li>
<li>
<strong class="text-text-light">Mengaktifkan PEMBUAT Antivirus Gratis</strong>
<span class="text-sm text-text-muted block mt-1">Petunjuk lengkap untuk
mengaktifkan lisensi PEMBUAT Antivirus Free Anda dan memastikan semua fitur keamanan
berfungsi penuh.</span>
</li>
<li>
<strong class="text-text-light">Akun PEMBUAT - FAQ</strong>
<span class="text-sm text-text-muted block mt-1">Pertanyaan dan jawaban
seputar pengelolaan akun PEMBUAT Anda, termasuk cara masuk, mengubah detail, dan
mengelola langganan.</span>
</li>
<li>
<strong class="text-text-light">Mentransfer langganan PEMBUAT ke perangkat
lain</strong>
<span class="text-sm text-text-muted block mt-1">Panduan untuk memindahkan
lisensi PEMBUAT Anda dari satu perangkat ke perangkat baru dengan mudah dan tanpa
hambatan.</span>
</li>
<li>
<strong class="text-text-light">Membatalkan langganan PEMBUAT -
FAQ</strong>
<span class="text-sm text-text-muted block mt-1">Informasi terperinci tentang
proses pembatalan langganan PEMBUAT Anda, termasuk kebijakan pengembalian dana jika
berlaku.</span>
</li>
</ul>
<h4 class="text-lg font-semibold text-text-light mt-6 mb-3 text-left">Masalah
Teknis</h4>
<ul class="mb-4">
<li>
<strong class="text-text-light">Mengelola notifikasi pop-up di produk
44. PEMBUAT</strong>
<span class="text-sm text-text-muted block mt-1">Sesuaikan preferensi notifikasi
pop-up dari PEMBUAT Antivirus agar tidak mengganggu pengalaman penggunaan
Anda.</span>
</li>
<li>
<strong class="text-text-light">Pemecahan masalah ketika komponen PEMBUAT
Antivirus tidak berfungsi dengan baik</strong>
<span class="text-sm text-text-muted block mt-1">Solusi umum dan langkah-
langkah diagnostik untuk mengatasi masalah fungsi komponen PEMBUAT Antivirus yang tidak
responsif atau error.</span>
</li>
<li>
<strong class="text-text-light">Mengecualikan file atau situs web tertentu dari
pemindaian di PEMBUAT Antivirus</strong>
<span class="text-sm text-text-muted block mt-1">Atur pengecualian untuk file
atau situs web yang Anda percaya agar tidak dipindai, menghindari deteksi palsu dan
mempercepat pemindaian.</span>
</li>
<li>
<strong class="text-text-light">Memperbaiki PEMBUAT Antivirus atau PEMBUAT
One</strong>
<span class="text-sm text-text-muted block mt-1">Langkah-langkah perbaikan
mandiri untuk mengatasi kerusakan atau masalah pada instalasi PEMBUAT Antivirus atau
PEMBUAT One.</span>
</li>
<li>
<strong class="text-text-light">Mencopot pemasangan PEMBUAT Antivirus
Gratis</strong>
<span class="text-sm text-text-muted block mt-1">Panduan lengkap dan aman
untuk menghapus PEMBUAT Antivirus Free dari perangkat Anda, memastikan tidak ada sisa file
yang tertinggal.</span>
</li>
</ul>
<p class="text-text-muted mt-6 mb-2 text-sm sm:text-base">Butuh bantuan
tambahan?</p>
<a href="https://wa.me/6282164715377" target="_blank" class="contact-link inline-flex
items-center justify-content-center bg-accent-blue text-white px-4 py-2 rounded-xl font-semibold
text-base sm:text-lg no-underline shadow-md hover:bg-blue-700 transform hover:-translate-y-1
transition-all" onclick="playClingSound();">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"
width="20px" height="20px" class="mr-2">
<path d="M20 2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V4c0-
1.1-.9-2-2-2zm-1 16H5V6h14v12zM6.5 7.5h11V9h-11zm0 2.5h11V11h-11zm0 2.5h11V13h-
11zm0 2.5h11V15h-11z"/>
</svg>
Hubungi kami
</a>
</div>
<!-- Bagian Pemantauan Temperatur dan Gelombang -->
<div class="monitor-section" id="monitor-section">
<h3 class="text-xl sm:text-2xl font-bold text-accent-purple mb-4">Pemantauan
Perangkat Real-time</h3>
<p class="text-text-muted mb-4 text-sm sm:text-base">
Pantau temperatur dan beban memori perangkat Anda untuk mencegah beban
berlebih pada prosesor.
</p>
<div class="monitor-canvas-container">
<canvas id="monitorCanvas"></canvas> <!-- Removed fixed width/height -->
</div>
<div class="monitor-readings">
<div class="monitor-reading-item">
<span>Temperatur:</span>
<span id="temp-reading">--°C</span>
</div>
<div class="monitor-reading-item">
<span>Beban Memori:</span>
<span id="memory-load-reading">--%</span>
46. <ul class="modal-threat-list" id="modal-threat-list">
<!-- Daftar ancaman akan dimasukkan di sini oleh JavaScript -->
</ul>
<button class="modal-recover-all-button" id="modal-recover-all-button"
onclick="playClingSound();">Pulihkan Semua</button>
</div>
</div>
<!-- Welcome/First Scan Popup (tetap ada) -->
<div class="welcome-modal-overlay" id="welcome-modal-overlay">
<div class="welcome-modal-content">
<h3>Selamat Datang di PEMBUAT.com Antivirus!</h3>
<p>Lindungi perangkat Anda dari ancaman digital. Mulai pemindaian pertama Anda
sekarang untuk memastikan keamanan sistem.</p>
<div class="welcome-modal-buttons">
<button class="welcome-modal-button primary" onclick="startFirstScan();
playClingSound();">Mulai Pemindaian Sekarang</button>
<button class="welcome-modal-button secondary" onclick="closeWelcomePopup();
playClingSound();">Nanti Saja</button>
</div>
</div>
</div>
<!-- Custom Alert Modal (kept for general alerts not specific to reports) -->
<div class="custom-modal-overlay" id="custom-alert-modal-overlay">
<div class="custom-modal-content">
<h4 id="custom-alert-title">Peringatan!</h4>
<p id="custom-alert-message"></p>
<div class="custom-modal-buttons">
<button class="custom-modal-button primary" onclick="closeCustomAlert();
playClingSound();">OK</button>
</div>
</div>
</div>
<!-- Custom Confirm Modal (kept for general confirms not specific to reports) -->
<div class="custom-modal-overlay" id="custom-confirm-modal-overlay">
<div class="custom-modal-content">
<h4 id="custom-confirm-title">Konfirmasi</h4>
<p id="custom-confirm-message"></p>
<div class="custom-modal-buttons">
<button class="custom-modal-button primary" id="custom-confirm-ok"
onclick="playClingSound();">OK</button>
<button class="custom-modal-button secondary" id="custom-confirm-cancel"
onclick="playClingSound();">Batal</button>
</div>
</div>
</div>
<!-- Custom Input Modal (kept for general inputs not specific to reports) -->
<div class="custom-modal-overlay" id="custom-input-modal-overlay">
<div class="custom-modal-content custom-input-modal-content">
<h4 id="custom-input-title">Masukkan Data</h4>
<p id="custom-input-message"></p>
<input type="text" id="custom-input-field" placeholder="">
<div class="custom-modal-buttons">
<button class="custom-modal-button primary" id="custom-input-ok"
onclick="playClingSound();">OK</button>
<button class="custom-modal-button secondary" id="custom-input-cancel"
onclick="playClingSound();">Batal</button>
</div>
</div>
</div>
<script>
// Objek untuk menyimpan interval pemindaian agar bisa dibersihkan
let scanIntervals = {};
let currentScannedDevice = '';
let scanHistory = [];
let threatLevelChart;
47. // Array untuk menyimpan notifikasi
let notifications = [];
// Referensi elemen animasi pemindaian
const scanAnimationArea = document.getElementById('scan-animation-area');
// Daftar simulasi ancaman dengan deskripsi dan solusi
const simulatedThreats = [
{ name: 'Malware.Generic', description: 'Malware umum yang dapat merusak file sistem.',
solution: 'Hapus file yang terinfeksi dan perbarui definisi virus.' },
{ name: 'Phishing.URL', description: 'Upaya penipuan untuk mendapatkan informasi
pribadi melalui tautan palsu.', solution: 'Jangan klik tautan mencurigakan dan laporkan situs
phishing.' },
{ name: 'Adware.Popups', description: 'Perangkat lunak yang menampilkan iklan pop-up
yang tidak diinginkan.', solution: 'Hapus program adware dan gunakan pemblokir iklan.' },
{ name: 'Spyware.Keylogger', description: 'Program yang merekam setiap ketikan
keyboard Anda.', solution: 'Gunakan anti-spyware untuk mendeteksi dan menghapus keylogger.'
},
{ name: 'Network.Intruder', description: 'Akses tidak sah ke jaringan Anda.', solution:
'Ubah kata sandi jaringan, gunakan enkripsi kuat, dan pantau aktivitas jaringan.' },
{ name: 'Spam.Email', description: 'Email yang tidak diminta, seringkali berisi tautan
berbahaya atau penipuan.', solution: 'Tandai sebagai spam, jangan buka tautan, dan gunakan
filter spam.' },
{ name: 'Netcut.Activity', description: 'Perangkat lunak yang memutus koneksi internet
perangkat lain di jaringan yang sama.', solution: 'Gunakan alat pelindung ARP spoofing dan
pantau jaringan Anda.' },
{ name: 'Ransomware.Lock', description: 'Malware yang mengunci file Anda dan
meminta tebusan.', solution: 'Jangan bayar tebusan. Pulihkan dari cadangan atau gunakan alat
dekripsi jika tersedia.' },
{ name: 'Trojan.Downloader', description: 'Program berbahaya yang mengunduh
malware lain ke sistem Anda.', solution: 'Pindai sistem secara menyeluruh dan hapus trojan.' },
{ name: 'Rootkit.Stealth', description: 'Jenis malware yang dirancang untuk
menyembunyikan keberadaannya di sistem.', solution: 'Gunakan alat deteksi rootkit khusus atau
instal ulang sistem.' },
{ name: 'Exploit.CVE-2023', description: 'Kerentanan perangkat lunak yang dieksploitasi
untuk mendapatkan akses tidak sah.', solution: 'Perbarui semua perangkat lunak dan sistem
operasi ke versi terbaru.' },
{ name: 'Botnet.Agent', description: 'Perangkat Anda menjadi bagian dari jaringan
komputer yang dikendalikan oleh penyerang.', solution: 'Pindai dan bersihkan sistem, lalu
perkuat keamanan jaringan.' }
];
// Fungsi untuk menginisialisasi Web Speech API
const synth = window.speechSynthesis;
let indonesianFemaleVoice = null;
function getIndonesianFemaleVoice() {
if (!synth) {
console.warn("Web Speech API tidak didukung oleh browser ini.");
return null;
}
const voices = synth.getVoices();
let foundVoice = voices.find(voice =>
(voice.lang === 'id-ID' || voice.name.toLowerCase().includes('indonesian')) &&
(voice.name.toLowerCase().includes('female') ||
voice.name.toLowerCase().includes('wanita') || voice.name.toLowerCase().includes('f')));
if (!foundVoice) {
foundVoice = voices.find(voice => voice.lang === 'id-ID' ||
voice.name.toLowerCase().includes('indonesian'));
}
if (!foundVoice) {
console.warn("Suara Bahasa Indonesia tidak ditemukan. Menggunakan suara default
atau suara pertama yang tersedia.");
foundVoice = voices.find(voice => voice.default) || voices[0];
}
indonesianFemaleVoice = foundVoice;
48. if (!indonesianFemaleVoice) {
console.error("Tidak ada suara yang tersedia sama sekali.");
} else {
console.log("Menggunakan suara:", indonesianFemaleVoice.name);
}
return indonesianFemaleVoice;
}
if (synth) {
synth.onvoiceschanged = () => {
getIndonesianFemaleVoice();
};
if (synth.getVoices().length > 0) {
getIndonesianFemaleVoice();
}
}
// Tone.js setup for "cling" sound
let clingSynth;
let clingReverb;
let isClingSoundPlaying = false; // Flag to prevent overlapping cling sounds
// Tone.js setup for "radio wave" sound
let radioWaveNoise;
let radioWaveFilter;
let radioWaveAutoFilter;
let isRadioWaveSoundPlaying = false; // Flag to prevent overlapping radio wave sounds
// Initialize Tone.js components when the document is ready
document.addEventListener('DOMContentLoaded', () => {
// Only initialize if Tone is available
if (typeof Tone !== 'undefined') {
// Set up a simple synth for the "cling" sound
clingSynth = new Tone.Synth({
oscillator: {
type: "sine" // A simple sine wave for a clean sound
},
envelope: {
attack: 0.001,
decay: 0.1,
sustain: 0.0,
release: 0.1
}
}).toDestination(); // Connect directly to speakers
// Add a small reverb for a more "metallic" cling sound
clingReverb = new Tone.Reverb({
decay: 0.5, // Shorter decay
preDelay: 0.01,
wet: 0.2 // A little bit of reverb
}).toDestination();
// Connect synth to reverb, then reverb to master output
clingSynth.connect(clingReverb);
clingReverb.toDestination();
// Setup for radio wave sound
radioWaveNoise = new Tone.Noise("white");
radioWaveFilter = new Tone.Filter(1000, "bandpass");
radioWaveAutoFilter = new Tone.AutoFilter({
frequency: "8n", // How fast the filter sweeps
depth: 1,
baseFrequency: 200,
octaves: 2.5,
type: "sine"
});
radioWaveNoise.connect(radioWaveAutoFilter);
radioWaveAutoFilter.connect(radioWaveFilter);
radioWaveFilter.toDestination();
49. radioWaveNoise.volume.value = -Infinity; // Start muted
// Start Tone.js context on first user interaction
document.documentElement.addEventListener('mousedown', Tone.start);
document.documentElement.addEventListener('touchstart', Tone.start);
} else {
console.warn("Tone.js not loaded. Cling sound and radio wave sound will not play.");
}
});
// Function to play the "cling" sound
function playClingSound() {
if (clingSynth && !isClingSoundPlaying) {
isClingSoundPlaying = true;
const now = Tone.now();
// Play a high-pitched note for a short duration at the current Tone.js time
clingSynth.triggerAttackRelease("C6", "8n", now); // Use 'now' as the start time
setTimeout(() => {
isClingSoundPlaying = false;
}, 200); // Allow re-triggering after 200ms (slightly longer than the sound duration)
}
}
// Function to play the "radio wave" sound
function playRadioWaveSound() {
if (radioWaveNoise && radioWaveAutoFilter && !isRadioWaveSoundPlaying) {
isRadioWaveSoundPlaying = true;
const now = Tone.now();
radioWaveNoise.volume.value = -10; // Unmute the noise
radioWaveNoise.start(now); // Start the noise at current time
radioWaveAutoFilter.start(now); // Start the filter modulation at current time
// Stop after a short duration
setTimeout(() => {
radioWaveNoise.stop(now + 1.5); // Stop noise after 1.5 seconds from now
radioWaveAutoFilter.stop(now + 1.5); // Stop filter after 1.5 seconds from now
radioWaveNoise.volume.value = -Infinity; // Ensure it's muted
isRadioWaveSoundPlaying = false;
}, 1500); // Play for 1.5 seconds
}
}
// Modified to use addNotification with speak: true for specific events
function speakThreatDetected() {
addNotification('threat', 'Ancaman terdeteksi pada sistem Anda.', true); // Voice enabled
}
// Modified to use addNotification with speak: true for specific events
function speakScanComplete() {
addNotification('info', 'Sistem Anda kini aman. Semua masalah telah berhasil
dipulihkan.', true); // Voice enabled
}
const currentScanTitle = document.getElementById('current-scan-title');
const currentScanStatus = document.getElementById('current-scan-status');
const detailedThreatResults = document.getElementById('detailed-threat-results');
const threatListContainer = document.getElementById('threat-list-container');
const detailedRecoverAllButton = document.getElementById('detailed-recover-all-button');
const scanButtons = document.querySelectorAll('.scan-button-item');
const shieldToggleButton = document.getElementById('shield-toggle-button');
const radioWaveScanButton = document.getElementById('radio-wave-scan-button'); // New
button reference
const ipDetectionButton = document.getElementById('ip-detection-button'); // New button
reference
const soundEnergyButton = document.getElementById('sound-energy-button'); // New
button reference for sound wave scan (renamed)
const welcomeModalOverlay = document.getElementById('welcome-modal-overlay');
const threatModalOverlay = document.getElementById('threat-modal-overlay');
50. const currentScanCard = document.getElementById('current-scan-card');
const donateSection = document.getElementById('donate-section');
const supportSection = document.getElementById('support-section');
const monitorSection = document.getElementById('monitor-section'); // New monitor
section
// New button elements
const updateFreeButton = document.getElementById('update-free-button');
const updateFreeText = document.getElementById('update-free-text');
const upgradeProButton = document.getElementById('upgrade-pro-button');
const upgradeProText = document.getElementById('upgrade-pro-text');
// Notification elements
const notificationBadge = document.getElementById('notification-badge');
// Custom modal elements (kept for general alerts/confirms, not specific reports)
const customAlertModalOverlay = document.getElementById('custom-alert-modal-overlay');
const customAlertMessage = document.getElementById('custom-alert-message');
const customConfirmModalOverlay = document.getElementById('custom-confirm-modal-
overlay');
const customConfirmMessage = document.getElementById('custom-confirm-message');
const customConfirmOkButton = document.getElementById('custom-confirm-ok');
const customConfirmCancelButton = document.getElementById('custom-confirm-cancel');
let confirmCallback = null; // To store the callback for custom confirm
// Custom Input Modal elements (kept for general inputs, not specific reports)
const customInputModalOverlay = document.getElementById('custom-input-modal-
overlay');
const customInputTitle = document.getElementById('custom-input-title');
const customInputMessage = document.getElementById('custom-input-message');
const customInputField = document.getElementById('custom-input-field');
const customInputOkButton = document.getElementById('custom-input-ok');
const customInputCancelButton = document.getElementById('custom-input-cancel');
let inputCallback = null; // To store the callback for custom input
// Monitor elements
const monitorCanvas = document.getElementById('monitorCanvas');
const monitorCtx = monitorCanvas.getContext('2d');
const tempReading = document.getElementById('temp-reading');
const memoryLoadReading = document.getElementById('memory-load-reading'); //
Renamed from waveReading
const monitorStatusText = document.getElementById('monitor-status-text');
let currentTemp = 45; // Initial temperature
let currentMemoryLoad = 50; // Initial memory load (was wave intensity)
let isBalancingActive = false; // New state for balancing feature
// Application Reports Section elements (NEW)
const applicationReportsSection = document.getElementById('application-reports-section');
const reportContent = document.getElementById('report-content');
// Inline Notification Section elements (NEW)
const inlineNotificationsSection = document.getElementById('inline-notifications-section');
const inlineNotificationList = document.getElementById('inline-notification-list');
const noInlineNotificationsMessage = document.getElementById('no-inline-notifications-
message');
// Subtitle element
const framedSubtitle = document.getElementById('framed-subtitle');
// Arabic text container
const arabicTextContainer = document.querySelector('.arabic-text-container');
// Network animation canvas elements
const networkAnimationCanvas = document.getElementById('network-animation-canvas');
const networkCtx = networkAnimationCanvas.getContext('2d');
let particles = [];
const numParticles = 50;
const particleSpeed = 0.5;
const connectionDistance = 100;
51. // Correct Pro Key
const CORRECT_PRO_KEY = 'LIAN-AJUN-CAKE-OIOI-1710';
/**
* Shows a custom alert modal.
* @param {string} message - The message to display.
* @param {string} [title='Peringatan!'] - The title of the alert.
*/
function showAlert(message, title = 'Peringatan!') {
document.getElementById('custom-alert-title').textContent = title;
customAlertMessage.textContent = message;
customAlertModalOverlay.classList.add('show');
}
/**
* Closes the custom alert modal.
*/
function closeCustomAlert() {
customAlertModalOverlay.classList.remove('show');
}
/**
* Shows a custom confirm modal.
* @param {string} message - The message to display.
* @param {Function} callback - The function to call with true/false based on user choice.
* @param {string} [title='Konfirmasi'] - The title of the confirm dialog.
*/
function showConfirm(message, callback, title = 'Konfirmasi') {
document.getElementById('custom-confirm-title').textContent = title;
customConfirmMessage.textContent = message;
confirmCallback = callback;
customConfirmModalOverlay.classList.add('show');
}
// Event listeners for custom confirm buttons
customConfirmOkButton.addEventListener('click', () => {
if (confirmCallback) {
confirmCallback(true);
}
customConfirmModalOverlay.classList.remove('show');
confirmCallback = null;
});
customConfirmCancelButton.addEventListener('click', () => {
if (confirmCallback) {
confirmCallback(false);
}
customConfirmModalOverlay.classList.remove('show');
confirmCallback = null;
});
/**
* Shows a custom input modal.
* @param {string} title - The title of the input modal.
* @param {string} message - The message to display.
* @param {string} placeholder - The placeholder text for the input field.
* @param {Function} callback - The function to call with the input value (string) or null if
canceled.
*/
function showInputModal(title, message, placeholder, callback) {
customInputTitle.textContent = title;
customInputMessage.textContent = message;
customInputField.value = ''; // Clear previous input
customInputField.placeholder = placeholder;
inputCallback = callback;
customInputModalOverlay.classList.add('show');
customInputField.focus(); // Focus the input field
53. }
},
x: {
title: {
display: true,
text: 'Pemindaian',
color: 'var(--text-muted)'
},
ticks: {
color: 'var(--text-muted)'
},
grid: {
color: 'rgba(255, 255, 255, 0.05)'
}
}
},
plugins: {
tooltip: {
callbacks: {
label: function(context) {
return `Tingkat Bahaya: ${context.raw}%`;
}
},
backgroundColor: 'rgba(0, 0, 0, 0.7)',
titleColor: 'white',
bodyColor: 'white'
},
legend: {
labels: {
color: 'var(--text-light)'
}
}
}
}
});
const hasScanned = localStorage.getItem('hasScannedBefore');
if (!hasScanned) {
showWelcomePopup();
}
// Load notifications from localStorage
const storedNotifications = localStorage.getItem('notifications');
if (storedNotifications) {
notifications = JSON.parse(storedNotifications);
}
updateNotificationBadge();
// Initialize update and upgrade status on load
checkVersionStatus();
// Add event listeners for the new buttons
updateFreeButton.addEventListener('click', () => { performFreeUpdate();
playClingSound(); });
upgradeProButton.addEventListener('click', () => { initiateProUpgrade();
playClingSound(); });
radioWaveScanButton.addEventListener('click', () => { startRadioWaveScan();
playClingSound(); });
ipDetectionButton.addEventListener('click', () => { detectAttackerIP();
playClingSound(); }); // Add event listener for new IP button
soundEnergyButton.addEventListener('click', () => { startSoundWaveScan();
playClingSound(); }); // Add event listener for new sound wave scan
// Set up daily report interval (simulated for 30 seconds for demo purposes)
// In a real app, this would be 24 hours (24 * 60 * 60 * 1000)
setInterval(generateDailyReport, 30 * 1000); // Check every 30 seconds for demo
generateDailyReport(); // Run once on load
// Start monitor animation loop
startMonitorAnimation();
54. // Initial canvas resize and add event listener
resizeMonitorCanvas();
window.addEventListener('resize', resizeMonitorCanvas);
// Initialize and start network animation
initNetworkAnimation();
window.addEventListener('resize', resizeNetworkCanvas);
});
function updateChart(isSafe = false) {
const labels = scanHistory.map((scan, index) => `Scan ${index + 1}`);
const data = scanHistory.map(scan => scan.threatLevel);
threatLevelChart.data.labels = labels;
threatLevelChart.data.datasets[0].data = data;
if (isSafe) {
threatLevelChart.data.datasets[0].borderColor = 'var(--safe-green)';
threatLevelChart.data.datasets[0].backgroundColor = 'rgba(56, 161, 105, 0.2)';
threatLevelChart.data.datasets[0].pointBorderColor = 'var(--safe-green)';
threatLevelChart.data.datasets[0].pointHoverBorderColor = 'var(--safe-green)';
} else {
threatLevelChart.data.datasets[0].borderColor = 'var(--threat-red)';
threatLevelChart.data.datasets[0].backgroundColor = 'rgba(229, 62, 62, 0.2)';
threatLevelChart.data.datasets[0].pointBorderColor = 'var(--threat-red)';
threatLevelChart.data.datasets[0].pointHoverBorderColor = 'var(--threat-red)';
}
threatLevelChart.update();
}
/**
* Displays a report in the dedicated application reports section.
* Clears previous content and shows the section.
* @param {string} title - The title of the report.
* @param {string} contentHtml - The HTML content of the report.
* @param {string} [type='info'] - Type of report for styling ('info', 'success', 'warning', 'error').
*/
function displayApplicationReport(title, contentHtml, type = 'info') {
reportContent.innerHTML = `
<div class="report-item ${type}">
<div class="report-title">${title}</div>
<div>${contentHtml}</div>
</div>
`;
applicationReportsSection.style.display = 'flex'; // Show the section
// Scroll to the new report
applicationReportsSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
/**
* Clears the application reports section.
*/
function clearApplicationReports() {
reportContent.innerHTML = '<p class="text-text-muted text-center">Tidak ada laporan
terbaru.</p>';
applicationReportsSection.style.display = 'none'; // Hide the section when empty
}
function startScan(device) {
localStorage.setItem('hasScannedBefore', 'true');
scanButtons.forEach(button => button.classList.add('disabled'));
radioWaveScanButton.classList.add('disabled'); // Disable radio wave scan button too
ipDetectionButton.classList.add('disabled'); // Disable IP detection button too
soundEnergyButton.classList.add('disabled'); // Disable sound energy button too
currentScannedDevice = device;
55. // Hide other sections, show scan card, clear reports
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
currentScanCard.style.display = 'flex'; // Ensure scan card is visible
detailedThreatResults.style.display = 'none'; // Hide detailed threats initially
threatListContainer.innerHTML = '';
currentScanTitle.textContent = `Memindai ${device}...`;
currentScanStatus.textContent = 'Memulai pemindaian...';
currentScanStatus.style.color = 'var(--text-muted)';
// Start scan animation
scanAnimationArea.classList.add('scanning');
setTimeout(() => {
let threatLevel;
let detectedThreats = [];
let movementDetected = false;
if (shieldToggleButton.classList.contains('active')) {
threatLevel = 0;
detectedThreats = [];
} else {
threatLevel = Math.floor(Math.random() * 80) + 5;
if (threatLevel > 20) {
const numThreats = Math.min(Math.floor(threatLevel / 20),
simulatedThreats.length);
const shuffledThreats = simulatedThreats.sort(() => 0.5 - Math.random());
detectedThreats = shuffledThreats.slice(0, numThreats);
}
// Simulate dangerous movement detection
if (Math.random() < 0.3) { // 30% chance of detecting dangerous movement
movementDetected = true;
}
}
scanHistory.push({
device: device,
threatLevel: threatLevel,
threats: detectedThreats,
movementDetected: movementDetected,
timestamp: new Date().toLocaleString()
});
// Stop scan animation
scanAnimationArea.classList.remove('scanning');
if (detectedThreats.length > 0) {
currentScanStatus.textContent = `Pemindaian ${device} selesai! Ancaman
terdeteksi dengan tingkat bahaya: ${threatLevel}%.`;
currentScanStatus.style.color = 'var(--threat-red)';
speakThreatDetected(); // This now calls addNotification with speak: true
displayDetailedThreats(detectedThreats);
updateChart(false);
addNotification('threat', `Ancaman terdeteksi pada ${device} dengan tingkat bahaya
${threatLevel}%.`, true); // Voice enabled
} else {
currentScanStatus.textContent = `Pemindaian ${device} selesai! Tidak ada
ancaman ditemukan. Tingkat bahaya: ${threatLevel}%.`;
currentScanStatus.style.color = 'var(--safe-green)';
speakScanComplete(); // This now calls addNotification with speak: true
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled'); // Re-enable radio wave scan
button
ipDetectionButton.classList.remove('disabled'); // Re-enable IP detection button
soundEnergyButton.classList.remove('disabled'); // Re-enable sound energy button
56. detailedThreatResults.style.display = 'none';
updateChart(true);
addNotification('info', `Pemindaian ${device} selesai tanpa ancaman. Sistem
aman.`, true); // Voice enabled
}
if (movementDetected) {
addNotification('movement', `Pergerakan berbahaya terdeteksi di ${device}!`,
true); // Voice enabled
}
}, 3000);
}
// New function for Radio Wave Scan
function startRadioWaveScan() {
localStorage.setItem('hasScannedBefore', 'true');
scanButtons.forEach(button => button.classList.add('disabled'));
radioWaveScanButton.classList.add('disabled'); // Disable itself
ipDetectionButton.classList.add('disabled'); // Disable IP detection button too
soundEnergyButton.classList.add('disabled'); // Disable sound energy button too
currentScannedDevice = 'Gelombang Radio';
// Hide other sections, show scan card, clear reports
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
currentScanCard.style.display = 'flex';
detailedThreatResults.style.display = 'none';
threatListContainer.innerHTML = '';
currentScanTitle.textContent = `Memindai Gelombang Radio...`;
currentScanStatus.textContent = 'Mendeteksi gelombang aktif di seluruh perangkat...';
currentScanStatus.style.color = 'var(--text-muted)';
// Start scan animation
scanAnimationArea.classList.add('scanning');
playRadioWaveSound(); // Play radio wave sound
setTimeout(() => {
let detectedWaves = [];
let hasIssues = false;
if (Math.random() < 0.7) { // 70% chance of detecting active radio waves
detectedWaves.push('Gelombang Radio Aktif');
addNotification('radio_wave', 'Gelombang Radio Aktif terdeteksi.', true);
}
if (Math.random() < 0.6) { // 60% chance of detecting active frequency waves
detectedWaves.push('Gelombang Frekuensi Aktif');
addNotification('frequency_wave', 'Gelombang Frekuensi Aktif terdeteksi.', true);
}
if (Math.random() < 0.8) { // 80% chance of detecting active internet network waves
detectedWaves.push('Gelombang Jaringan Internet Aktif');
addNotification('internet_wave', 'Gelombang Jaringan Internet Aktif terdeteksi.',
true);
}
// Simulate some "threats" related to unusual wave activity if any are detected
let simulatedThreatsForWaves = [];
if (detectedWaves.length > 0 && Math.random() < 0.4) { // 40% chance of a related
threat
simulatedThreatsForWaves.push({ name: 'Interferensi Sinyal', description:
'Beberapa gelombang menunjukkan interferensi yang tidak biasa.', solution: 'Periksa sumber
interferensi atau sesuaikan pengaturan jaringan.' });
hasIssues = true;
}
57. if (detectedWaves.length > 1 && Math.random() < 0.2) { // 20% chance of another
related threat
simulatedThreatsForWaves.push({ name: 'Penyalahgunaan Bandwidth', description:
'Deteksi aktivitas jaringan yang tidak sah atau penggunaan bandwidth berlebihan.', solution:
'Identifikasi perangkat yang mencurigakan dan batasi aksesnya.' });
hasIssues = true;
}
scanHistory.push({
device: 'Gelombang Radio',
threatLevel: hasIssues ? 30 : 0, // Assign a low threat level if issues are found
threats: simulatedThreatsForWaves,
movementDetected: false,
timestamp: new Date().toLocaleString()
});
// Stop scan animation
scanAnimationArea.classList.remove('scanning');
let reportHtml = '';
let reportType = 'info';
if (hasIssues) {
currentScanStatus.textContent = `Pemindaian Gelombang Radio selesai! Beberapa
anomali terdeteksi.`;
currentScanStatus.style.color = 'var(--threat-red)';
speakThreatDetected();
displayDetailedThreats(simulatedThreatsForWaves);
updateChart(false);
reportHtml += `<p class="text-threat-red font-semibold">Anomali Terdeteksi:</p>`;
simulatedThreatsForWaves.forEach(threat => {
reportHtml += `<p><strong>${threat.name}:</strong> ${threat.description}</p>`;
});
reportType = 'error';
} else if (detectedWaves.length > 0) {
currentScanStatus.textContent = `Pemindaian Gelombang Radio selesai!
Gelombang aktif terdeteksi: ${detectedWaves.join(', ')}. Tidak ada anomali serius.`;
currentScanStatus.style.color = 'var(--safe-green)';
speakScanComplete();
detailedThreatResults.style.display = 'none';
updateChart(true);
reportHtml += `<p class="text-safe-green font-semibold">Gelombang Aktif
Terdeteksi:</p>`;
detectedWaves.forEach(wave => {
reportHtml += `<p>${wave}</p>`;
});
reportHtml += `<p>Tidak ada anomali serius yang ditemukan.</p>`;
reportType = 'success';
} else {
currentScanStatus.textContent = `Pemindaian Gelombang Radio selesai! Tidak ada
gelombang aktif terdeteksi.`;
currentScanStatus.style.color = 'var(--safe-green)';
speakScanComplete();
detailedThreatResults.style.display = 'none';
updateChart(true);
reportHtml += `<p>Tidak ada gelombang aktif terdeteksi di sekitar perangkat
Anda.</p>`;
reportType = 'info';
}
displayApplicationReport('Laporan Pemindaian Gelombang Radio', reportHtml,
reportType);
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled'); // Re-enable itself
ipDetectionButton.classList.remove('disabled'); // Re-enable IP detection button
soundEnergyButton.classList.remove('disabled'); // Re-enable sound energy button
}, 4000); // Longer timeout for radio wave scan
}
58. // New function to detect attacker IP and show on map (simulated)
function detectAttackerIP() {
localStorage.setItem('hasScannedBefore', 'true');
scanButtons.forEach(button => button.classList.add('disabled'));
radioWaveScanButton.classList.add('disabled');
ipDetectionButton.classList.add('disabled'); // Disable itself
soundEnergyButton.classList.add('disabled'); // Disable sound energy button too
currentScannedDevice = 'Deteksi IP Penyerang';
// Hide other sections, show scan card, clear reports
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
currentScanCard.style.display = 'flex';
detailedThreatResults.style.display = 'none';
threatListContainer.innerHTML = '';
currentScanTitle.textContent = `Mendeteksi IP Penyerang...`;
currentScanStatus.textContent = 'Menganalisis lalu lintas jaringan untuk aktivitas
mencurigakan...';
currentScanStatus.style.color = 'var(--text-muted)';
// Start scan animation
scanAnimationArea.classList.add('scanning');
setTimeout(() => {
const attackerTypes = ['Hacker', 'Spammer', 'Phishing', 'Penelpon', 'Telepon Seluler
Terkoneksi'];
const simulatedLocations = [
{ city: 'New York', country: 'USA', address: '123 Main St, New York' },
{ city: 'Berlin', country: 'Germany', address: 'Karl-Marx-Allee 10, Berlin' },
{ city: 'Tokyo', country: 'Japan', address: 'Shibuya Crossing, Tokyo' },
{ city: 'Jakarta', country: 'Indonesia', address: 'Jl. Sudirman 1, Jakarta' },
{ city: 'Moscow', country: 'Russia', address: 'Red Square, Moscow' },
{ city: 'Beijing', country: 'China', address: 'Tiananmen Square, Beijing' },
{ city: 'London', country: 'UK', address: 'Baker Street 221B, London' },
{ city: 'Paris', country: 'France', address: 'Eiffel Tower Area, Paris' }
];
const randomAttackerType = attackerTypes[Math.floor(Math.random() *
attackerTypes.length)];
const randomLocation = simulatedLocations[Math.floor(Math.random() *
simulatedLocations.length)];
const simulatedPublicIP = `${Math.floor(Math.random() * 223) + 1}.$
{Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.$
{Math.floor(Math.random() * 255)}`; // Simulated public IP
let detectedAttacker = null;
if (Math.random() < 0.6) { // 60% chance of detecting an attacker
detectedAttacker = {
type: randomAttackerType,
ip: simulatedPublicIP, // Use a public-like IP for map simulation
location: `${randomLocation.address}, ${randomLocation.city}, $
{randomLocation.country}`
};
}
// Stop scan animation
scanAnimationArea.classList.remove('scanning');
let reportHtml = '';
let reportType = 'info';
if (detectedAttacker) {
currentScanStatus.textContent = `Penyerang terdeteksi! Tipe: $
59. {detectedAttacker.type}, IP: ${detectedAttacker.ip}.`;
currentScanStatus.style.color = 'var(--threat-red)';
addNotification('threat', `Penyerang terdeteksi! Tipe: ${detectedAttacker.type}, IP: $
{detectedAttacker.ip}.`, true);
reportHtml = `
<p class="text-threat-red font-semibold">Penyerang Terdeteksi!</p>
<p><strong>Tipe:</strong> ${detectedAttacker.type}</p>
<p><strong>IP:</strong> ${detectedAttacker.ip}</p>
<p><strong>Lokasi Simulasi:</strong> ${detectedAttacker.location}</p>
<p class="text-sm text-text-muted mt-2">
Deteksi IP penyerang sulit bagi manusia (privasi). PEMBUAT.com Antivirus
menembus IP samaran.
Aktifkan Perisai PRO untuk perlindungan berlapis!
</p>
<div class="report-buttons">
<button class="report-button primary"
onclick="window.open('https://www.google.com/maps/search/?api=1&query=$
{encodeURIComponent(detectedAttacker.location)}', '_blank'); playClingSound();">Lihat di Peta
Keberadaan OTdK (Lokasi Terkini)</button>
</div>
`;
reportType = 'error';
// Add to scan history
scanHistory.push({
device: 'Deteksi IP Penyerang',
threatLevel: 100, // High threat level for detected attacker
threats: [{ name: `Serangan ${detectedAttacker.type}`, description: `Deteksi
aktivitas mencurigusan dari IP ${detectedAttacker.ip} di ${detectedAttacker.location}.`, solution:
'Blokir IP ini dan perkuat firewall.' }],
movementDetected: true, // Assume movement if attacker detected
timestamp: new Date().toLocaleString()
});
displayDetailedThreats([{ name: `Serangan ${detectedAttacker.type}`, description:
`Deteksi aktivitas mencurigusan dari IP ${detectedAttacker.ip} di ${detectedAttacker.location}.`,
solution: 'Blokir IP ini dan perkuat firewall.' }]);
updateChart(false);
} else {
currentScanStatus.textContent = `Deteksi IP Penyerang selesai! Tidak ada aktivitas
mencurigakan terdeteksi.`;
currentScanStatus.style.color = 'var(--safe-green)';
addNotification('info', 'Deteksi IP Penyerang selesai. Tidak ada ancaman
terdeteksi.', true);
detailedThreatResults.style.display = 'none';
updateChart(true);
reportHtml = `
<p>Deteksi IP Penyerang selesai.</p>
<p>Tidak ada aktivitas mencurigakan terdeteksi pada jaringan Anda.</p>
<p class="text-sm text-text-muted mt-2">
Deteksi IP penyerang sulit bagi manusia (privasi). PEMBUAT.com Antivirus
menembus IP samaran.
Aktifkan Perisai PRO untuk perlindungan berlapis!
</p>
`;
reportType = 'success';
}
displayApplicationReport('Laporan Deteksi IP Penyerang', reportHtml, reportType);
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled');
ipDetectionButton.classList.remove('disabled'); // Re-enable itself
soundEnergyButton.classList.remove('disabled'); // Re-enable sound energy button
}, 4000); // Longer timeout for IP detection scan
}
// New function for Sound Wave Energy Detection Scan
function startSoundWaveScan() {
60. localStorage.setItem('hasScannedBefore', 'true');
scanButtons.forEach(button => button.classList.add('disabled'));
radioWaveScanButton.classList.add('disabled');
ipDetectionButton.classList.add('disabled');
soundEnergyButton.classList.add('disabled'); // Disable itself
currentScannedDevice = 'Energi Gelombang Suara';
// Hide other sections, show scan card, clear reports
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
currentScanCard.style.display = 'flex';
detailedThreatResults.style.display = 'none';
threatListContainer.innerHTML = '';
currentScanTitle.textContent = `Memindai Energi Gelombang Suara...`;
currentScanStatus.textContent = 'Menganalisis keadaan, situasi, dan sikon berdasarkan
energi gelombang suara di sekitar Anda...';
currentScanStatus.style.color = 'var(--text-muted)';
// Start scan animation
scanAnimationArea.classList.add('scanning');
// Simulate a sound wave effect (can be a simple Tone.js noise or a more complex
sound)
if (typeof Tone !== 'undefined') {
const soundWaveSynth = new Tone.NoiseSynth().toDestination();
soundWaveSynth.triggerAttackRelease("4n", Tone.now()); // Play a short noise burst
}
setTimeout(() => {
let isPositiveEnergy = Math.random() < 0.7; // 70% chance of positive energy
// Stop scan animation
scanAnimationArea.classList.remove('scanning');
let reportHtml = `
<p>Fitur deteksi energi gelombang suara ini adalah resapan dari kekuatan energi di
dalam perangkat yang Anda pakai, yang diaplikasikan nyata, berdasarkan deteksi akurat
keadaan dan situasi berdasarkan gelombang suara pada perangkat keras dan algoritma
pemrosesan sinyal yang canggih.</p>
`;
let reportType = 'info';
if (isPositiveEnergy) {
currentScanStatus.textContent = `Pemindaian Energi Gelombang Suara selesai!
Energi Positif Terdeteksi.`;
currentScanStatus.style.color = 'var(--safe-green)';
speakScanComplete();
updateChart(true);
addNotification('info', `Pemindaian gelombang suara selesai. Energi Positif
Terdeteksi.`, true);
reportHtml += `
<p class="text-safe-green font-semibold mt-3">Pemindaian telah berhasil bahwa
ada energi positif pada perangkat Anda.</p>
<p class="text-safe-green font-semibold mt-1">Energi perangkat Anda sudah
kembali positif.</p>
<div class="report-buttons">
<button class="report-button superpositive-action"
onclick="absorbAllPositiveEnergy(); playClingSound();">Serap Semua Energi Positif</button>
</div>
`;
reportType = 'success';
} else {
currentScanStatus.textContent = `Pemindaian Energi Gelombang Suara selesai!
Energi Negatif Terdeteksi.`;
61. currentScanStatus.style.color = 'var(--threat-red)';
speakThreatDetected();
updateChart(false);
addNotification('threat', `Anomali gelombang suara terdeteksi: Energi Negatif
Terdeteksi.`, true);
reportHtml += `
<p class="text-threat-red font-semibold mt-3">Perangkat Anda masih bermasalah
dengan energi negatif.</p>
<p class="text-threat-red font-semibold mt-1">Ada masalah energi pada
perangkat Anda.</p>
<div class="report-buttons">
<button class="report-button negative-action"
onclick="disconnectNegativeEnergy(); playClingSound();">Putuskan Semua Energi
Negatif</button>
<button class="report-button positive-action" onclick="fillWithPositiveEnergy();
playClingSound();">Penuhi dengan Energi Positif</button>
</div>
`;
reportType = 'error';
}
displayApplicationReport('Laporan Pemindaian Energi Gelombang Suara', reportHtml,
reportType);
// Re-enable scan buttons after the entire energy scan flow is complete (handled by
subsequent button clicks)
// For now, they remain disabled until the energy flow is completed.
}, 4500); // Longer timeout for sound wave scan
}
function disconnectNegativeEnergy() {
const currentReportItem = reportContent.querySelector('.report-item');
if (currentReportItem) {
currentReportItem.innerHTML = `
<div class="report-title">Memutuskan Energi Negatif...</div>
<p>Memproses pemutusan semua energi negatif...</p>
<p class="text-warning-orange font-semibold mt-2">Memproses...</p>
`;
currentReportItem.className = 'report-item warning';
}
setTimeout(() => {
if (currentReportItem) {
currentReportItem.innerHTML = `
<div class="report-title">Energi Negatif Terputus!</div>
<p>Semua energi negatif telah berhasil diputuskan. Perangkat Anda kini siap
untuk menyerap energi positif.</p>
<p class="text-safe-green font-semibold mt-2">Energi perangkat Anda sudah
kembali positif.</p>
<div class="report-buttons">
<button class="report-button positive-action" onclick="fillWithPositiveEnergy();
playClingSound();">Penuhi dengan Energi Positif</button>
</div>
`;
currentReportItem.className = 'report-item success';
}
addNotification('info', 'Energi negatif berhasil diputuskan.', true);
}, 2500);
}
function fillWithPositiveEnergy() {
const currentReportItem = reportContent.querySelector('.report-item');
if (currentReportItem) {
currentReportItem.innerHTML = `
<div class="report-title">Memenuhi dengan Energi Positif...</div>
<p>Memenuhi perangkat dengan energi positif...</p>
<p class="text-warning-orange font-semibold mt-2">Menciptakan polar
keseimbangan...</p>
62. `;
currentReportItem.className = 'report-item warning';
}
setTimeout(() => {
if (currentReportItem) {
currentReportItem.innerHTML = `
<div class="report-title">Energi Positif Terisi Penuh!</div>
<p>Perangkat Anda kini penuh dengan energi positif dan telah mencapai polar
keseimbangan yang sempurna.</p>
<p class="text-safe-green font-semibold mt-2">Energi perangkat Anda sudah
kembali positif.</p>
<div class="report-buttons">
<button class="report-button superpositive-action"
onclick="absorbAllPositiveEnergy(); playClingSound();">Serap Semua Energi Positif</button>
</div>
`;
currentReportItem.className = 'report-item success';
}
addNotification('info', 'Perangkat berhasil diisi energi positif. Keseimbangan polar
tercapai.', true);
}, 3000);
}
function absorbAllPositiveEnergy() {
const currentReportItem = reportContent.querySelector('.report-item');
if (currentReportItem) {
currentReportItem.innerHTML = `
<div class="report-title text-warning-orange">SUPERPOSITIVE!</div>
<p>Perangkat Anda telah berhasil menyerap semua energi positif dan Anda
sekarang berada dalam perangkat SUPERPOSITIVE!</p>
<p class="text-safe-green font-semibold mt-2">Nikmati kinerja optimal!</p>
`;
currentReportItem.className = 'report-item success'; // Use success for the final
positive state
}
addNotification('info', 'Perangkat Anda SUPERPOSITIVE! Nikmati kinerja optimal.', true);
// Re-enable all scan buttons after the final SUPERPOSITIVE state
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled');
ipDetectionButton.classList.remove('disabled');
soundEnergyButton.classList.remove('disabled');
currentScanCard.style.display = 'flex'; // Show scan card again
}
function displayDetailedThreats(threats) {
threatListContainer.innerHTML = '';
if (threats.length > 0) {
threats.forEach(threat => {
const threatItem = document.createElement('div');
threatItem.classList.add('detailed-threat-item');
threatItem.innerHTML = `
<div class="threat-name">${threat.name}</div>
<div class="threat-description">${threat.description}</div>
<button class="recover-single-button" onclick="recoverSingleThreat(event, '$
{threat.name}'); playClingSound();">Pulihkan</button>
`;
threatListContainer.appendChild(threatItem);
});
detailedThreatResults.style.display = 'block';
} else {
detailedThreatResults.style.display = 'none';
}
detailedRecoverAllButton.disabled = false;
}
function recoverSingleThreat(event, threatName) {
const button = event.target;
63. button.textContent = 'Memulihkan...';
button.disabled = true;
button.style.backgroundColor = '#c05621';
setTimeout(() => {
button.textContent = 'Dipulihkan';
button.style.backgroundColor = 'var(--safe-green)';
button.closest('.detailed-threat-item').remove();
addNotification('recovery', `Ancaman '${threatName}' berhasil dipulihkan.`, true); //
Voice enabled
if (threatListContainer.children.length === 0) {
currentScanStatus.textContent = `Semua ancaman berhasil dipulihkan! Sistem
Perangkat Anda. Sekarang Sudah Aman, Nyaman, Sehat, Sentosa, Tanpa Masalah
("ANCAMAN SUDAH DIMUSNAHKAN!") Selamat Perangkat Anda Sehat`;
currentScanStatus.style.color = 'var(--safe-green)';
speakScanComplete(); // This now calls addNotification with speak: true
detailedThreatResults.style.display = 'none';
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled'); // Re-enable radio wave scan
button
ipDetectionButton.classList.remove('disabled'); // Re-enable IP detection button
soundEnergyButton.classList.remove('disabled'); // Re-enable sound energy button
if (scanHistory.length > 0) {
scanHistory[scanHistory.length - 1].threatLevel = 0;
updateChart(true);
}
}
}, 1500);
}
function recoverAllThreats() {
detailedRecoverAllButton.disabled = true;
detailedRecoverAllButton.textContent = 'Memulihkan Semua...';
const recoverButtons = document.querySelectorAll('.recover-single-button');
recoverButtons.forEach(button => {
button.textContent = 'Memulihkan...';
button.disabled = true;
button.style.backgroundColor = '#c05621';
});
currentScanStatus.textContent = `Memulihkan semua ancaman...`;
currentScanStatus.style.color = 'var(--warning-orange)';
setTimeout(() => {
currentScanStatus.textContent = `Semua ancaman berhasil dipulihkan! Sistem
Perangkat Anda. Sekarang Sudah Aman, Nyaman, Sehat, Sentosa, Tanpa Masalah
("ANCAMAN SUDAH DIMUSNAHKAN!") Selamat Perangkat Anda Sehat`;
currentScanStatus.style.color = 'var(--safe-green)';
speakScanComplete(); // This now calls addNotification with speak: true
threatListContainer.innerHTML = '';
detailedThreatResults.style.display = 'none';
detailedRecoverAllButton.textContent = 'Pulihkan Semua';
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled'); // Re-enable radio wave scan
button
ipDetectionButton.classList.remove('disabled'); // Re-enable IP detection button
soundEnergyButton.classList.remove('disabled'); // Re-enable sound energy button
if (scanHistory.length > 0) {
scanHistory[scanHistory.length - 1].threatLevel = 0;
updateChart(true);
}
addNotification('recovery', `Semua ancaman berhasil dipulihkan.`, true); // Voice
enabled
}, 3000);
}
64. function toggleShield() {
const isProVersion = localStorage.getItem('isProVersion') === 'true';
const shieldButton = document.getElementById('shield-toggle-button');
const shieldStatus = document.getElementById('shield-status');
if (shieldButton.classList.contains('active')) {
shieldButton.disabled = true;
shieldButton.textContent = 'Menonaktifkan Perisai...';
shieldStatus.textContent = 'Perisai: Menonaktifkan perlindungan...';
shieldStatus.style.color = 'var(--text-muted)';
setTimeout(() => {
shieldButton.classList.remove('active');
if (isProVersion) {
shieldButton.textContent = 'Aktifkan Perisai (PRO)';
shieldStatus.textContent = 'Perisai: Nonaktif (PRO)';
shieldStatus.style.color = 'var(--threat-red)'; // Still red when inactive, even for
PRO
} else {
shieldButton.textContent = 'Aktifkan Perisai';
shieldStatus.textContent = 'Perisai: Nonaktif';
shieldStatus.style.color = 'var(--threat-red)';
}
shieldButton.disabled = false;
addNotification('shield', 'Perisai Antivirus telah dinonaktifkan.', true); // Voice
enabled
}, 2000);
} else {
shieldButton.disabled = true;
shieldButton.textContent = 'Mengaktifkan Perisai...';
shieldStatus.textContent = 'Perisai: Mengaktifkan perlindungan terhadap virus,
malware, phishing, hacker, spam, jaringan kabel, WiFi, hotspot, dan menutup semua celah...
Berlapis Kekuatan FULL ENERGI POSITIF & FULL SUPER POWER!';
shieldStatus.style.color = 'var(--warning-orange)';
setTimeout(() => {
shieldButton.classList.add('active');
if (isProVersion) {
shieldButton.textContent = 'Nonaktifkan Perisai (PRO)';
shieldStatus.textContent = 'Perisai: AKTIF! Semua celah ditutup, ancaman
dimusnahkan. Sistem aman, nyaman, sentosa, tanpa ada lagi masalah. Berlapis Kekuatan
FULL ENERGI POSITIF & FULL SUPER POWER! (PRO)';
shieldStatus.style.color = 'var(--safe-green)'; // Green when active for PRO
} else {
shieldButton.textContent = 'Nonaktifkan Perisai';
shieldStatus.textContent = 'Perisai: AKTIF! Semua celah ditutup, ancaman
dimusnahkan. Sistem aman, nyaman, sentosa, tanpa ada lagi masalah. Berlapis Kekuatan
FULL ENERGI POSITIF & FULL SUPER POWER!';
shieldStatus.style.color = 'var(--safe-green)'; // Green when active for FREE
}
addNotification('shield', 'Selamat, perisai Anda telah aktif. Berlapis Kekuatan FULL
ENERGI POSITIF & FULL SUPER POWER!', true); // Voice enabled
shieldButton.disabled = false;
}, 3000);
}
}
// Function to toggle the visibility of the donate section
function toggleDonateSection() {
if (donateSection.style.display === 'block') {
donateSection.style.display = 'none';
currentScanCard.style.display = 'flex'; // Show scan card when donate is hidden
} else {
currentScanCard.style.display = 'none';
detailedThreatResults.style.display = 'none';
threatModalOverlay.classList.remove('show');
supportSection.style.display = 'none'; // Hide support section if visible
monitorSection.style.display = 'none'; // Hide monitor section if visible
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
65. clearApplicationReports(); // Clear and hide the report section
donateSection.style.display = 'block'; // Show the donate section
}
}
// Function to toggle the visibility of the support section
function toggleSupportSection() {
if (supportSection.style.display === 'block') {
supportSection.style.display = 'none';
currentScanCard.style.display = 'flex'; // Show scan card when support is hidden
} else {
currentScanCard.style.display = 'none';
detailedThreatResults.style.display = 'none';
threatModalOverlay.classList.remove('show');
donateSection.style.display = 'none'; // Hide donate section if visible
monitorSection.style.display = 'none'; // Hide monitor section if visible
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
supportSection.style.display = 'block'; // Show the support section
}
}
// Function to toggle the visibility of the monitor section
function toggleMonitorSection() {
if (monitorSection.style.display === 'flex') { // Check for 'flex' as it's a flex container
monitorSection.style.display = 'none';
currentScanCard.style.display = 'flex'; // Show scan card when monitor is hidden
} else {
currentScanCard.style.display = 'none';
detailedThreatResults.style.display = 'none';
threatModalOverlay.classList.remove('show');
donateSection.style.display = 'none'; // Hide donate section if visible
supportSection.style.display = 'none'; // Hide support section if visible
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
monitorSection.style.display = 'flex'; // Show the monitor section
resizeMonitorCanvas(); // Ensure canvas is resized when shown
}
}
// --- Functions for Update and Upgrade ---
function checkVersionStatus() {
const isProVersion = localStorage.getItem('isProVersion') === 'true';
const lastFreeUpdate = localStorage.getItem('lastFreeUpdate');
const proUpgradeDate = localStorage.getItem('proUpgradeDate');
const now = new Date();
// Update Subtitle
if (isProVersion) {
framedSubtitle.textContent = "Anda sedang menggunakan Aplikasi PEMBUAT.com
Antivirus Versi.FULL.JALiN.KB.PRO";
framedSubtitle.classList.remove('free-version');
framedSubtitle.classList.add('pro-version');
arabicTextContainer.classList.add('pro-active'); // Add pro-active class to arabic text
container
} else {
framedSubtitle.textContent = "Anda sedang menggunakan Aplikasi PEMBUAT.com
Antivirus Versi.FULL.JALiN.KB.FREE";
framedSubtitle.classList.remove('pro-version');
framedSubtitle.classList.add('free-version');
arabicTextContainer.classList.remove('pro-active'); // Remove pro-active class from
arabic text container
}
// Handle Free Update Button
if (isProVersion) {
updateFreeText.textContent = 'Update Sistem Gratis';
updateFreeButton.disabled = false; // Always enabled for Pro users
66. updateFreeButton.classList.remove('disabled');
} else if (lastFreeUpdate) { // Existing logic for non-pro users
const lastUpdateDate = new Date(lastFreeUpdate);
const nextUpdateDue = new Date(lastUpdateDate.getTime() + 7 * 24 * 60 * 60 *
1000); // 7 days from last update
if (now >= nextUpdateDue) {
updateFreeText.textContent = 'Update Gratis (Tersedia)';
updateFreeButton.disabled = false;
updateFreeButton.classList.remove('disabled');
} else {
const diffTime = Math.abs(nextUpdateDue - now);
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
updateFreeText.textContent = `Update Gratis (dalam ${diffDays} hari)`;
updateFreeButton.disabled = true;
updateFreeButton.classList.add('disabled');
}
} else {
// First time user, update is available (for non-pro)
updateFreeText.textContent = 'Update Gratis (Tersedia)';
updateFreeButton.disabled = false;
updateFreeButton.classList.remove('disabled');
}
// Handle Pro Upgrade Button
if (isProVersion) {
upgradeProText.textContent = 'Versi Pro Aktif';
upgradeProButton.disabled = true;
upgradeProButton.classList.add('pro-active'); // Add new class for pro active styling
} else {
upgradeProText.textContent = 'Upgrade Pro';
upgradeProButton.disabled = false;
upgradeProButton.classList.remove('pro-active'); // Remove class if not pro
}
// Handle Shield Button Styling
const shieldIcon = shieldToggleButton.querySelector('svg');
if (isProVersion) {
shieldToggleButton.classList.add('pro-version-active');
// Also update the text if it's currently active/inactive
if (shieldToggleButton.classList.contains('active')) {
shieldToggleButton.textContent = 'Nonaktifkan Perisai (PRO)';
document.getElementById('shield-status').textContent = 'Perisai: AKTIF! Semua
celah ditutup, ancaman dimusnahkan. Sistem aman, nyaman, sentosa, tanpa ada lagi masalah.
Berlapis Kekuatan FULL ENERGI POSITIF & FULL SUPER POWER! (PRO)';
document.getElementById('shield-status').style.color = 'var(--safe-green)'; // Green
when active for PRO
} else {
shieldToggleButton.textContent = 'Aktifkan Perisai (PRO)';
document.getElementById('shield-status').textContent = 'Perisai: Nonaktif (PRO)';
document.getElementById('shield-status').style.color = 'var(--threat-red)'; // Still red
when inactive, even for PRO
}
} else {
shieldToggleButton.classList.remove('pro-version-active');
// Reset text if it was previously Pro
if (shieldToggleButton.classList.contains('active')) {
shieldToggleButton.textContent = 'Nonaktifkan Perisai';
document.getElementById('shield-status').textContent = 'Perisai: AKTIF! Semua
celah ditutup, ancaman dimusnahkan. Sistem aman, nyaman, sentosa, tanpa ada lagi masalah.
Berlapis Kekuatan FULL ENERGI POSITIF & FULL SUPER POWER!';
document.getElementById('shield-status').style.color = 'var(--safe-green)'; // Green
when active for FREE
} else {
shieldToggleButton.textContent = 'Aktifkan Perisai';
document.getElementById('shield-status').textContent = 'Perisai: Nonaktif';
document.getElementById('shield-status').style.color = 'var(--threat-red)'; // Red
when inactive for FREE
}
}
67. }
function performFreeUpdate() {
updateFreeButton.disabled = true;
updateFreeText.textContent = 'Memperbarui...';
updateFreeButton.classList.add('disabled');
// Hide other sections, show scan card, clear reports
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
currentScanCard.style.display = 'flex';
detailedThreatResults.style.display = 'none';
setTimeout(() => {
localStorage.setItem('lastFreeUpdate', new Date().toISOString());
const reportHtml = `<p>Pembaruan gratis berhasil! Aplikasi Anda kini mutakhir.</p>`;
displayApplicationReport('Laporan Pembaruan Sistem', reportHtml, 'success');
addNotification('update', 'Pembaruan gratis aplikasi berhasil diselesaikan.', true); //
Voice enabled
checkVersionStatus(); // Update button text and status
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled');
ipDetectionButton.classList.remove('disabled');
soundEnergyButton.classList.remove('disabled');
}, 2000);
}
function initiateProUpgrade() {
// Hide other sections, show scan card, clear reports
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
inlineNotificationsSection.style.display = 'none'; // Hide inline notifications
clearApplicationReports(); // Clear and hide the report section
currentScanCard.style.display = 'flex';
detailedThreatResults.style.display = 'none';
const initialHtml = `
<p>Apakah Anda sudah melakukan pembayaran untuk Upgrade Pro?</p>
<div class="report-buttons">
<button class="report-button primary" onclick="promptProKeyInput();
playClingSound();">Ya, Sudah Bayar</button>
<button class="report-button secondary" onclick="cancelProUpgrade();
playClingSound();">Belum / Batalkan</button>
</div>
`;
displayApplicationReport('Upgrade Pro', initialHtml, 'info');
}
function promptProKeyInput() {
const inputHtml = `
<p>Silakan masukkan 20 digit kata kunci Pro yang telah dikirimkan kepada Anda:</p>
<input type="text" id="pro-key-input" placeholder="XXXX-XXXX-XXXX-XXXX-XXXX">
<div class="report-buttons">
<button class="report-button primary" onclick="processProKey();
playClingSound();">Aktifkan</button>
<button class="report-button secondary" onclick="cancelProUpgrade();
playClingSound();">Batal</button>
</div>
`;
displayApplicationReport('Upgrade Pro - Masukkan Kata Kunci', inputHtml, 'info');
document.getElementById('pro-key-input').focus();
}
function processProKey() {
const keyEntered = document.getElementById('pro-key-input').value;
const cleanedKey = keyEntered.toUpperCase().replace(/-/g, '');
68. const correctCleanedKey = CORRECT_PRO_KEY.replace(/-/g, '');
if (cleanedKey === correctCleanedKey) {
const processingHtml = `
<p>Kata kunci valid. Mengaktifkan versi Pro...</p>
<p class="text-warning-orange font-semibold mt-2">Harap tunggu...</p>
`;
displayApplicationReport('Upgrade Pro - Memproses Aktivasi', processingHtml,
'warning');
setTimeout(() => {
localStorage.setItem('isProVersion', 'true');
localStorage.setItem('proUpgradeDate', new Date().toISOString());
const successHtml = `
<p class="text-safe-green font-semibold">SELAMAT ANDA TELAH BERHASIL
MELAKUKAN UPGRADE KE VERSI.FULL.JALiN.KB.PRO</p>
<p class="mt-2">Nikmati semua fitur premium!</p>
`;
displayApplicationReport('Upgrade Berhasil!', successHtml, 'success');
addNotification('upgrade', 'Aplikasi berhasil di-upgrade ke versi Pro. Nikmati fitur
premium!', true); // Voice enabled
checkVersionStatus(); // Update button text and status (will disable the button)
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled');
ipDetectionButton.classList.remove('disabled');
soundEnergyButton.classList.remove('disabled');
}, 3000);
} else {
const errorHtml = `
<p class="text-threat-red font-semibold">Kata kunci tidak valid.</p>
<p>Mohon periksa kembali kode Anda atau coba lagi.</p>
<div class="report-buttons">
<button class="report-button primary" onclick="promptProKeyInput();
playClingSound();">Coba Lagi</button>
<button class="report-button secondary" onclick="cancelProUpgrade();
playClingSound();">Batal</button>
</div>
`;
displayApplicationReport('Aktivasi Gagal', errorHtml, 'error');
}
}
function cancelProUpgrade() {
const cancelHtml = `
<p>Aktivasi dibatalkan.</p>
<p>Silakan lakukan pembayaran terlebih dahulu jika Anda ingin mengaktifkan versi
Pro.</p>
`;
displayApplicationReport('Upgrade Pro Dibatalkan', cancelHtml, 'info');
scanButtons.forEach(button => button.classList.remove('disabled'));
radioWaveScanButton.classList.remove('disabled');
ipDetectionButton.classList.remove('disabled');
soundEnergyButton.classList.remove('disabled');
}
// --- Notification System Functions (MODIFIED FOR INLINE DISPLAY) ---
/**
* Adds a new notification to the list and updates the badge.
* @param {string} type - Type of notification (e.g., 'threat', 'update', 'upgrade', 'report',
'movement', 'info', 'recovery', 'balancing').
* @param {string} message - The notification message.
* @param {boolean} [speak=true] - Whether to speak the notification message.
*/
function addNotification(type, message, speak = true) {
const newNotification = {
id: Date.now(), // Unique ID for notification
type: type,
message: message,
69. timestamp: new Date().toLocaleString('id-ID', {
year: 'numeric', month: 'short', day: 'numeric',
hour: '2-digit', minute: '2-digit', second: '2-digit'
}),
read: false
};
notifications.unshift(newNotification); // Add to the beginning
localStorage.setItem('notifications', JSON.stringify(notifications));
updateNotificationBadge();
// If inline notifications are already visible, update them immediately
if (inlineNotificationsSection.style.display === 'flex') {
displayInlineNotifications();
}
if (speak) { // Only speak if 'speak' parameter is true
if (synth && indonesianFemaleVoice) {
const utterance = new SpeechSynthesisUtterance(message);
utterance.lang = 'id-ID';
utterance.voice = indonesianFemaleVoice;
utterance.pitch = 1.0;
utterance.rate = 0.9;
try {
synth.speak(utterance);
} catch (error) {
console.error("Gagal mengeluarkan suara:", error);
}
} else {
console.warn("Web Speech API tidak didukung atau suara Bahasa Indonesia tidak
ditemukan. Voice output mungkin tidak berfungsi.");
}
}
}
/**
* Updates the unread notification count badge.
*/
function updateNotificationBadge() {
const unreadCount = notifications.filter(n => !n.read).length;
if (unreadCount > 0) {
notificationBadge.textContent = unreadCount;
notificationBadge.classList.remove('hidden');
} else {
notificationBadge.classList.add('hidden');
}
}
/**
* Toggles the visibility of the inline notification section and displays notifications.
*/
function toggleInlineNotifications() {
if (inlineNotificationsSection.style.display === 'flex') {
// If currently visible, hide it
inlineNotificationsSection.style.display = 'none';
currentScanCard.style.display = 'flex'; // Show scan card again
} else {
// If currently hidden, show it
// Hide other sections
currentScanCard.style.display = 'none';
detailedThreatResults.style.display = 'none';
donateSection.style.display = 'none';
supportSection.style.display = 'none';
monitorSection.style.display = 'none';
threatModalOverlay.classList.remove('show');
clearApplicationReports(); // Clear and hide the report section
// Display notifications in the inline section
displayInlineNotifications();
inlineNotificationsSection.style.display = 'flex';
// Mark all notifications as read when the section is opened
70. notifications.forEach(n => n.read = true);
localStorage.setItem('notifications', JSON.stringify(notifications));
updateNotificationBadge(); // Update badge to 0
inlineNotificationsSection.scrollIntoView({ behavior: 'smooth', block: 'start' }); // Scroll to
view
}
}
/**
* Renders the notifications in the inline section.
*/
function displayInlineNotifications() {
inlineNotificationList.innerHTML = ''; // Clear previous list
if (notifications.length === 0) {
noInlineNotificationsMessage.classList.remove('hidden');
inlineNotificationList.appendChild(noInlineNotificationsMessage);
} else {
noInlineNotificationsMessage.classList.add('hidden');
notifications.forEach(n => {
const notificationItem = document.createElement('div');
notificationItem.classList.add('notification-item', n.type, n.read ? 'read' : 'unread');
notificationItem.innerHTML = `
<div class="flex justify-between items-center">
<span class="type">${n.type.toUpperCase()}</span>
<span class="timestamp">${n.timestamp}</span>
</div>
<div class="message">${n.message}</div>
`;
inlineNotificationList.appendChild(notificationItem);
});
}
}
/**
* Generates a daily report notification.
* This function is designed to run once every 24 hours (simulated with a shorter interval).
*/
function generateDailyReport() {
const lastReportDate = localStorage.getItem('lastDailyReportDate');
const now = new Date();
let shouldGenerate = false;
if (!lastReportDate) {
shouldGenerate = true;
} else {
const lastReport = new Date(lastReportDate);
// Simulate 24 hours with a shorter interval for testing (e.g., 60 seconds)
// In production, use: const twentyFourHours = 24 * 60 * 60 * 1000;
const dailyInterval = 60 * 1000; // 60 seconds for demo
if (now.getTime() - lastReport.getTime() >= dailyInterval) {
shouldGenerate = true;
}
}
if (shouldGenerate) {
let reportMessage = 'Laporan Harian PEMBUAT Antivirus:n';
let threatsFound = 0;
let scansPerformed = 0;
let movementsDetected = 0;
// Summarize recent activity from scanHistory
const today = new Date();
const recentScans = scanHistory.filter(scan => {
const scanDate = new Date(scan.timestamp);
return scanDate.getDate() === today.getDate() &&
scanDate.getMonth() === today.getMonth() &&
scanDate.getFullYear() === today.getFullYear();
});
recentScans.forEach(scan => {
71. scansPerformed++;
if (scan.threats && scan.threats.length > 0) {
threatsFound += scan.threats.length;
}
if (scan.movementDetected) {
movementsDetected++;
}
});
reportMessage += `- ${scansPerformed} pemindaian dilakukan hari ini.n`;
if (threatsFound > 0) {
reportMessage += `- ${threatsFound} masalah terdeteksi dan ditangani.n`;
} else {
reportMessage += `- Tidak ada masalah serius terdeteksi.n`;
}
if (movementsDetected > 0) {
reportMessage += `- ${movementsDetected} pergerakan berbahaya terdeteksi dan
dipantau.n`;
}
// Check for update/upgrade status
const lastFreeUpdate = localStorage.getItem('lastFreeUpdate');
const isProVersion = localStorage.getItem('isProVersion') === 'true';
const proUpgradeDate = localStorage.getItem('proUpgradeDate');
if (lastFreeUpdate) {
const lastUpdateDate = new Date(lastFreeUpdate);
const nextUpdateDue = new Date(lastUpdateDate.getTime() + 7 * 24 * 60 * 60 *
1000);
if (now >= nextUpdateDue) {
reportMessage += `- Pembaruan gratis tersedia. Segera perbarui aplikasi Anda!
n`;
} else {
const diffDays = Math.ceil((nextUpdateDue - now) / (1000 * 60 * 60 * 24));
reportMessage += `- Pembaruan gratis berikutnya dalam ${diffDays} hari.n`;
}
} else {
reportMessage += `- Pembaruan gratis tersedia. Segera perbarui aplikasi Anda!n`;
}
if (isProVersion) {
const upgradeDate = new Date(proUpgradeDate);
const nextRenewalDue = new Date(upgradeDate.getFullYear() + 1,
upgradeDate.getMonth(), upgradeDate.getDate());
if (now >= nextRenewalDue) {
reportMessage += `- Langganan Pro Anda akan segera berakhir. Segera
perbarui untuk melanjutkan perlindungan premium!n`;
} else {
const diffDays = Math.ceil((nextRenewalDue - now) / (1000 * 60 * 60 * 24));
reportMessage += `- Langganan Pro aktif. Berakhir dalam ${diffDays} hari.n`;
}
} else {
reportMessage += `- Pertimbangkan untuk Upgrade ke Versi Pro untuk
perlindungan lengkap!n`;
}
addNotification('report', reportMessage, false); // No voice for daily report
localStorage.setItem('lastDailyReportDate', now.toISOString());
// Clear scan history for the next report period if needed, or keep it for longer historical
data
// For this demo, we'll keep it, but in a real app, you might want to archive/clear.
}
}
// --- Monitor Section Functions ---
function startMonitorAnimation() {
function animateMonitor() {
updateMonitorData();
drawMonitor();
72. requestAnimationFrame(animateMonitor);
}
animateMonitor();
}
/**
* Resizes the monitor canvas to fit its parent container.
* This function should be called on initial load and window resize.
*/
function resizeMonitorCanvas() {
const container = monitorCanvas.parentElement;
// Set canvas display size (CSS pixels)
monitorCanvas.style.width = '100%';
monitorCanvas.style.height = '180px'; // Fixed height for consistency
// Set canvas drawing buffer size (actual pixels)
// Use clientWidth for the actual rendered width of the container
monitorCanvas.width = container.clientWidth;
monitorCanvas.height = 180; // Keep drawing height fixed for simplicity
drawMonitor(); // Redraw content after resizing
}
function updateMonitorData() {
// Simulate temperature fluctuation
const tempChange = (Math.random() - 0.5) * 5; // Change by -2.5 to +2.5
currentTemp = Math.max(30, Math.min(90, currentTemp + tempChange)); // Keep
between 30-90°C
// Simulate memory load fluctuation (0-100%)
const memoryLoadChange = (Math.random() - 0.5) * 10; // Change by -5 to +5
currentMemoryLoad = Math.max(0, Math.min(100, currentMemoryLoad +
memoryLoadChange)); // Keep between 0-100%
// --- Automatic Balancing Logic ---
const tempThresholdWarning = 65;
const tempThresholdCritical = 80;
const memoryLoadThresholdWarning = 70;
const memoryLoadThresholdCritical = 90;
let oldIsBalancingActive = isBalancingActive;
if (currentTemp >= tempThresholdWarning || currentMemoryLoad >=
memoryLoadThresholdWarning) {
isBalancingActive = true;
let balancingMessage = 'Status: Meningkatkan keseimbangan... ';
let notify = false;
if (currentTemp >= tempThresholdCritical) {
currentTemp = Math.max(30, currentTemp - 2); // Faster decrease for critical temp
balancingMessage += 'Temperatur KRITIS! ';
notify = true;
} else if (currentTemp >= tempThresholdWarning) {
currentTemp = Math.max(30, currentTemp - 0.5); // Slower decrease for warning
temp
balancingMessage += 'Temperatur Tinggi. ';
}
if (currentMemoryLoad >= memoryLoadThresholdCritical) {
currentMemoryLoad = Math.max(0, currentMemoryLoad - 3); // Faster decrease for
critical memory
balancingMessage += 'Beban Memori KRITIS! ';
notify = true;
} else if (currentMemoryLoad >= memoryLoadThresholdWarning) {
currentMemoryLoad = Math.max(0, currentMemoryLoad - 1); // Slower decrease for
warning memory
balancingMessage += 'Beban Memori Tinggi. ';
}
monitorStatusText.textContent = balancingMessage.trim();
73. monitorStatusText.className = 'monitor-status warning'; // Use warning for active
balancing
// Only add notification if balancing just started for critical issues, WITHOUT voice
if (notify && !oldIsBalancingActive) {
addNotification('balancing', `Sistem mulai menyeimbangkan: $
{monitorStatusText.textContent}`, false); // 'false' to prevent voice
}
} else {
if (isBalancingActive) { // Balancing just finished
addNotification('info', 'Sistem berhasil menyeimbangkan. Perangkat kembali
normal.', false); // No voice
}
isBalancingActive = false;
monitorStatusText.textContent = 'Status: Normal';
monitorStatusText.className = 'monitor-status safe';
}
tempReading.textContent = `${currentTemp.toFixed(0)}°C`;
memoryLoadReading.textContent = `${currentMemoryLoad.toFixed(0)}%`;
}
function drawMonitor() {
const canvasWidth = monitorCanvas.width;
const canvasHeight = monitorCanvas.height;
const padding = 20;
const barHeight = 40;
const barSpacing = 20;
const maxBarWidth = canvasWidth - (2 * padding);
// Clear canvas
monitorCtx.clearRect(0, 0, canvasWidth, canvasHeight);
// --- Draw Temperature Bar ---
const tempBarY = padding;
let tempColor = 'var(--safe-green)';
if (currentTemp >= 80) {
tempColor = 'var(--threat-red)';
} else if (currentTemp >= 65) {
tempColor = 'var(--warning-orange)';
}
// Background bar for Temperature
monitorCtx.fillStyle = 'rgba(66, 153, 225, 0.1)'; // Light blue transparent
monitorCtx.fillRect(padding, tempBarY, maxBarWidth, barHeight);
monitorCtx.strokeStyle = 'rgba(66, 153, 225, 0.5)';
monitorCtx.lineWidth = 2;
monitorCtx.strokeRect(padding, tempBarY, maxBarWidth, barHeight);
// Filled bar for Temperature
const tempFillWidth = (currentTemp / 100) * maxBarWidth; // Assuming temp max is 100
for scaling
monitorCtx.fillStyle = tempColor;
monitorCtx.fillRect(padding, tempBarY, tempFillWidth, barHeight);
// Temperature text on bar
monitorCtx.fillStyle = 'var(--text-light)';
monitorCtx.font = 'bold 16px Inter';
monitorCtx.textAlign = 'left';
monitorCtx.textBaseline = 'middle';
monitorCtx.fillText(`Temperatur: ${currentTemp.toFixed(0)}°C`, padding + 10, tempBarY
+ barHeight / 2);
// --- Draw Memory Load Bar ---
const memoryLoadBarY = tempBarY + barHeight + barSpacing;
let memoryLoadColor = 'var(--safe-green)';
if (currentMemoryLoad >= 90) {
memoryLoadColor = 'var(--threat-red)';