# Co-Applicant Consent API & AutoDecision (AutoBRE) Trigger (Phase 2)
---
## CRED-6180 — 2026-05-07
### Overview
Introduced the Co-applicant Consent API (Phase 2) and merged it with the existing Applicant Consent API. Updated the AutoDecision (AutoBRE) generation and Bureau pull logic to enforce a strict "wait-and-run" dependency: automated jobs are only queued when *both* the mandatory application data points are present and the respective applicant/co-applicant consent is successfully logged.
---
### Business Rules
* **Consent & Data Requirement (Wait-and-Run)**: The Bureau pull and AutoDecision job must never trigger unless two conditions are met:
1. All 20 mandatory data points to run BRE are received in the database.
2. Customer consent is officially received for the applicant being processed:
- Primary: `is_consent == 1` and/or `consent_logs` file (`applicant_type = 1`)
- Co-applicant: `is_co_app_consent == 1` and/or `co_app_consent_logs` file (`applicant_type = 2`)
*(If one is received without the other, the system waits. Once both are available for that applicant, the system may fetch Bureau and run BRE for that applicant.)*
* **Per-applicant Bureau gating**: Primary and co-applicant bureau pulls are evaluated independently. A missing co-applicant consent must not block the primary applicant's pull, and vice versa. Neither soft nor hard (Equifax) bureau pull may run for an applicant until that applicant's consent is received.
* **Co-Applicant Trigger Point**: A consent link SMS (using the exact same template as the primary applicant) is automatically sent as soon as the Co-Applicant's communication number is added to the application, regardless of whether they are added for income contribution or just as a signing guarantor.
* **Compulsory Location Tracking**: Capturing geographical location (Latitude and Longitude) is strictly mandatory when consent is received through the customer link for *both* the applicant and co-applicant, for both "I Agree" and "I Deny" actions.
* **Consent Log Generation**: Upon receiving co-applicant consent, a consent log document must be generated in the exact same format as the primary applicant and saved to the application file.
* **Mobile Number Re-Trigger**: If the applicant's or co-applicant's mobile number is updated before consent is received, the system must deactivate the old consent link and re-trigger a new consent link to the newly added mobile number.
---
### Logic Added
#### Application Edit Controller
`ConsumerApplicationController::getEditPostConsumerApplication()`
* **AutoBRE Gate Check**: Added an explicit check for both primary applicant (`is_consent == 1`) and co-applicant (`is_co_app_consent == 1`) consent. AutoBRE evaluation takes place for each applicant type independently. This ensures the system skips checking the 20 data points and dispatching the job for an applicant if their respective consent is missing.
* **Fallback Validation**: Restored three field fallback validation checks (`employee_status`, `monthly_income`, `power_savings`) to ensure they are verified from the request payload if missing in the database.
* **Mobile Number Change Detection**: Detects if `mobile_number` or `co_applicant_mobile_number` is updated. If the corresponding consent is absent, a fresh consent link is dynamically generated and dispatched to the new number.
#### Bureau Pull — Soft & Hard
`ConsumerApplicationController::generateSoftBureauReport($id, $type, $applicantType, $runBre)`
* **Unified consent gate (primary + co-applicant)**: Before any Experian soft pull, consent is required for the requested `$applicantType`:
- Type `1`: `consent_logs` file **or** `consumer_application_element.is_consent == 1`
- Type `2`: `co_app_consent_logs` file **or** `consumer_application_element.is_co_app_consent == 1`
* **Mconnect exception preserved**: Consent is treated as received if either the PDF exists or the DB flag is set (mconnect may set `is_consent` / `is_co_app_consent` before the consent document job finishes).
* **Failure responses**:
- Primary: `"Please get applicant consent."`
- Co-applicant: `"Please get Co-Applicant consent."`
* **AutoDecision integration**: `AutoDecision` calls `generateSoftBureauReport($id, 'autoBRE', 2, false)` for co-applicant before the primary pull. Co-applicant consent is enforced at this entry point; the job returns `FAIL` without calling Experian when consent is absent.
* **Equifax fallback (`autoBRE`)**: When soft pull fails, hard pull via `generateEqifaxReport()` only proceeds if consent was already received for that applicant type (reuses the same `$consentReceived` check). Previously, the soft-fail path only validated `is_consent`, which incorrectly allowed co-applicant hard pull without co-app consent.
`ConsumerApplicationController::generateEqifaxReport()`
* **Existing behaviour (unchanged)**: Hard pull already requires the consent log file (`consent_logs` or `co_app_consent_logs`) for the given `applicant_type`.
#### Post Approval Controller
`PostApprovalController::getKYCDone()`
* **Hashids Collision Resolution**: The esign link generated in `ConsumerDocument` encodes both the `application_id` and a Unix timestamp (`time()`). To prevent `ConsentController::addConstantDocument()` from incorrectly interpreting the timestamp as a mobile number hash, a clean `$consent_hashed_id` (encoding only the application ID) is specifically generated and passed to the frontend for consent submission via the esign flow.
#### Consent Controller
`ConsentController::sendConsentMessage()`
* **Link Expiry Hash**: A secure hash of the applicant's current mobile number is dynamically encoded into the `Hashids` payload of the generated consent link.
`ConsentController::addConstantDocument()`
* **Applicant & Co-Applicant AutoBRE**: Upon successful consent submission (`$status != 'deny'`), checks for both `$applicant_type == 1` and `$applicant_type == 2`. It dynamically instantiates `autoBRE`, queries `MerchantOffers`, and executes `checkDataPoints`. If valid, the `EventAutoDecision` job is dispatched into the queue specifically for the respective applicant type.
* **Consent Logging**: Sets the corresponding consent flag (`is_consent` or `is_co_app_consent`) and uploads the corresponding log document (`consent_logs` or `co_app_consent_logs`).
* **Mobile Number Validation**: Extracts the mobile number hash embedded in the `Hashids` link and strictly validates it against the database. If they mismatch (meaning the number was changed after link generation), submission is aborted with an expiry message. (Older links lacking the hash process gracefully for backward compatibility).
* **Geolocation Validation**: Ensures `latitude` and `longitude` are present in the HTTP request payload. Missing coordinates result in a rejected submission. Valid coordinates are passed into the `$data` array and stamped onto the generated consent PDF.
#### Frontend / Views
`resources/views/front/consent_page.blade.php`
* **Geolocation API (Standard Flow)**: Triggers the HTML5 Geolocation API to request location access on page load. If the user denies access or the location cannot be fetched, form submission is blocked with a mandatory alert prompt.
`resources/views/admin/_consent_partial.blade.php`, `resources/views/admin/digio_vkyc_integration.blade.php`, `resources/views/admin/karza_vkyc_integration.blade.php`
* **Geolocation API (Esign Flow)**: Enforces the exact same mandatory HTML5 Geolocation tracking in the esign consent flow. The location prompt triggers on page load, and the AJAX submission payload securely transmits `latitude` and `longitude`.
---
### Impact — Files Changed / Added
| File | Type | Change |
| --- | --- | --- |
| `app/Http/Controllers/Admin/ConsumerApplicationController.php` | Modified | AutoBRE consent gate on edit (checks both `is_consent == 1` and `is_co_app_consent == 1` for triggering individual jobs), fallback validations, mobile number re-trigger logic, and **per-applicant bureau consent gate** in `generateSoftBureauReport()` for primary (`is_consent` / `consent_logs`) and co-applicant (`is_co_app_consent` / `co_app_consent_logs`). |
| `app/Http/Controllers/ConsentController.php` | Modified | Added AutoDecision trigger (`EventAutoDecision`) on both primary and co-applicant consent, `Hashids` mobile validation for link expiry, and mandatory `latitude`/`longitude` payload validation. |
| `app/Http/Controllers/PostApprovalController.php` | Modified | Added `$consent_hashed_id` payload to prevent Hashid collision with link expiry validation during esign consent submission. |
| `resources/views/front/consent_page.blade.php` | Modified | Added HTML5 Geolocation API requirement; explicitly blocks form submission if location access is denied. |
| `resources/views/admin/_consent_partial.blade.php`
`digio_vkyc_integration.blade.php`
`karza_vkyc_integration.blade.php` | Modified | Integrated HTML5 Geolocation API into the esign flow AJAX payload, enforcing mandatory location tracking on page load. |
---
### Bureau consent flow (summary)
```text
generateSoftBureauReport(id, type, applicantType)
│
├─ applicantType 1 → require consent_logs OR is_consent == 1
├─ applicantType 2 → require co_app_consent_logs OR is_co_app_consent == 1
│
├─ consent missing → return FAIL (no Experian call)
└─ consent OK → soft pull → on FAIL + autoBRE → Equifax only if consent still OK
```