One workspace for legal aid, case records & panel lawyers.
iGuaman - Sistem Integrated Bantuan Guaman is the internal production system for JBG - Jabatan Bantuan Guaman Malaysia (the Legal Aid Department). "Integrated" = two legacy systems (Rekod Kes + Peguam Panel) fused into one Laravel app, plus a new public advisory + appointment layer and an AI chatbot.
v222 Penambahbaikan - shipped & tested
v2 closes the full SENARAI PENAMBAHBAIKAN SUBSISTEM: 22 improvement requests against the consolidated app, sequenced foundation-first around a new central claim ledger. 21 fully shipped, 1 (OCR) deferred to the Python microservice. Merged to main and pushed to production; suite 377/377 green. See the full 22-wish status →
actor_id + before/after diff), aria-label on every form field, chatbot PII minimisation + PDPA notice, and PHPStan level 5 + CI. Suite grew 351 → 377.🧾 Central claim ledger
New lejar_tuntutan_bayaran - one polymorphic money trail for KN, Pembelaan, Mediasi & external-lawyer claims. Auto-creates on paid advisory selesai().
⇄ Branch transfer + KPI
Move a case or KN between branches with zero history loss (everything keys off id_kes) and dual-branch visibility. New 12-month in/out KPI matrix.
🛡 Pembelaan Awam
Public criminal-defence cases ride the existing 3-tier spine as tagged forms rows (no new table). Interim → muktamad legal-aid certificate with PDF.
⚖️ Mediation, first-class
Its own PGT… file number, standalone or via-litigation intake, and mediator assignment that opens a MEDIASI ledger row.
💬 KN intake & iPayment
Intake split by source (prison/clinic vs public) with a new prison_officer role; manual counter payments record a receipt into the KN + ledger.
🔔 Real-time integration
Laravel events + a queued listener (a transfer notifies the destination branch). CawanganScope branch-isolation extended beyond forms to khidmat_nasihat.
01What iGuaman actually is
Three legacy/origin systems were merged into a single Laravel application with one login table and one permission layer. Understanding the three origins is the fastest way to understand everything else.
📂 1 · Sistem Rekod Kes
The litigation backbone. A citizen applies for legal aid → the Director approves/rejects → the case runs through mediation (pengantaraan) or court (mahkamah) → the file is closed. Centered on the 94-column forms table.
⚖️ 2 · Sistem Peguam Panel
The panel-lawyer side. Private lawyers apply to join the panel, get vetted, and are assigned cases through a 3-tier approval spine (PPUU → Director → Director General). Tracks workload, withdrawals, and practice areas.
💬 3 · Khidmat Nasihat + Janji Temu
New layer (ported from iGuaman Janji Temu). Legal-advisory applications with eligibility screening, appointment booking on a slot calendar, attendance tracking, feedback, and a bridge to open a full case. Includes a public citizen portal + AI chatbot.
users table with a user_type of staff, lawyer, or awam (citizen). On login each type lands in its own portal. One spatie/laravel-permission layer governs everything; admin is a super-admin that bypasses all checks via Gate::before.02Module map - what's inside
Every functional area, grouped. This is the table of contents of the actual app menu.
🗂 Rekod Kes
Case CRUD, OYD registry, closed files, attachments, per-case PDF printouts.
⚖️ Pengantaraan / Mahkamah
Mediation sections + hearing reschedule; civil/syariah court records & case reports.
⇄ Agihan Peguam
3-tier case-to-lawyer assignment, workload board, over-time auto-reassign.
👔 Panel Peguam
Lawyer applications, vetting, withdrawals, practice-area add/drop, activate/deactivate.
💬 Khidmat Nasihat
Advisory applications, eligibility screening, officer processing, KN→case bridge.
📆 Janji Temu / Slot
Slot generation per branch/room, session config, operational closures, calendar.
📊 Statistik & Laporan
SLA matrices, mediation stats, file-number error log, KPI, 8 KN reports, CSV/Excel/PDF.
🛠 Pentadbiran & Selenggara
Users, roles & access matrix, staff registry, audit log, all reference masters, e-Poster.
🌐 Portal Awam
Citizen IC-login, self-service KN application wizard, upload, reschedule/cancel.
🤖 AI@JBG Chatbot
Public widget → Laravel proxy → Python microservice. Throttled.
📝 Maklum Balas
Public post-appointment satisfaction feedback - no login, one per advisory.
🔑 Auth & Akaun
Plain login, password reset, forced password change for migrated accounts.
🧾 Lejar Tuntutan v2
Central claim ledger across KN, Pembelaan, Mediasi & external lawyers; officer lifecycle + receipt step.
⇄ Pemindahan Cawangan v2
Branch transfer engine for cases & KN + dual-branch worklists + 12-month transfer KPI.
🛡 Pembelaan Awam v2
Public criminal-defence cases on the litigation spine; interim → muktamad legal-aid certificate.
🔔 Events & Queue v2
Lifecycle events + queued listeners (transfer notifications); cross-module real-time integration.
03Technical architecture
A conventional Laravel MVC stack with a thin-controller / service-layer split. Business rules live in app/Support/*Service.php; controllers handle transport + gating; Eloquent models map the legacy schema.
🧱 Stack
| Language | PHP 8.3 |
| Framework | Laravel 13 |
| Database | MySQL 8.4 (iguaman_2in1) |
| Views | Blade + vanilla JS |
| Assets | Vite 8 + Tailwind v4 |
| Auth | Custom controller + Auth::attempt |
| RBAC | spatie/laravel-permission |
| PDF / Excel | dompdf · maatwebsite/excel |
| Chatbot | Python microservice + Laravel proxy |
⚙️ Service layer (app/Support)
Domain logic extracted out of controllers:
Plus one policy (KhidmatNasihatPolicy) and a Gate::before super-admin bypass for admin.
The 6 layers a request passes through
whereNumber / whereIn.auth, guest, permission:x, role:x|y, throttle:n,1, plus custom ForcePasswordChange & SecurityHeaders.#[Fillable].04Request lifecycle
A typical authenticated, permission-gated request - e.g. a PPUU picking a lawyer for a case.
system.login (wired in bootstrap/app.php via redirectGuestsTo).
05Security model
🔐 Auth & sessions
Plain Auth::attempt, bcrypt-hashed passwords, session-based. No SPA tokens. Three login surfaces (staff / lawyer share one, citizen separate).
🧱 RBAC + super-admin
Every staff route gated by a named permission. admin bypasses all via Gate::before. Role/permission matrix editable in-app (Peranan & Akses).
🔁 Forced password change
Migrated legacy accounts pinned to /password/change via ForcePasswordChange middleware until must_change_password clears.
⏱ Throttling
Login (10/min), public forms & uploads (6–20/min), chatbot (20/min), feedback (6/min). Honeypot + captcha on public application forms.
📎 Private file access
Attachments stored on a private disk, streamed only through auth + ownership checks. Citizens can only download their own KN documents.
🧾 Audit + headers
audit_trail records sensitive actions with the acting user (actor_id) and field-level before/after diffs; SecurityHeaders middleware sets hardening headers; CSRF on all state-changing forms.
06Users & roles
Three user types (which portal you land in) and twelve roles (what you can do) - the original eight plus three v2 additions (prison_officer + the two Pembelaan Awam approver tiers) and the awam citizen role. The Malay hierarchy mirrors a real government legal-aid department.
🛡 admin
Super-admin. Bypasses every permission via Gate::before. Only role granted role/permission management (urus.peranan).
👑 ketua_pengarah
Director General. Final approver - the top of every 3-tier chain (assignment, withdrawal, practice-area, panel application).
🎖 pengarah
Director. Approves/rejects case applications, endorses (sokong) lawyer picks, closes files. The middle tier.
🧭 koordinator
Coordinator. Branch-wide operations, maintenance masters, can also act as case distributor. Sees all branches.
🧑💼 pegawai
Officer. Case data entry, advisory (KN) processing. The everyday operational role.
📑 ppuu
Penolong Pegawai Undang-Undang. The case distributor - vets new cases and picks panel lawyers (ppuuPilih).
🗃 pembantu_tadbir
Admin assistant / clerk. Screening, data, KN viewing. Excluded from KN processing & approvals.
👔 peguam
Panel lawyer (external). Own portal only - accept/reject case offers, report, withdraw, manage practice areas.
🏛 prison_officer v2
Prison / clinic officer. Files Khidmat Nasihat on behalf of inmates. Reaches the staff area + KN intake only (no approvals, no payments).
🛡 pembelaan-awam tiers v2
pengarah_pembelaan_awam · ketua_pembelaan_awam. The forked criminal-track approver tier for panel registration (W10) - endorse / decide on the jenayah jalur.
awam.portal permission - enough to run the self-service advisory wizard and nothing else. Lawyers (peguam) similarly hold only lawyer.area.07Permission matrix
Exact role→permission grants from RolePermissionSeeder. admin is omitted from rows - it implicitly has all via Gate::before. Read down a column to see what a role can reach.
| Permission | pengarah | koord. | pegawai | ppuu | p.tadbir | ketua_p. | peguam |
|---|---|---|---|---|---|---|---|
| system.view | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | · |
| kes.view / create / update | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | · |
| kes.keputusan (approve/close) | ✔ | · | · | · | · | ✔ | · |
| pengantaraan / mahkamah / lampiran | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | · |
| oyd.manage · cetakan · kpi · laporan | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | · |
| statistik.view | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | · |
| agihan.manage | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | · |
| agihan.ppuu (pick lawyer) | · | ✔ | · | ✔ | · | · | · |
| agihan.pengarah (endorse) | ✔ | · | · | · | · | · | · |
| agihan.kp (final approve) | · | · | · | · | · | ✔ | · |
| khidmat.view / manage | ✔ | ✔ | ✔ | · | ✔ | ✔ | · |
| khidmat.proses (advisory processing) | ✔ | ✔ | ✔ | · | · | · | · |
| slot.view / slot.manage | ✔ | ✔ | ✔ view | · | ✔ | ✔ | · |
| peguam.semak (vet application) | · | ✔ | · | ✔ | ✔ | · | · |
| peguam.sokong (endorse) | ✔ | · | · | · | · | · | · |
| peguam.keputusan (decide) | · | · | · | · | · | ✔ | · |
| selenggara.* (maintenance masters) | ✔ | ✔ | · | · | · | ✔ | · |
| urus.pengguna · audit.view | ✔ | ✔ | · | · | · | ✔ | · |
| menu.selenggara | ✔ | ✔ | · | · | · | · | · |
| cawangan.view-all (cross-branch) | · | ✔ | · | · | · | ✔ | · |
| urus.peranan | · | · | · | · | · | · | · |
| lawyer.area / awam.portal | · | · | · | · | · | · | ✔ |
urus.peranan = admin only · awam.portal = citizen type only. Branch isolation: most staff see only their cawangan; koordinator + ketua_pengarah see all (cawangan.view-all).
tuntutan.view/manage/semak/lulus/bayar (claim ledger, W15) · agihan.luar (external-lawyer KN, W5) · kes.pindah (branch transfer, W7) · pengantaraan.agih (mediator assignment, W19) · pembelaan.view/manage + kes.perakuan (Pembelaan Awam + certificate, W9/W14). New roles: prison_officer (KN intake) and the pengarah/ketua_pembelaan_awam approver tiers. Branch isolation (CawanganScope) now also covers khidmat_nasihat (W21), closing the cross-branch read gap.08The 3 portals
Each user type gets a different shell after login (chosen by User::homeRoute()). Menu items appear/disappear by permission (@can).
staff · sidebar shell · /system
- Senarai Kes
- Permohonan Baharu
- OYD
- Fail Tutup
- Statistik
- Statistik SLA
- Kesilapan No. Fail
- Statistik Pengantaraan
- KPI
- Laporan
- Laporan KN
- Permohonan Khidmat
- Pemprosesan KN
- Jadual Janji Temu
- Penjanaan Slot
- Penutupan Operasi
- Permohonan Peguam
- Agihan Kes
- Beban Tugas
- Tarik Diri
- Kemaskini Bidang
- Pengguna
- Pegawai JBG
- Log Audit
- Peranan & Akses
- Jenis Kes
- Mahkamah
- Cuti
- Cawangan
- Jenis Khidmat
- Jawatan
- e-Poster
lawyer · topbar shell · /peguam
- Dashboard
- Kes Saya
- Tawaran
- Profil
- Terima / Tolak tawaran
- Hantar laporan kes
- Tarik diri dari kes
- Tambah / gugur bidang
- Kemaskini profil
- /peguam/daftar (apply to panel - no login)
citizen · /awam · IC login
- Daftar (IC)
- Log Masuk
- Permohonan Saya (dashboard)
- Saringan kelayakan
- Permohonan baharu (wizard)
- Tempah slot janji temu
- Muat naik lampiran
- Jadual semula / Batal
- AI@JBG chatbot
- Maklum balas selepas temu janji
09Process flow · Case lifecycle
A legal-aid case (the forms row). Two status fields run in parallel: status (the high-level file state) and status_agihan (the assignment sub-state, see next section).
File status - forms.status
laporan_kes child reports), attach files, and print per-case PDFs (ringkasan, penugasan, laporan).10Process flow · 3-tier lawyer assignment (Agihan)
The heart of the panel system. forms.status_agihan is a numeric state machine (0–17). A new case climbs PPUU → Pengarah → Ketua Pengarah before it's offered to a lawyer, who accepts or bounces it back.
Happy path - new case to accepted
StatusAgihan); each arrow names the acting role.📥 Bucket: Baru
New & in-approval cases. Statuses 0, 8, 10, 13, 9, 15, 14.
📤 Bucket: Semasa
Offered / active / over-time. Statuses 1, 2, 7.
🔁 Bucket: Semula
Re-assignment loop. Statuses 4, 15.
1) within the SLA window, the case flips to 7 LEBIH_MASA and re-enters the re-pick loop. Deactivating a lawyer (nyahaktif) similarly redistributes their active cases.11Process flow · Khidmat Nasihat (advisory + appointment)
The advisory record (khidmat_nasihat.status_kn) and its appointment (temu_janji.status) move together. A completed advisory can spawn a full litigation case ("Buka Kes").
Advisory status - status_kn
Appointment status - temu_janji.status
SlotAvailabilityService generates bookable slots per cawangan + bilik + date, honoring weekends, public holidays (ref_cuti / cuti negeri) and operational closures (penutupan_operasi). The /slot/tarikh & /slot/masa JSON endpoints are shared by staff and citizens.12Process flow · Citizen journey (Awam)
The self-service path a member of the public takes - no staff involvement until officer processing.
13Process flow · Lawyer-side & staff review queues
What a panel lawyer initiates, and the 3-tier staff queues that approve it. Both withdrawal and practice-area changes climb PPUU/Pengarah → Pengarah → Ketua Pengarah.
Tarik Diri - lawyer withdraws from an active case
Kemaskini Bidang - add / drop a practice area
butiran_peguam_panel_6.checkbox_value_status. Drop is blocked if the lawyer still has an active case in that category.14Process flow · Panel lawyer application
A prospective lawyer applies publicly; staff vet in three tiers. On approval the application becomes a live peguam_panel record. butiran_peguam_panel_2.permohonan_status.
15Data model
~52 tables total: 20 imported legacy tables + ~15 new (batches 8–13) + the v2 ledger & transfer tables + 7 spatie permission tables + Laravel framework tables. Grouped by domain below.
📂 Core case records
forms is the 94-column case spine. History & child tables hang off it via id_kes.
👔 Lawyer panel
IC-keyed (kp_peguam / kpBaru). One master + 6 detail tables (qual, firm, bank, specialization).
💬 Khidmat Nasihat
Advisory master + 3-level category tree + feedback.
📆 Appointments / calendar
Slot engine + branches/rooms + closures.
📚 Reference / master
Flat lookup tables. ref_kes (litigation taxonomy) is separate from the KN category tree.
🔧 System / auth
Unified login, RBAC, audit, uploads, announcements.
🆕 v2 - ledger & transfer
The central claim ledger (polymorphic across sources) and the shared branch-transfer journal. KN also gained applicant_source, waiver/resit links, mediation & certificate columns.
Key relationships
| From | → | To | Via |
|---|---|---|---|
| forms | → | laporan_kes · sejarah_* | id_kes |
| khidmat_nasihat | → | users (applicant + assigned officer) | id_pengguna · id_pegawai_kn |
| khidmat_nasihat | → | cawangan · ref_kategori_kn · ref_subkategori_kn | FK nullOnDelete |
| khidmat_nasihat | → | temu_janji · forms (Buka Kes bridge) | id_temu_janji · id_forms |
| khidmat_nasihat | → | maklum_balas (1:1, unique) | khidmat_nasihat_id |
| temu_janji | → | slot_temu_janji · cawangan | FK |
| slot_temu_janji | → | cawangan · bilik | FK cascade/null |
| bilik · penutupan_operasi | → | cawangan | cawangan_id |
| butiran_peguam_panel_3…6 | → | butiran_peguam_panel_2 | kpBaru (IC index, no FK) |
| uploaded_files | → | forms · khidmat_nasihat · users | id_kes · id_khidmat · user_doc_id |
| users | ↔ | roles ↔ permissions (spatie) | pivot tables |
users extra columns: user_type (staff/lawyer/awam), role, cawangan, nokp (IC), id_peguam_panel (links a lawyer login to their panel record), is_active, must_change_password, last_login_at. FK strategy: bigint (new) tables get real FKs; legacy int tables (ref_negeri, forms.id) use plain indexes only.16The KN category tree
A 3-level taxonomy used only for advisory (Khidmat Nasihat) - deliberately separate from the litigation ref_kes.
khidmat_nasihat references L1 (id_kategori) + L3 (id_subkategori), both nullOnDelete so reference data outlives advisory records.
17Glossary - Malay → English
The UI and code are in Malay. This decodes the recurring terms.
- JBG
- Jabatan Bantuan Guaman - the Legal Aid Department
- Guaman
- Litigation / legal (suit)
- Kes
- Case (the
formsrecord)
- Permohonan
- Application / request
- Peguam Panel
- Panel lawyer (private lawyer on the roster)
- Agihan
- Assignment / distribution (of cases to lawyers)
- OYD
- Orang Yang Dibantu - the assisted person / client
- Pengantaraan
- Mediation
- Mahkamah
- Court (sivil = civil, syariah = syariah)
- Sidang
- Court hearing / session
- Khidmat Nasihat
- Legal advisory service (KN)
- Janji Temu / Temu Janji
- Appointment
- Saringan
- Screening (eligibility check)
- Slot / Penjanaan Slot
- Appointment slot / slot generation
- Cawangan
- Branch (office)
- Bilik
- Room
- Penutupan Operasi
- Operational closure (block dates)
- Cuti
- Holiday (umum = public, negeri = state)
- Pengarah
- Director
- Ketua Pengarah
- Director General (KP)
- Koordinator
- Coordinator
- Pegawai
- Officer
- PPUU
- Penolong Pegawai Undang-Undang - assistant legal officer (case distributor)
- Pembantu Tadbir
- Administrative assistant (clerk)
- Semak / Semakan
- Review / check (vetting step)
- Sokong / Sokongan
- Endorse / recommendation
- Keputusan
- Decision
- Lulus / Tolak
- Approve / Reject
- Tawaran
- Offer (case offered to a lawyer)
- Tarik Diri
- Withdraw / withdrawal
- Bidang Pengkhususan
- Practice area / specialization
- Lebih Masa
- Over-time (offer not answered in SLA)
- Fail Tutup
- Closed file
- Beban Tugas
- Workload
- Laporan
- Report
- Maklum Balas
- Feedback
- Selenggara
- Maintenance (reference data admin)
- Pengguna
- User
- Peranan & Akses
- Role & access (permission matrix)
- Awam
- Public / citizen
- No. KP / NoKP
- IC number (national identity card)
- Buka Kes
- Open a case (KN → litigation bridge)
- Laluan Sumbangan
- Contribution path (when income exceeds the aid threshold)