# Step 23 — Global Search — Implementation Report

**Status:** COMPLETED  
**Verified:** 12 August 2026  
**Pull request:** #35

## Overview

Step 23 adds authenticated global search over the authoritative operational records already implemented in earlier modules.

The implementation intentionally does **not** create a duplicate search-index table. Results are read directly from the current customer, loan, collateral, loan-payment and remote-payment records, so newly created records are searchable immediately without synchronization jobs.

## Search coverage

The global search supports the required roadmap identifiers:

- Customer name
- Phone
- Alternative phone
- NIN
- Customer number
- Loan number
- Collateral number/code
- Loan-payment receipt number
- Loan-payment reference

It also searches remote-payment transaction references because they are permanent payment references already used by the remote-payment workflow.

## Source permissions

Search does not grant access to a module by itself. A source is queried only when the authenticated user already has the permission required to open that result's existing destination page.

- **Customers** require `customers.view`.
- **Loans** require `loans.view`.
- **Loan-payment receipts and posted payment references** require `loans.view`, matching the existing receipt route permission.
- **Collateral** requires `collateral.view`.
- **Remote-payment transaction references** require `payments.remote.verify`, matching the existing verification/detail page permission.

This prevents global search from becoming a side channel for unauthorized records.

## Branch isolation

Every search query is restricted to the authenticated user's assigned branches before matching occurs.

- Branch users see only records belonging to branches assigned to them.
- Cross-branch matches are not returned even when the user knows the exact identifier.
- Super Administrator continues to use the existing global branch-access bypass.
- Destination controllers still enforce their own branch and permission checks after navigation.

## Search behavior

- Queries require at least 2 characters before database search begins.
- Input is validated to a maximum of 100 characters.
- Multi-word customer searches split the query into terms so a full-name search can match separate first/middle/last-name columns.
- Exact identifier matches rank ahead of prefix matches and partial matches.
- Results are grouped by record type.
- Each group is capped to a compact result set for immediate navigation.
- Permanent identifiers are displayed beside result titles so similarly named records remain distinguishable.

## Immediate navigation

Results point directly to the existing application pages rather than a duplicate preview record:

- Customer profile
- Loan detail
- Collateral detail
- Loan-payment receipt
- Remote-payment verification/detail

This keeps search navigation consistent with the authorization and business rules already enforced by those modules.

## Top-bar integration

The previously visual-only top-bar search control is now functional.

Desktop:

- Real GET search field in the top bar
- Submits directly to global search
- Retains the current query while on the search page

Mobile:

- Compact search icon opens the global search page

Keyboard:

- **Ctrl + K** on Windows/Linux
- **Command + K** on macOS

The shortcut focuses and selects the top-bar search field when visible. If the desktop field is unavailable, it navigates to the search page.

## Route

New authenticated route:

- `GET /search`
- Route name: `global-search.index`

No public global-search endpoint was added.

## Database changes

None.

Step 23 searches the existing authoritative tables and does not add or rewrite financial or operational data.

## Main files created

- `app/Http/Controllers/GlobalSearchController.php`
- `app/Services/GlobalSearchService.php`
- `resources/views/global-search/index.blade.php`
- `routes/global-search.php`
- `tests/Feature/GlobalSearchTest.php`

## Main files modified

- `resources/views/layouts/partials/topbar.blade.php`
- `public/assets/microfinance/app.js`
- `routes/web.php`

## Automated tests

Step 23 adds 5 feature tests covering:

1. Every roadmap search identifier, plus remote-payment references, with direct existing-record navigation.
2. Branch isolation and Super Administrator all-branch search.
3. Module-permission isolation so search cannot expose loans, collateral or payments to a customer-only role.
4. Remote-payment references requiring verification permission.
5. Authentication, minimum query length, top-bar integration and Ctrl/Command + K behavior.

## Verification

GitHub Actions Foundation CI on pull request #35:

- Fresh migrations: PASS
- All seeders: PASS
- Full Laravel test suite: **165 passed**
- Assertions: **1,760**
- Existing Step 1–22 regression tests: PASS
- Step 23 feature tests: **5 passed**

## Remaining Step 23 work

None.

## Next roadmap module

**Step 24 — Final Documents and Exports**.
