first
This commit is contained in:
247
docs/08-deployment-notes.md
Normal file
247
docs/08-deployment-notes.md
Normal file
@@ -0,0 +1,247 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user