# Initial Architecture ## Technology Stack - Backend: Laravel 13.12.0, installed through `laravel/laravel` 13.8.0. - Database: MySQL. - Views: Blade. - Styling: Bootstrap 5 with Bootstrap Icons. - JavaScript: Vite-managed assets, jQuery where it improves progressive enhancement, plus selected UI helpers. - Queue: Laravel queue system for email and heavier export-related tasks where useful. - Mail: Laravel Mail and Notifications with Markdown mail templates. - Authorization: Laravel policies, gates, middleware, and `spatie/laravel-permission`. - Auditing: `spatie/laravel-activitylog` plus domain-specific history tables where a structured audit timeline is needed. - Export: OpenSpout for current PHP 8.5 compatibility. `maatwebsite/excel` remains the preferred package from the original requirement but was not installable in this environment during Phase 1. ## Phase 1 Implemented Structure Implemented: - Breeze auth controllers and routes. - Generic `/register` routes disabled. - Bootstrap-based `layouts.app`, `layouts.guest`, and navigation. - Role-aware dashboards: - `/admin/dashboard` - `/kewangan/dashboard` - `/ppm/dashboard` - `/ktm/dashboard` - `/pemohon/dashboard` - `/dashboard` role redirect. - Spatie role middleware aliases: - `role` - `permission` - `role_or_permission` - `RolePermissionSeeder`. - Default Admin seed account from `config/prn.php`. ## Application Structure Planned directories: ```text app/ Actions/ Exports/ Http/ Controllers/ Requests/ Middleware/ Models/ Notifications/ Policies/ Services/ Support/ ``` Guidelines: - Controllers orchestrate requests and responses only. - Form Request classes validate input and authorize request-specific actions. - Policies enforce model-level access. - Services hold business rules and transactional workflows. - Action classes may be used for high-value operations such as approving applications, changing assignments, registering KTM-created KP, and recording attendance. - Export classes live in `app/Exports`. - Report filters and query preparation live in services, not controllers. ## Architectural Layers ### Presentation Layer - Blade templates with Bootstrap 5. - Responsive layouts for desktop, tablet, and mobile. - Shared layout components for navigation, cards, filters, badges, breadcrumbs, tables, empty states, and modals. - Mobile-friendly table alternatives for high-density data. ### HTTP Layer - Named routes. - Route groups by role and module. - Middleware for authentication, role, registration period, and public QR validation. - Route model binding using internal IDs for authenticated admin areas where safe. - Public routes use UUID/ULID identifiers only. ### Domain Layer Core services: - `RegistrationPeriodService` - `VacancyService` - `ApplicationService` - `AssignmentService` - `KtmTeamService` - `PpmScopeService` - `BankVerificationService` - `AttendanceService` - `WheelchairService` - `ExportLoggingService` - `SensitiveDataMaskingService` Potential action classes: - `SubmitPublicApplication` - `CreateKtmApplicant` - `ApproveApplication` - `RejectApplication` - `ChangeApplicantRole` - `AssignStaffToSaluran` - `RecordAttendance` - `VerifyBankDetails` - `RecordWheelchairTransaction` ### Data Layer - Eloquent models and relationships. - Foreign keys for domain integrity. - Soft deletes for records that should remain auditable. - Domain history tables for applications and assignments. - Activity log for actor/value snapshots and operational traceability. ## Role-Based Areas Planned route groups: ```text /dashboard /admin/... /ppm/... /ktm/... /kewangan/... /pohon/{pusat_mengundi_uuid} ``` Expected access: - `Admin`: full operational management. - `Admin Kewangan`: finance verification and finance exports only. - `PPM`: assigned Pusat Mengundi only. - `KTM`: assigned Saluran/team only. - `Pemohon`: public form and own submission flow only if login is later required. ## Public Identifier Strategy - Public QR links must use UUID or ULID stored on `pusat_mengundis.public_uuid` or equivalent. - Internal auto-increment IDs must not appear in public application URLs. - Uploaded documents are accessed only through authenticated authorization checks and signed/temporary download responses where needed. ## Dual-Role Assignment Strategy The system must support a PPM who is also KTM. This should not be modeled as a single role column on a user or application. Planned approach: - Use `users` for login identity. - Use `applications` or staff records for applicant/staff biographical and banking data. - Use `staff_assignments` as the canonical placement table. - A person can have multiple active `staff_assignments` within the same election when business rules allow it. - `staff_assignments` references `position_id`, `pusat_mengundi_id`, optional `saluran_mengundi_id`, and optional supervisor/team references. - Uniqueness constraints prevent invalid duplicate active assignments, while allowing explicitly permitted dual role such as PPM + KTM. ## Audit Strategy Use two audit levels: - Structured domain histories for application status and assignment changes. - General activity log for before/after data changes, actor, timestamp, source, and notes. Audit targets: - Application approval/rejection. - Role changes. - Assignment changes. - Document upload/change. - Bank verification. - Admin edits after registration closes. - Attendance updates. - Wheelchair transactions. - Excel exports. ## File Storage Strategy - IC documents and bank statements are stored on Laravel private storage disk. - Public symlink storage must not expose sensitive uploads. - File validation must restrict MIME type, size, and extension. - Document access must pass policy checks. - File records should be stored in `application_documents` with document type, disk, path, original name, MIME type, size, uploader, and timestamps. ## Export Strategy - `maatwebsite/excel` will generate XLSX exports. - Every export inserts a row into `export_logs`. - Export logs include generated_by, generated_at, report_type, filter parameters, and file name. - Export services prepare queries and filters. - Export classes only shape spreadsheet data. ## Queue and Mail Strategy - KTM-created applicant email notification should use Laravel Notifications or Mailables. - Queue should be enabled for mail in production. - Local development can use log mailer or local mail catcher. - Admin-keyed records do not trigger bank account email requests. ## Security Principles - Use CSRF protection for all form submissions. - Use policies and middleware for every protected module. - Validate uploads strictly. - Store sensitive files privately. - Mask IC, bank account, phone, and email where full values are unnecessary. - Avoid raw SQL unless justified and documented. - Use transactions for approval, assignment, finance verification, and attendance updates.