Files
prn2026/docs/09-improvement-plan.md
2026-06-03 08:51:22 +08:00

324 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.