1. Stage 11 Objective
Stage 11 is the platform’s final automated gate before the account opening form (AOF) is generated. When the customer taps “Review & Proceed”, the backend executes 7 checks in strict sequence. The customer sees a loading screen while these checks run — there is no polling or partial-result display.
Hard Failure Rule
A single hard failure at any check immediately terminates the journey. The customer is shown a drop screen with the relevant drop code. There is no retry or skip for hard-stop checks.
- 7 checks run in a defined order (some sequential, some parallel).
- Each check produces a pass/fail/skip result stored in
final_validations.
- The STP/Non-STP decision is made at Check 6 — this evaluates all name-match scores, face-match, income proof type, C-SAFE, PEP, and AML flags.
- The customer remains on a loading screen for the entire duration; this is customer-triggered (not background/async).
- On success, the lead advances to
FINAL_VALIDATION state with the STP decision recorded.
2. Preconditions
| Condition | Detail | Failure Behaviour |
lead.state = DETAILS_DONE |
All prior stages (1–10) must be completed. Lead must be in the DETAILS_DONE state. |
Return 400 with message “Lead not in valid state for final validation.” |
| All name-match scores present |
aadhaar_name_match, bank_name_match, and face_match scores must already be computed and stored in the database. |
Return 400 with message “Missing prerequisite match scores.” |
| Customer taps “Review & Proceed” |
This is a customer-initiated action. The frontend sends a POST request to the final validation endpoint. |
N/A — endpoint is not called until the customer triggers it. |
3. The 7 Checks
Critical: Each check is documented below with its failure type.
“Hard Stop” means the journey is terminated and the lead is dropped. “CS Journey” means the lead is routed to the Customer Service assisted journey for manual completion.
| # |
Check Name |
What It Does |
Vendor / Source |
Failure Type |
Failure Action |
| 1 |
PAN Validity Re-check |
Re-verifies PAN status with NSDL/Protean. Ensures PAN is still active and not deactivated, surrendered, or flagged since Stage 2. |
NSDL / Protean |
Hard Stop |
Drop lead — DROP_FINAL_PAN |
| 2 |
PAN Name Re-verify |
Re-checks the name associated with the PAN. Only runs if 5+ days have elapsed since the original PAN verification at Stage 2. Detects name changes at NSDL after initial check. |
NSDL / Protean |
Hard Stop |
Drop lead — DROP_FINAL_PAN_CHANGED |
| 3 |
Negative List Re-check |
Re-checks mobile number, PAN, and Aadhaar against the internal negative/blocked list. Catches entries added after initial Stage 2 check. |
Internal Negative List API |
Hard Stop |
Drop lead — DROP_FINAL_NEGLIST |
| 4 |
Dedupe Re-check |
Re-checks PAN, email, mobile, bank account, and Aadhaar for duplicate accounts. Catches duplicates created after initial Stage 2 dedupe. |
Internal Dedupe API |
Hard Stop |
Drop lead — DROP_FINAL_DEDUPE |
| 5 |
Data Completeness |
Validates that all mandatory fields across all stages are present and non-null. Checks personal details, bank details, nominee, income proof, signature, and address. |
Internal validation |
CS Journey or Hard Stop |
If recoverable: route to CS Journey. If critical fields missing: hard stop — BE_FINAL_INCOMPLETE |
| 6 |
STP / Non-STP Decision |
Evaluates all match scores, income proof type, C-SAFE result, PEP declaration, and AML flags to produce the STP or NON_STP decision. Always produces a result — never fails. |
Internal — StpDecisionService.Evaluate() |
N/A |
Always produces STP or NON_STP with reason codes. |
| 7 |
AOF Pre-check |
Validates all prerequisites for PDF generation of the Account Opening Form: photo present, signature present, address proof, PAN copy, income proof document. Ensures the AOF can be assembled. |
Internal validation |
CS Journey |
Route to CS Journey — CS_AOF_FAIL |
4. Check Execution Order
The 7 checks do not all run sequentially. The execution order is optimized for fail-fast and parallelism where checks are independent.
Execution Pipeline
1
PAN Validity Re-check — Runs first. If PAN is invalid, the journey stops immediately. No other checks are executed.
2
PAN Name Re-verify — Runs only if Check 1 passes. Additionally, this check is skipped entirely if fewer than 5 days have elapsed since the original PAN verification. If the name has changed, the journey stops.
3
Negative List Re-check — Runs in parallel with Check 4. Checks mobile + PAN + Aadhaar against the negative list.
4
Dedupe Re-check — Runs in parallel with Check 3. Checks PAN + email + mobile + bank account + Aadhaar for duplicates.
5
Data Completeness — Validates all mandatory fields. If incomplete and recoverable, routes to CS Journey. If critical fields are missing, hard stop.
6
STP / Non-STP Decision — Evaluates all 8 flags via StpDecisionService.Evaluate(). Always produces a result; never blocks the pipeline.
7
AOF Pre-check — Validates PDF generation prerequisites. On failure, routes to CS Journey rather than dropping the lead.
Parallel Execution Note
Checks 3 and 4 execute concurrently. Both must pass before proceeding to Check 5. If either fails, the journey stops with the corresponding drop code. If both fail, the first failure encountered (by response order) is used as the drop reason.
5. STP Decision Logic
Check 6 uses StpDecisionService.Evaluate() which inspects 8 independent flags. Every flag must evaluate to STP for the lead to qualify for straight-through processing. A single NON_STP flag routes the lead to operations review.
Rule: ALL flags must be STP for straight-through processing.
A single NON_STP flag on any dimension routes the entire lead to operations/manual review. There is no partial STP.
| Flag |
STP Condition |
NON_STP Condition |
Special Rules |
aadhaar_name_match |
Score ≥ 70 |
Score 1–69 |
Score = 0 means the lead was already dropped at Stage 5 (Aadhaar verification). This value should never be seen at Stage 11. |
bank_name_match |
Score ≥ 70 |
Score < 70 |
— |
face_match |
Score ≥ 70 |
Score < 70 |
— |
income_proof |
Auto-fetched (e.g., ITR via DigiLocker) |
Always NON_STP if manual upload |
Manual upload of income proof always triggers NON_STP because the document requires human verification. |
csafe_result |
CLEAR |
FLAGGED = NON_STP always |
If C-SAFE returns FLAGGED, the lead is always NON_STP and is escalated to the compliance team for review. |
pep_declared |
No (customer declares they are not a PEP) |
Yes = NON_STP always |
If the customer declares PEP status (Yes), the lead is always NON_STP and is escalated to the compliance team. |
aml_pep_mismatch |
No mismatch (C-SAFE PEP flag agrees with customer declaration) |
Mismatch = NON_STP |
If C-SAFE flags the customer as PEP but the customer declared pep = No, this is a mismatch. Results in NON_STP + compliance escalation. This is a serious discrepancy. |
esign_mismatch |
No mismatch detected |
Mismatch detected |
Post-eSign check: verifies that the name/details used during eSign match the lead data. Mismatch triggers NON_STP. |
Compliance Escalation Flags
Three conditions trigger mandatory compliance team escalation in addition to NON_STP routing: (1) csafe_result = FLAGGED, (2) pep_declared = Yes, (3) aml_pep_mismatch = true. These are logged separately and generate compliance workflow tickets.
STP Decision Pseudocode
function StpDecisionService.Evaluate(leadId):
flags = []
// 1. Aadhaar name match
if aadhaar_name_match >= 70: flags.push(STP)
else: flags.push(NON_STP, reason="AADHAAR_NAME_LOW")
// 2. Bank name match
if bank_name_match >= 70: flags.push(STP)
else: flags.push(NON_STP, reason="BANK_NAME_LOW")
// 3. Face match
if face_match >= 70: flags.push(STP)
else: flags.push(NON_STP, reason="FACE_MATCH_LOW")
// 4. Income proof
if income_proof.source == AUTO_FETCH: flags.push(STP)
else: flags.push(NON_STP, reason="MANUAL_INCOME_PROOF")
// 5. C-SAFE
if csafe_result == CLEAR: flags.push(STP)
else:
flags.push(NON_STP, reason="CSAFE_FLAGGED")
escalateToCompliance(leadId, "CSAFE_FLAGGED")
// 6. PEP declared
if pep_declared == false: flags.push(STP)
else:
flags.push(NON_STP, reason="PEP_DECLARED")
escalateToCompliance(leadId, "PEP_DECLARED")
// 7. AML/PEP mismatch
if csafe_pep_flag == customer_pep_declaration: flags.push(STP)
else:
flags.push(NON_STP, reason="AML_PEP_MISMATCH")
escalateToCompliance(leadId, "AML_PEP_MISMATCH")
// 8. eSign mismatch
if esign_name_matches_lead: flags.push(STP)
else: flags.push(NON_STP, reason="ESIGN_MISMATCH")
// Final decision
if ALL flags == STP:
return { decision: "STP", reason_codes: [] }
else:
return { decision: "NON_STP", reason_codes: [all NON_STP reasons] }
6. Backend Validations
| Scenario |
Check # |
Action |
Code |
Customer Impact |
| PAN re-check fails (inactive / deactivated / surrendered) |
1 |
Drop lead immediately |
DROP_FINAL_PAN |
Journey terminated. Drop screen shown. |
| PAN name changed since Stage 2 verification |
2 |
Drop lead immediately |
DROP_FINAL_PAN_CHANGED |
Journey terminated. Drop screen shown with message indicating PAN name discrepancy. |
| Negative list match found |
3 |
Drop lead immediately |
DROP_FINAL_NEGLIST |
Journey terminated. Generic drop screen (no details about negative list revealed). |
| Dedupe match found |
4 |
Drop lead immediately |
DROP_FINAL_DEDUPE |
Journey terminated. Drop screen indicating existing account found. |
| Data incomplete (recoverable) |
5 |
Route to CS Journey |
BE_FINAL_INCOMPLETE |
Customer is routed to CS-assisted journey for manual completion of missing fields. |
| Data incomplete (critical / non-recoverable) |
5 |
Hard stop |
BE_FINAL_INCOMPLETE |
Journey terminated. This should be rare as prior stages enforce mandatory fields. |
| NSDL / Protean API unavailable |
1, 2 |
Route to CS Journey |
CS_NSDL_DOWN |
Customer is routed to CS-assisted journey. PAN validation deferred to manual process. |
| Negative List API down |
3 |
Proceed with SKIPPED flag |
— |
Journey continues. Check result recorded as SKIPPED. Ops team alerted for post-facto review. |
| Dedupe API down |
4 |
Proceed with SKIPPED flag |
— |
Journey continues. Check result recorded as SKIPPED. Ops team alerted for post-facto review. |
API Downtime Strategy
NSDL downtime is treated more seriously (CS Journey redirect) because PAN validity is a regulatory requirement. Negative list and dedupe API downtimes allow the journey to proceed with a SKIPPED flag because these are internal systems that can be retroactively checked by the ops team.
7. Existing Stored Procedure Mapping
The following stored procedures in the existing system handle the logic that Stage 11 encapsulates. These must be analysed for business rules during migration.
| Stored Procedure |
Purpose |
Maps To |
USP_CHECK_ALL_VALIDATIONS_SJET SP |
Master validation orchestrator. Runs all final checks including PAN re-verify, negative list, dedupe, and data completeness in sequence. |
Checks 1–5 (overall orchestration) |
USP_AUTO_APPROVE_PROOF_SJET SP |
Evaluates whether income proof and other documents can be auto-approved or require manual review. |
Check 6 (income_proof flag in STP decision) |
USP_JOINT_STP_NONSTP_LOGIC_SJET SP |
STP/Non-STP logic for joint account applications. Contains the multi-applicant scoring logic. |
Check 6 (joint account variant of STP logic) |
USP_STP_NONSTP_SUPERAPP_SJET SP |
STP/Non-STP logic for SuperApp channel. Contains channel-specific scoring thresholds and rules. |
Check 6 (SuperApp channel variant) |
USP_ALLOW_ESIGN_SJET SP |
Determines if the lead is eligible for eSign based on validation results. Pre-eSign eligibility gate. |
Check 7 (AOF pre-check / eSign readiness) |
USP_INSERT_UPDATE_STP_FLAG_SJET SP |
Persists the STP/Non-STP decision and all associated reason codes to the database. |
Check 6 result persistence |
8. Error / Drop Codes
| Code |
Type |
Description |
Check # |
Customer Message |
DROP_FINAL_PAN |
DROP |
PAN is no longer valid at NSDL. PAN may have been deactivated, surrendered, or flagged since Stage 2. |
1 |
“We are unable to proceed with your application. Please contact support.” |
DROP_FINAL_PAN_CHANGED |
DROP |
PAN-associated name has changed at NSDL since the original verification. Name mismatch with application data. |
2 |
“Your PAN details have changed. Please re-apply with updated information.” |
DROP_FINAL_NEGLIST |
DROP |
Mobile, PAN, or Aadhaar found in the negative/blocked list. |
3 |
“We are unable to proceed with your application at this time.” |
DROP_FINAL_DEDUPE |
DROP |
Duplicate account detected on PAN, email, mobile, bank account, or Aadhaar. |
4 |
“An existing account was found matching your details. Please contact support.” |
BE_FINAL_INCOMPLETE |
ERROR |
One or more mandatory fields are missing or invalid. May be recoverable (CS Journey) or critical (hard stop). |
5 |
CS Journey: “We need a few more details. Our team will assist you.” Hard stop: “Unable to complete your application.” |
CS_AOF_FAIL |
CS ROUTE |
AOF PDF generation prerequisites not met. Missing photo, signature, or document required for the account opening form. |
7 |
“We need a few more details to complete your form. Our team will assist you.” |
CS_NSDL_DOWN |
CS ROUTE |
NSDL/Protean API is unavailable. PAN verification cannot be completed electronically. |
1, 2 |
“We are experiencing a temporary issue. Our team will complete your verification shortly.” |
9. Exit State
On successful completion of all 7 checks, the following state is written:
| Field |
Value |
Storage |
lead.state |
FINAL_VALIDATION |
leads table |
stp_decision |
STP or NON_STP |
leads table |
stp_reason_codes |
JSON array of reason codes (empty for STP, populated for NON_STP) |
leads table |
final_validation_timestamp |
UTC timestamp of when all checks completed |
leads table |
| All 7 check results |
Individual pass/fail/skip result for each check, with vendor response payloads |
final_validations table |
Successful Exit
After Stage 11, the lead is ready for AOF generation and eSign. The STP decision determines whether the account is auto-approved or routed to the ops review queue.
Exit State Pseudocode
// After all 7 checks pass
UPDATE leads SET
state = 'FINAL_VALIDATION',
stp_decision = @stpDecision, -- 'STP' or 'NON_STP'
stp_reason_codes = @stpReasonCodesJson, -- '[]' or '["AADHAAR_NAME_LOW","MANUAL_INCOME_PROOF"]'
final_validation_ts = GETUTCDATE(),
updated_at = GETUTCDATE()
WHERE lead_id = @leadId;
INSERT INTO final_validations (lead_id, check_number, check_name, result, vendor_response, created_at)
VALUES
(@leadId, 1, 'PAN_VALIDITY', @check1Result, @check1Response, GETUTCDATE()),
(@leadId, 2, 'PAN_NAME_VERIFY', @check2Result, @check2Response, GETUTCDATE()),
(@leadId, 3, 'NEGATIVE_LIST', @check3Result, @check3Response, GETUTCDATE()),
(@leadId, 4, 'DEDUPE', @check4Result, @check4Response, GETUTCDATE()),
(@leadId, 5, 'DATA_COMPLETENESS',@check5Result, @check5Response, GETUTCDATE()),
(@leadId, 6, 'STP_DECISION', @check6Result, @check6Response, GETUTCDATE()),
(@leadId, 7, 'AOF_PRECHECK', @check7Result, @check7Response, GETUTCDATE());
10. Vendor & Integration Calls
| Vendor / System |
Used In Check |
Purpose |
Fallback |
| NSDL / Protean |
Check 1, Check 2 |
PAN validity verification and PAN name lookup. Primary vendor for PAN services. |
UTI (fallback vendor for PAN verification) |
| UTI (fallback) |
Check 1, Check 2 |
Fallback PAN verification vendor if NSDL/Protean is unavailable. |
Route to CS Journey (CS_NSDL_DOWN) |
| Internal Negative List API |
Check 3 |
Checks mobile, PAN, and Aadhaar against the internal negative/blocked list database. |
Proceed with SKIPPED flag; ops team alerted |
| Internal Dedupe API |
Check 4 |
Checks PAN, email, mobile, bank account, and Aadhaar for existing duplicate accounts. |
Proceed with SKIPPED flag; ops team alerted |
| CleverTap |
Post-validation |
Event tracking: final validation outcome, STP decision, drop events. Used for analytics and customer engagement. |
Fire-and-forget; failure does not block journey |
| Zoho |
Post-validation |
CRM update: lead status update, STP/Non-STP flag, compliance escalation tickets if applicable. |
Fire-and-forget; failure does not block journey |
| CDP |
Post-validation |
Customer Data Platform event push: final validation event with all check results and STP decision. |
Fire-and-forget; failure does not block journey |
| Datalake |
Post-validation |
Raw event and payload logging for audit trail, analytics, and compliance reporting. |
Fire-and-forget; failure does not block journey |
11. Database Tables
| Table |
Access |
Purpose in Stage 11 |
final_validations |
WRITE NEW |
Stores results of all 7 checks for each lead. Each check is a separate row with check number, result (PASS/FAIL/SKIP), vendor response payload, and timestamp. |
leads |
READ WRITE |
Read: Current state, lead data for validation. Write: state, stp_decision, stp_reason_codes, final_validation_timestamp. |
pan_verifications |
READ WRITE |
Read: Original PAN verification timestamp (to determine if 5+ days elapsed for Check 2). Write: Re-verification result from Check 1/2. |
aadhaar_verifications |
READ |
Read Aadhaar number for negative list check (Check 3) and dedupe check (Check 4). Read aadhaar_name_match score for STP decision (Check 6). |
bank_accounts |
READ |
Read bank account details for dedupe check (Check 4). Read bank_name_match score for STP decision (Check 6). |
liveness_verifications |
READ |
Read face_match score for STP decision (Check 6). |
signature_verifications |
READ |
Read signature presence for AOF pre-check (Check 7). Verify signature document exists. |
personal_details |
READ |
Read all personal details for data completeness check (Check 5). Read PEP declaration for STP decision (Check 6). |
csafe_checks |
READ |
Read C-SAFE result and C-SAFE PEP flag for STP decision (Check 6). Used in AML/PEP mismatch detection. |
negative_list_entries |
READ WRITE |
Read: Check if mobile/PAN/Aadhaar exists in negative list (Check 3). Write: Log the re-check result and timestamp. |
12. Implementation Notes
StpDecisionService.Evaluate()
Check 6 uses StpDecisionService.Evaluate() which inspects exactly 8 flags: aadhaar_name_match, bank_name_match, face_match, income_proof, csafe_result, pep_declared, aml_pep_mismatch, and esign_mismatch. All 8 must evaluate to STP for straight-through processing.
PAN Re-verify Elapsed Time
Check 2 (PAN Name Re-verify) only executes if 5 or more days have elapsed since the original PAN verification at Stage 2. This threshold is configurable via system configuration (e.g., config.pan_reverify_days_threshold). If fewer than 5 days have elapsed, Check 2 is recorded as SKIPPED with reason WITHIN_THRESHOLD and the pipeline proceeds directly to Checks 3+4.
Loading Screen Duration
The customer waits on a loading screen while all 7 checks execute. Typical execution time is 3–8 seconds depending on vendor response times. Implement a client-side timeout of 30 seconds. If the backend does not respond within 30 seconds, the frontend should display a “Please wait” message and retry once.
Post-Validation Event Dispatch
After all checks complete and the state is written, fire analytics events to CleverTap, Zoho, CDP, and Datalake asynchronously. These are fire-and-forget — failures do not block the customer journey or roll back the validation result.