# Deployment Notes ## Target Environment The application is intended for a standard Laravel production deployment using: - PHP compatible with selected Laravel version. - Composer. - MySQL. - Web server such as Nginx or Apache. - Node/npm only for building frontend assets, not necessarily required on production runtime if assets are built during deployment. - Queue worker for mail and background jobs. - Scheduler for Laravel scheduled tasks where needed. ## Local Environment Findings Inspection date: 2026-05-28 - PHP CLI: 8.5.1. - Composer: 2.9.4. - Node: 25.1.0. - npm works through `npm.cmd`; `npm` PowerShell shim is blocked by execution policy. - MySQL CLI is not available in PATH and must be confirmed before database setup. - `pdo_mysql` PHP extension is available. - MySQL 8.4.8 connection was confirmed through Laravel/PDO during Phase 2. - Local `.env` is configured for MySQL database `prn2026`. ## Environment Configuration Required `.env` values: ```text APP_NAME="Sistem Pengurusan Pusat Mengundi" APP_ENV=production APP_KEY= APP_DEBUG=false APP_URL= APP_TIMEZONE=Asia/Kuala_Lumpur DB_CONNECTION=mysql DB_HOST= DB_PORT=3306 DB_DATABASE= DB_USERNAME= DB_PASSWORD= QUEUE_CONNECTION=database MAIL_MAILER= MAIL_HOST= MAIL_PORT= MAIL_USERNAME= MAIL_PASSWORD= MAIL_ENCRYPTION= MAIL_FROM_ADDRESS= MAIL_FROM_NAME= FILESYSTEM_DISK=local SEED_ADMIN_NAME="Admin Sistem" SEED_ADMIN_EMAIL=admin@prn.local SEED_ADMIN_PASSWORD=password ``` Production must override the seeded Admin password before deployment or disable default seeding after the first secure Admin account is created. ## Storage Sensitive documents: - IC document. - Bank statement. Rules: - Store sensitive documents on private disk. - Do not expose sensitive uploads through public storage symlink. - Serve document downloads through authorized controller actions only. - Use secure file validation for MIME type, extension, and size. ## Deployment Steps Initial production deployment should follow this sequence: 1. Pull or upload application source. 2. Install Composer dependencies without dev packages. 3. Install/build frontend assets. 4. Configure `.env`. 5. Generate app key if not already configured. 6. Run migrations. 7. Run seeders for roles, permissions, positions, and initial Admin user where appropriate. 8. Cache configuration, routes, and views. 9. Start queue worker. 10. Configure scheduler. 11. Validate login and critical workflows. Planned commands: ```bash composer install --no-dev --optimize-autoloader npm.cmd ci npm.cmd run build php artisan key:generate php artisan migrate --force php artisan db:seed --force php artisan config:cache php artisan route:cache php artisan view:cache php artisan queue:restart ``` Commands may need adjustment for the actual hosting environment. ## Queue Worker Queue should handle: - KTM-created applicant email notifications. - Potentially larger exports. - Future notification jobs. Recommended: - Use database queue initially for simplicity. - Use Supervisor, Windows service wrapper, or hosting panel worker support to keep queue running. ## Scheduler Active scheduled tasks: | Command | Schedule | Purpose | |---|---|---| | `exports:purge --days=30` | Daily at 00:00 | Purge export files older than 30 days | To change the retention period, edit `routes/console.php` and update `--days=30`. Scheduler entry (add to OS cron): ```bash * * * * * php /path/to/artisan schedule:run >> /dev/null 2>&1 ``` To run purge manually: ```bash php artisan exports:purge --days=30 php artisan exports:purge --days=7 # shorter retention for testing ``` ## Security Checklist - `APP_DEBUG=false` in production. - Strong database credentials. - HTTPS enabled. - Private document storage. - Correct file permissions for storage and cache. - Document downloads must use authorized controller routes; do not expose `storage/app/private`. - Admin Kewangan document access is limited to bank statements. - Queue worker runs under least-privilege user. - Audit log retention policy defined. - Regular backups. - Admin accounts reviewed before launch. - Default development accounts removed or password-changed. ## Index Verification After Migration After running migrations on a fresh database, verify the performance indexes exist: ```sql SHOW INDEX FROM applications WHERE Key_name IN ( 'app_election_status_idx', 'app_ktm_position_idx' ); SHOW INDEX FROM staff_assignments WHERE Key_name IN ( 'sa_election_pusat_position_idx', 'sa_election_saluran_position_idx', 'sa_reports_to_pos_status_idx' ); ``` All of the above should return rows. If any are missing, re-run `php artisan migrate`. Use `EXPLAIN` on critical service queries to confirm index usage: ```sql -- KtmVacancyService: reserved application count EXPLAIN SELECT * FROM applications WHERE selected_ktm_assignment_id = ? AND requested_position_id = ? AND status IN ('submitted', 'under_ppm_review', 'approved'); -- KtmVacancyService: active KP count under a KTM EXPLAIN SELECT COUNT(*) FROM staff_assignments WHERE reports_to_assignment_id = ? AND position_id = ? AND status = 'active'; ``` Both should show `key` as the respective composite index, not NULL. ## Final Quality Gate Run before production release: ```bash php artisan route:list --except-vendor php artisan test vendor/bin/pint --test vendor/bin/phpstan analyse --memory-limit=1G npm.cmd run build ``` The Windows local environment uses `.bat` wrappers for vendor binaries: ```bash vendor\bin\pint.bat --test vendor\bin\phpstan.bat analyse --memory-limit=1G ``` ## Backup Checklist Back up: - MySQL database. - Private storage documents. - Export files if retained. - `.env` securely through infrastructure secret management, not public repository. Recommended frequency: - Daily database backups during active registration and polling period. - More frequent backup before and on polling day. - Storage backup aligned with database backups. ## Performance Notes - Use server-side pagination for large lists. - Add indexes for election, Pusat Mengundi, status, role, and IC lookup. - Avoid loading documents or large relationship graphs on index pages. - Use queued exports if datasets become large. - Cache role/permission checks through Spatie package defaults. - Keep attendance, finance, Admin management, and setup index pages paginated. - For very large datasets, move XLSX exports to queued jobs and notify users when complete. ## Release Notes Process Every deployment should update: - `docs/changelog.md` for user-facing changes. - `docs/progress-log.md` for implementation phase completion. - `docs/decision-log.md` for architecture, database, security, and package decisions.