EKYC 3.0 — Stage 10: Income Proof Upload (F&O Only)

Backend-Only Developer Implementation Guide • Manual Document Upload + OCR + Verifier Pipeline
Stage ID: STAGE_10_INCOME_PROOF Trigger: F&O customer without Account Aggregator income BRD Section: 17 — Stage 10 Version: 1.0

Table of Contents

  1. Stage 10 Objective
  2. Preconditions
  3. Accepted Documents
  4. Upload Specifications
  5. Backend Flow
  6. Backend Validations
  7. Existing Stored Procedure Mapping
  8. Error / Drop Codes
  9. Exit State
  10. Vendor & Integration Calls
  11. Database Tables (New Backend)
  12. Implementation Notes

1. Stage 10 Objective

F&O (Futures & Options) customers who could not obtain income verification via the Account Aggregator flow are routed to this stage to upload income proof documents manually. The uploaded document is stored, OCR-extracted for the customer name, and queued for verifier review.

Critical: ALL Manual Uploads = NON_STP Every document uploaded through this stage results in stp_income_flag = NON_STP. There is no income threshold check and no automated approval. The verifier reviews every upload for completeness and authenticity. The OCR name match score is logged for verifier context only — it does NOT influence the STP decision.
Stage 10 is Conditional This stage only applies to F&O customers whose income could not be verified through Account Aggregator. Non-F&O customers and F&O customers with successful Account Aggregator income verification skip this stage entirely.

2. Preconditions

All conditions below must be true for Stage 10 to be presented:

Condition Required Value Notes
lead.state DETAILS_DONE Customer has completed all prior detail stages
stage_10_required true Set by journey orchestrator when income proof is needed
fno_selected true Customer has opted for F&O trading segment
income_proof_source MANUAL_UPLOAD_PENDING Account Aggregator did not return income data

Skip Conditions

Stage 10 is SKIPPED if any of the following are true:

Backend Check The backend must validate preconditions before accepting any upload request. If fno_selected = false or income_proof_source = ACCOUNT_AGGREGATOR, return HTTP 400 with error code FE_INCOME_001.

3. Accepted Documents

The following document types are accepted as income proof for F&O customers:

Document Type Period / Validity Max Files Notes
Bank Statement Last 6 months 1 Must cover a continuous 6-month period
Salary Slip Last 3 months 3 Up to 3 files allowed (one per month); each slip is a separate upload
ITR Acknowledgement Last 1 year 1 Income Tax Return acknowledgement for the most recent assessment year
Form 16 Last Financial Year 1 Issued by employer for the immediately preceding financial year
One Document Type Per Journey The customer selects one document type and uploads the corresponding file(s). They do not need to upload multiple document types. If the selected document type is Salary Slip, up to 3 files can be uploaded; all other types accept exactly 1 file.

4. Upload Specifications

Parameter Specification
Accepted Formats PDF, JPG, PNG
Maximum File Size 5 MB per file
Max Files — Salary Slip 3 files (one per month)
Max Files — All Other Types 1 file
Password-Protected PDFs Rejected — backend must detect and block; return error code FE_INCOME_003
Wrong Document Type Stored but flagged — if OCR detects a mismatch between selected type and actual content, the file is stored with a flag for verifier review
File Size Validation File size must be validated on the backend regardless of any frontend checks. Files exceeding 5 MB must be rejected with error code FE_INCOME_002 before any storage or OCR processing occurs.

5. Backend Flow

1
Select Document Type
Customer selects one of the accepted document types (Bank Statement, Salary Slip, ITR Acknowledgement, or Form 16). Backend validates the selected type against the allowed list and stores the selection in income_proof_document_type.
WRITE document_uploads.document_type
2
Upload File
Customer uploads file(s). Backend validates format (PDF/JPG/PNG), file size (≤ 5 MB), checks for password-protected PDFs (reject), and enforces the max file count per document type. If Salary Slip, up to 3 files are accepted sequentially.
WRITE document_uploads — one row per file
3
Claude Vision OCR — Extract Name
Each uploaded file is sent to the OCR service (Claude Vision / AiNXT) to extract the customer name from the document. The extracted name is stored against the upload record. If OCR fails, the raw file is stored and flagged for manual verifier review.
READ uploaded file → WRITE document_uploads.ocr_extracted_name
4
Name Match Score — Logged Only
The OCR-extracted name is compared against the customer's registered name (personal_details.full_name) to produce a match score. This score is logged in income_proof_name_match_score for verifier context only. It does NOT affect the STP decision — all manual uploads are always NON_STP.
READ personal_details.full_nameWRITE document_uploads.name_match_score
5
Store Document Encrypted
The uploaded file is stored encrypted on the configured file storage drive. The S3/storage key is recorded in income_proof_s3_keys (array, one entry per file). Encryption is mandatory — plain file storage is not permitted.
WRITE document_uploads.storage_key, document_uploads.encrypted = true
6
Mark Stage Complete
Set stage_10_complete = true. Set stp_income_flag = NON_STP. Log the event in journey_stage_events. Fire downstream events to CleverTap, Zoho, and Datalake.
WRITE journey_stage_events, downstream_events
NON_STP Always Step 4 computes a name match score but it is never used for STP determination. Regardless of the score (even 100% match), stp_income_flag is always set to NON_STP. The score is purely informational for the verifier.

6. Backend Validations

Scenario Detection Action Error Code
OCR Failure OCR service returns error or empty extraction Store raw file as-is. Flag for verifier manual review. Do NOT block the upload.
Password-Protected PDF Attempt to read/parse PDF fails with password error Block upload. Return error immediately. Do not store the file. FE_INCOME_003
Max Upload Attempts Exceeded (3) Customer has already uploaded 3 files for Salary Slip or re-attempted 3 times for other types Store the raw file. Flag for verifier review. No further retries allowed. MAX_UPLOADS_REACHED
File Storage Failure Storage service returns error on write Retry once. If retry also fails, return error and log for ops investigation. FE_INCOME_005
Invalid File Format File MIME type is not PDF, JPG, or PNG Reject upload immediately FE_INCOME_002
File Size Exceeded File size > 5 MB Reject upload immediately FE_INCOME_002
Graceful Degradation for OCR OCR failures must never block the customer journey. If OCR fails, the document is stored and the verifier will manually review. The name_match_score field is left null when OCR fails.

7. Existing Stored Procedure Mapping

The following stored procedures exist in the legacy system and must be considered during migration. The new backend may call, wrap, or replace these as appropriate.

Income Proof SPs

Stored Procedure Purpose Migration Action
USP_INSERT_INCOMEPROOFTYPE_SJET Inserts the selected income proof document type for the customer EXISTING Map to document_uploads.document_type insert
USP_CHECKUPLOADEDPROOF_SJET Checks whether the customer has already uploaded an income proof document EXISTING Replace with query on document_uploads
USP_INSERT_UPDATE_INCOMEPROOFMAINPDF_DETAILS_SJET Inserts or updates the main income proof PDF details (file path, metadata) EXISTING Map to document_uploads insert with storage key
USP_GET_CLIENT_INCOMEPROOF_SJET Retrieves income proof details for a given client (used by verifier portal) EXISTING Replace with query on document_uploads
USP_VALIDATE_ONEMONEYDATA_SJET Validates data received from OneMoney (Account Aggregator) EXISTING Not directly used in Stage 10 manual flow; relevant for AA path

OneMoney (Account Aggregator) SPs

These 6 SPs handle the Account Aggregator flow. They are not called in Stage 10 (manual upload) but are listed for completeness since the income proof module spans both paths:

Stored Procedure Purpose
USP_ONEMONEY_CONSENT_INSERT Records AA consent request
USP_ONEMONEY_CONSENT_STATUS_UPDATE Updates consent approval/rejection status
USP_ONEMONEY_FI_REQUEST_INSERT Logs financial information fetch request to AA
USP_ONEMONEY_FI_RESPONSE_INSERT Stores financial information response from AA
USP_ONEMONEY_SESSION_INSERT Creates AA session record
USP_ONEMONEY_SESSION_UPDATE Updates AA session status

Legacy Tables

The following legacy tables are referenced by the stored procedures above:

Migration Note The new backend should use the new document_uploads table as the primary store. Legacy SPs may still be called in parallel during the migration window for data parity. Ensure dual-write logic is in place if legacy systems still read from TBL_CLIENT_PROOFULOAD.

8. Error / Drop Codes

Error Code HTTP Status Scenario User-Facing Message (Suggested)
FE_INCOME_001 400 Precondition not met — customer is not eligible for income proof upload (F&O not selected or AA already completed) Income proof upload is not required for your account.
FE_INCOME_002 400 Invalid file — unsupported format (not PDF/JPG/PNG) or file size exceeds 5 MB Please upload a valid PDF, JPG, or PNG file under 5 MB.
FE_INCOME_003 400 Password-protected PDF detected Password-protected files are not accepted. Please upload an unprotected document.
FE_INCOME_004 400 Invalid document type selected — not in the accepted list Please select a valid document type.
FE_INCOME_005 500 File storage failure after retry — storage service unavailable We are unable to process your upload right now. Please try again shortly.
MAX_UPLOADS_REACHED 400 Maximum upload attempts (3) exhausted for this document type Maximum upload attempts reached. Your documents have been submitted for review.

9. Exit State

After successful completion of Stage 10, the following state is set:

Field Value Notes
lead.state DETAILS_DONE No change — lead state remains DETAILS_DONE
stage_10_complete true Marks this stage as completed
income_proof_document_type BANK_STATEMENT | SALARY_SLIP | ITR_ACKNOWLEDGEMENT | FORM_16 The document type selected by the customer
income_proof_s3_keys Array of storage keys One entry per uploaded file (1 for most types, up to 3 for Salary Slip)
income_proof_name_match_score 0.0 – 1.0 (or null) Verifier context only. Not used for STP decision. Null if OCR failed.
stp_income_flag NON_STP Always NON_STP for all manual uploads regardless of any other factor
stp_income_flag is ALWAYS NON_STP This is a hard rule. The backend must set stp_income_flag = NON_STP unconditionally for every document uploaded through Stage 10. No configuration, threshold, or match score should override this value.
lead.state Does Not Change Unlike most other stages, Stage 10 does not transition the lead state. It remains DETAILS_DONE. The stage_10_complete flag is the signal that this stage is finished.

10. Vendor & Integration Calls

Vendor / Service Purpose When Called Failure Handling
Claude Vision / AiNXT OCR — extracts customer name from uploaded document After file upload (Step 3) Store raw file, flag for verifier review. Do not block journey.
File Storage (Configured Drive) Encrypted file storage for uploaded documents After validation (Step 5) Retry once. If retry fails, return FE_INCOME_005.
CleverTap Event tracking — logs income proof upload event for analytics After stage completion (Step 6) Fire-and-forget. Log failure. Do not block journey.
Zoho CRM update — records income proof submission status After stage completion (Step 6) Fire-and-forget. Log failure. Do not block journey.
Datalake Data pipeline — pushes upload metadata for reporting and analytics After stage completion (Step 6) Fire-and-forget. Log failure. Do not block journey.
OCR is Currently Simulated The Claude Vision / AiNXT OCR integration is currently in simulation mode. During development and initial rollout, OCR responses may be mocked. Ensure the code is structured to swap between simulated and live OCR without code changes (use configuration/feature flags).

11. Database Tables (New Backend)

document_uploads NEW

Primary table for all income proof document uploads in Stage 10.

Column Type Description
id BIGINT (PK) Auto-increment primary key
lead_id BIGINT (FK) Reference to the customer lead
document_type VARCHAR(50) BANK_STATEMENT, SALARY_SLIP, ITR_ACKNOWLEDGEMENT, FORM_16
file_name VARCHAR(255) Original uploaded file name
file_format VARCHAR(10) PDF, JPG, or PNG
file_size_bytes BIGINT File size in bytes
storage_key VARCHAR(500) Encrypted file storage key (S3 / configured drive path)
encrypted BOOLEAN Always true — plain storage not permitted
ocr_extracted_name VARCHAR(255) Name extracted by OCR. Null if OCR failed.
name_match_score DECIMAL(5,4) Match score vs registered name (0.0 to 1.0). Null if OCR failed. Verifier context only.
ocr_status VARCHAR(20) SUCCESS, FAILED, SIMULATED
doc_type_mismatch_flag BOOLEAN True if OCR detected content does not match the selected document type
verifier_review_required BOOLEAN Always true for manual uploads
upload_attempt INT Attempt number (1, 2, or 3)
created_at TIMESTAMP Upload timestamp
updated_at TIMESTAMP Last update timestamp

personal_details EXISTING

Read-only in this stage. Used to fetch the customer's registered name for name match comparison.

Column Usage in Stage 10
lead_id Join key to identify the customer
full_name READ Compared against OCR-extracted name for match scoring

journey_stage_events EXISTING

Logs the stage completion event.

Column Usage in Stage 10
lead_id Customer lead reference
stage WRITE STAGE_10_INCOME_PROOF
status WRITE COMPLETED
metadata WRITE JSON with document_type, file_count, stp_flag, name_match_score
created_at WRITE Event timestamp

downstream_events EXISTING

Queues events for CleverTap, Zoho, and Datalake integration.

Column Usage in Stage 10
lead_id Customer lead reference
event_type WRITE INCOME_PROOF_UPLOADED
target WRITE CLEVERTAP, ZOHO, DATALAKE (one row each)
payload WRITE JSON with upload details, document type, STP flag
status WRITE PENDING (processed async)

12. Implementation Notes

File Storage via Configured Drive File storage does not use a hardcoded S3 bucket. The storage destination is determined by the application configuration (environment variable or config service). This allows switching between S3, Azure Blob, or local encrypted storage without code changes. Always reference the storage abstraction layer, never a specific provider.
OCR is Currently Simulated The OCR integration (Claude Vision / AiNXT) is in simulation mode during initial development. The OCR service layer should be behind an interface so that the simulated implementation can be swapped for the live implementation via configuration. Simulated OCR should return a realistic but clearly marked response (e.g., ocr_status = SIMULATED).
All F&O Manual Uploads are NON_STP This is the single most important business rule for Stage 10. Regardless of the name match score, document quality, or any other factor, every income proof document uploaded manually through this stage results in stp_income_flag = NON_STP. The verifier must review every manual upload for completeness and authenticity. There is no income threshold check in this stage. Do not implement any logic that could set this flag to STP.