This commit is contained in:
Saufi
2026-06-03 08:51:22 +08:00
commit a14d43fe34
347 changed files with 38197 additions and 0 deletions

323
docs/09-improvement-plan.md Normal file
View File

@@ -0,0 +1,323 @@
# Improvement Plan
Dokumen ini mencatat pelan pembetulan dan penambahbaikan sistem PRN2026 selepas semakan kod menyeluruh selepas Phase 11 selesai. Setiap fasa mengikut susunan keutamaan: kritikal → prestasi → pengalaman pengguna → pengurusan data.
Setiap pembetulan dan perubahan wajib kemaskini:
- `docs/progress-log.md`
- `docs/changelog.md`
- `docs/decision-log.md` jika ada keputusan seni bina, pakej, pangkalan data atau keselamatan yang berubah
---
## Fasa 12: Pembetulan Kritikal dan Keselamatan
Status: Belum dimulakan.
Skop fasa ini ialah menangani kelemahan yang boleh menyebabkan data tidak konsisten, kawalan akses bocor, atau keperluan edit database secara manual dalam persekitaran produksi.
### 12-A: Admin Settings UI — Toggle Kehadiran dan Override Pendaftaran
Masalah semasa:
- `election_settings.is_attendance_active` hanya boleh diubah melalui edit database secara terus.
- `election_settings.is_registration_open_override` juga tiada UI khusus; bergantung pada pengaturan tarikh semata-mata.
- Ini tidak selamat dan tidak praktikal dalam persekitaran produksi semasa hari mengundi.
Tugas:
- Tambah halaman Admin Settings di bawah `/admin/settings` atau `/admin/setup/settings`.
- Paparkan toggle untuk `is_attendance_active` dengan label jelas dan amaran impak.
- Paparkan toggle atau dropdown untuk `is_registration_open_override` (null / buka paksa / tutup paksa).
- Paparkan tarikh buka dan tarikh tutup pendaftaran semasa sebagai konteks.
- Tambah `AdminSettingsController` dan `UpdateElectionSettingsRequest`.
- Tambah `ElectionSettingsService` untuk enkapsulasi logik kemaskini.
- Rekod perubahan dalam activity log: siapa, nilai lama, nilai baru, masa.
- Tambah ujian ciri untuk kemaskini setiap toggle, halaman diakses Admin sahaja.
- Tambah pautan ke Admin Settings dari Admin dashboard.
Kriteria keluar:
- Admin boleh toggle kehadiran dan override pendaftaran dari UI tanpa sentuh database.
- Perubahan direkod dalam activity log.
- Admin Kewangan, PPM, KTM tidak boleh akses halaman settings.
Dokumentasi yang perlu dikemaskini:
- `docs/01-development-plan.md` — tambah Fasa 12 dengan semua tugas dan kriteria keluar.
- `docs/04-rbac-permission-matrix.md` — tambah permission `manage election settings` untuk Admin.
- `docs/05-workflow-design.md` — tambah bahagian pengurusan tetapan pilihan raya.
- `docs/progress-log.md` — rekod selepas siap.
- `docs/changelog.md` — rekod selepas siap.
- `docs/decision-log.md` — rekod keputusan reka bentuk halaman settings.
---
### 12-B: Pembetulan Semakan IC Duplikasi untuk Rekod Soft-Deleted
Masalah semasa:
- Semakan IC duplikasi dalam `StorePublicApplicationRequest` menapis rekod aktif sahaja, tetapi soft-deleted KTM-created records masih wujud dalam pangkalan data.
- Jika KTM delete rekod pemohon (`deleted_by_ktm`), rekod tersebut soft-deleted tetapi IC dalam `applications` masih boleh menyebabkan konflik bergantung kepada cara query dikodkan.
- Risiko: pemohon awam mungkin diblock padahal KTM sudah delete rekod mereka.
Tugas:
- Semak semula query semakan IC duplikasi dalam `StorePublicApplicationRequest` dan mana-mana service yang menjalankan semakan serupa.
- Pastikan rekod `deleted_at IS NOT NULL` (soft-deleted) tidak diambil kira sebagai "aktif" dalam semakan duplikasi.
- Pastikan `withTrashed()` atau scoped query digunakan secara eksplisit dan konsisten.
- Tambah kes ujian: KTM delete rekod → pemohon awam dengan IC sama boleh mohon semula.
- Semak `KtmVacancyService` dan `AssignmentVacancyService` juga untuk memastikan tiada pengiraan yang termasuk soft-deleted rows secara tidak sengaja.
Kriteria keluar:
- Ujian baru lulus: soft-deleted KTM record tidak menghalang permohonan awam baharu.
- Semua semakan IC dalam system menggunakan kaedah yang sama dan konsisten.
Dokumentasi yang perlu dikemaskini:
- `docs/05-workflow-design.md` — perjelas bahawa soft-deleted records dikecualikan dari semakan IC aktif.
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
---
### 12-C: Perkukuh Enforcement Nota Catatan Post-Pendaftaran
Masalah semasa:
- `AdminPostCloseNoteService` menguatkuasakan keperluan `catatan` pada peringkat service layer.
- Jika ada controller baru yang lupa panggil service ini, semakan tidak berlaku dan Admin boleh edit rekod tanpa nota selepas pendaftaran ditutup tanpa sebarang amaran.
- Enforcement bergantung sepenuhnya pada konvensyen pemanggilan, bukan pada mekanisme framework.
Tugas:
- Semak semua controller Admin yang boleh mengubah `Application`, `StaffAssignment`, `PoliceEscort`, `KkmRepresentative`, atau `JkmRepresentative` selepas pendaftaran ditutup.
- Tambah senarai semak di `AdminPostCloseNoteService` yang boleh dipanggil secara konsisten.
- Pertimbangkan untuk tambah `middleware` khusus pada route group Admin management yang secara automatik menjalankan semakan ini, dan reject request tanpa `catatan` apabila pendaftaran ditutup.
- Jika middleware digunakan, dokumentasikan dalam `docs/decision-log.md`.
- Tambah ujian integrasi untuk setiap route Admin management yang sepatutnya enforce semakan ini.
Kriteria keluar:
- Semua route management Admin yang mengubah rekod domain enforce catatan secara konsisten apabila pendaftaran ditutup.
- Ujian baru mengesahkan enforcement pada setiap route yang berkenaan.
- Tiada jalan pintas yang boleh bypass semakan ini tanpa sengaja.
Dokumentasi yang perlu dikemaskini:
- `docs/05-workflow-design.md` — dokumentasikan mekanisme enforcement yang dipilih.
- `docs/decision-log.md` — rekod keputusan sama ada guna middleware atau service pattern.
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
---
### 12-D: Pembetulan SampleElectionSeeder dan Konsistensi Nama Jawatan
Masalah semasa:
- Selepas migrasi Phase 11 menukar `CALON_SIMPANAN` kepada `CALON_TAMBAHAN`, ada kemungkinan `SampleElectionSeeder.php` masih mengandungi rujukan kepada nama atau slug lama.
- Jika seeder dijalankan semula (fresh seed untuk UAT atau persekitaran baharu), data yang dijana mungkin tidak konsisten dengan `PositionSeeder`.
Tugas:
- Buka dan audit `SampleElectionSeeder.php` secara menyeluruh.
- Cari semua rujukan kepada `CALON_SIMPANAN` atau string berkaitan dan gantikan dengan `CALON_TAMBAHAN`.
- Pastikan semua slug jawatan dalam seeder sepadan tepat dengan apa yang `PositionSeeder` jana.
- Jalankan `php artisan migrate:fresh --seed` dan pastikan tiada ralat.
- Jalankan `php artisan test` dan pastikan semua 80 ujian lulus.
Kriteria keluar:
- `php artisan migrate:fresh --seed` selesai tanpa ralat.
- `php artisan test` lulus sepenuhnya.
- Tiada rujukan kepada `CALON_SIMPANAN` dalam mana-mana seeder.
Dokumentasi yang perlu dikemaskini:
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
---
### 12-E: Konsistensikan Semakan Jenis Dokumen pada Semua Path Download
Masalah semasa:
- Admin Kewangan route download secara eksplisit mengehad kepada `bank_statement` sahaja.
- Route download PPM, Admin, dan Admin Kewangan masing-masing menggunakan implementasi yang berbeza.
- Jika ada ketidakkonsistenan dalam cara jenis dokumen disahkan, pengguna yang dibenarkan mungkin boleh download jenis dokumen yang sepatutnya terhad untuk mereka.
Tugas:
- Audit semua route download dokumen: PPM, Admin, dan Admin Kewangan.
- Cipta satu senarai jenis dokumen yang dibenarkan per peranan (`document_type` allowlist).
- Refactor semakan jenis dokumen ke dalam satu tempat — boleh dalam `DocumentDownloadController` atau policy `ApplicationPolicy`.
- Tambah ujian untuk setiap peranan mengesahkan mereka:
- Boleh download dokumen yang dibenarkan.
- Tidak boleh download dokumen di luar skop mereka walaupun ID dokumen diketahui.
- Pastikan 403 dikembalikan, bukan 404, untuk download yang diblock (supaya mesej ralat tidak mendedahkan kewujudan dokumen).
Kriteria keluar:
- Semua path download dokumen menggunakan semakan jenis yang konsisten.
- Ujian baru mengesahkan boundary setiap peranan.
- Tiada path yang boleh bypass semakan jenis dokumen.
Dokumentasi yang perlu dikemaskini:
- `docs/04-rbac-permission-matrix.md` — tambah baris untuk akses dokumen per peranan.
- `docs/decision-log.md` — rekod keputusan centralize semakan jenis dokumen.
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
---
## Fasa 13: Indeks Pangkalan Data dan Prestasi
Status: Belum dimulakan.
Skop fasa ini ialah menambah composite indexes yang diperlukan sebelum sistem mula menerima data sebenar dalam kuantiti besar.
### 13-A: Tambah Composite Indexes untuk Query Kerap
Masalah semasa:
- Query senarai Admin global (`/admin/management/applications`) menyaring mengikut `election_id`, `status`, dan `pusat_mengundi_id` tanpa composite index.
- Query `AssignmentVacancyService` dan `KtmVacancyService` menyaring `staff_assignments` mengikut `election_id`, `pusat_mengundi_id`, `position_id`, dan `is_active` tanpa composite index.
- Untuk pilihan raya dengan 5,00020,000 permohonan, query ini boleh menjadi lambat secara signifikan.
Tugas:
- Cipta migration baharu untuk menambah indexes (jangan ubah migration sedia ada).
- Tambah pada jadual `applications`:
- `(election_id, status)`
- `(election_id, pusat_mengundi_id, status)`
- `(election_id, ic_number)` — untuk semakan IC duplikasi
- Tambah pada jadual `staff_assignments`:
- `(election_id, pusat_mengundi_id, position_id, is_active)`
- `(election_id, saluran_mengundi_id, position_id, is_active)`
- `(reports_to_assignment_id, is_active)` — untuk KtmVacancyService
- Tambah pada jadual `bank_verifications`:
- `(election_id, status)`
- Gunakan nama index yang pendek dan eksplisit (ikut konvensyen sedia ada dalam sistem).
- Jalankan `php artisan migrate` dan sahkan indexes wujud.
- Jalankan `php artisan test` dan pastikan semua ujian lulus.
Kriteria keluar:
- Migration berjaya tanpa ralat.
- Semua ujian lulus.
- Query utama pada senarai admin menggunakan indexes (boleh disahkan dengan `EXPLAIN` dalam MySQL Workbench).
Dokumentasi yang perlu dikemaskini:
- `docs/03-database-design.md` — tambah bahagian indexes dan justifikasi.
- `docs/decision-log.md` — rekod keputusan indexes yang ditambah dan sebab.
- `docs/08-deployment-notes.md` — tambah arahan semak indexes semasa deployment.
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
---
## Fasa 14: Portal Status Permohonan Pemohon Awam
Status: Belum dimulakan.
Skop fasa ini ialah memberi pemohon awam cara untuk semak status permohonan mereka tanpa perlu login atau hubungi Admin.
### 14-A: Halaman Status Permohonan via UUID Awam
Masalah semasa:
- Pemohon awam hanya menerima redirect ke `/permohonan/{uuid}/berjaya` selepas mohon.
- Tiada cara untuk semak status kemudian (diluluskan? ditolak? kenapa ditolak?).
- Ini menyebabkan beban sokongan kepada Admin dan PPM.
Tugas:
- Tambah route `GET /permohonan/{application:public_uuid}/status`.
- Halaman ini tidak memerlukan login — cukup UUID awam permohonan sebagai pengecam.
- Paparkan maklumat terhad: nama pemohon (sebahagian), jawatan dipohon, pusat mengundi, status semasa, tarikh kemaskini terakhir.
- Jika status `rejected`, paparkan sebab penolakan jika ada.
- Jika status `assigned`, paparkan pengesahan penempatan tanpa mendedahkan butiran dalaman (saluran ID, dsb.).
- Jangan paparkan nombor IC penuh, nombor akaun bank, atau data sensitif lain.
- Gunakan `SensitiveData` helper untuk mask nama sebahagian jika perlu.
- Tambah ujian untuk: permohonan berstatus submitted, approved, assigned, rejected, dan UUID tidak wujud.
Kriteria keluar:
- Pemohon boleh semak status dengan hanya URL yang mengandungi UUID awam.
- Data sensitif tidak didedahkan.
- Halaman tidak mendedahkan sama ada UUID wujud atau tidak kepada orang lain (status 200 dengan mesej umum untuk UUID tidak dikenali, bukan 404).
Dokumentasi yang perlu dikemaskini:
- `docs/05-workflow-design.md` — tambah bahagian portal status pemohon.
- `docs/06-ui-ux-plan.md` — tambah reka bentuk halaman status.
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
- `docs/decision-log.md` — rekod keputusan reka bentuk privacy (status 200 vs 404 untuk UUID tidak dikenali).
---
## Fasa 15: Pengurusan Eksport dan Data Sensitif
Status: Belum dimulakan.
Skop fasa ini ialah memastikan fail eksport yang mengandungi data sensitif tidak kekal dalam storage tanpa had masa.
### 15-A: Purge Automatik Fail Eksport Lama
Masalah semasa:
- Fail XLSX eksport kewangan (disimpan di `exports/finance`) dan eksport kehadiran (disimpan di `exports/attendance`) disimpan dalam private storage tanpa had masa.
- Fail-fail ini mengandungi data bank, nombor IC, dan maklumat peribadi lain.
- Tiada mekanisme untuk padam fail lama secara automatik.
Tugas:
- Tambah `ExportPurgeCommand` (`php artisan exports:purge`) sebagai Artisan command.
- Command menerima parameter `--days=` (default: 30) untuk menentukan tempoh simpanan.
- Command akan:
- Query `export_logs` untuk rekod lebih lama daripada tempoh yang ditetapkan.
- Padam fail dari storage disk yang berkaitan.
- Kemaskini `export_logs` dengan `purged_at` dan `purged_by` (system).
- Log aktiviti purge.
- Daftarkan command dalam `bootstrap/app.php` atau `routes/console.php` sebagai scheduled task (contoh: harian pada tengah malam).
- Tambah kolum `purged_at` pada jadual `export_logs` melalui migration baharu.
- Tambah ujian untuk: command berjaya padam fail lama, fail baru tidak terpadam, `export_logs` dikemaskini.
Kriteria keluar:
- Command boleh dijalankan secara manual dan secara scheduled.
- Fail lebih lama dari tempoh yang ditetapkan dipadamkan dari storage.
- `export_logs` menunjukkan rekod purge.
- Fail yang masih dalam tempoh simpanan tidak terpadam.
Dokumentasi yang perlu dikemaskini:
- `docs/03-database-design.md` — tambah kolum `purged_at` dalam jadual `export_logs`.
- `docs/08-deployment-notes.md` — tambah arahan konfigurasi scheduler dan polisi simpanan eksport.
- `docs/decision-log.md` — rekod keputusan tempoh simpanan default dan strategi purge.
- `docs/progress-log.md` dan `docs/changelog.md` — rekod selepas siap.
---
## Ringkasan Keutamaan
| Fasa | Tajuk | Keutamaan | Status |
|------|-------|-----------|--------|
| 12-A | Admin Settings UI (toggle kehadiran/pendaftaran) | Kritikal | **Selesai 2026-06-02** |
| 12-B | Pembetulan semakan IC soft-deleted | Kritikal | **Selesai 2026-06-02** |
| 12-C | Perkukuh enforcement nota catatan | Kritikal | **Selesai 2026-06-02** |
| 12-D | Pembetulan SampleElectionSeeder | Kritikal | **Selesai 2026-06-02** |
| 12-E | Konsistensikan semakan jenis dokumen download | Kritikal | **Selesai 2026-06-02** |
| 13-A | Tambah composite indexes pangkalan data | Prestasi | **Selesai 2026-06-02** |
| 14-A | Portal status permohonan pemohon awam | UX | **Selesai 2026-06-02** |
| 15-A | Purge automatik fail eksport sensitif | Data | **Selesai 2026-06-02** |
---
## Nota Pelaksanaan
- Setiap item dalam Fasa 12 boleh dilaksanakan secara bebas dan tidak perlu tunggu item lain selesai.
- Fasa 13 patut dilaksanakan sebelum data sebenar mula dimasukkan ke dalam sistem.
- Fasa 14 dan 15 boleh dilaksanakan secara selari kerana tidak ada kebergantungan antara satu sama lain.
- Setiap pembetulan mesti menjalankan semula suite ujian penuh (`php artisan test`) sebelum dianggap selesai.
- Jalankan `vendor\bin\pint.bat --test` dan `vendor\bin\phpstan.bat analyse --memory-limit=1G` selepas setiap fasa.