Skip to content

Part 10 — System Blueprint

Domain Model Core

Core domain entities are reused by origination, loan management, collections, partner APIs and compliance. They should live behind stable service APIs because PAN, GSTIN, CKYC, beneficial-owner, consent and document records are regulatory evidence. Do not duplicate borrower identity inside every loan table. Use immutable identifiers, versioned evidence and role mappings.

The model assumes PostgreSQL-style types. uuid fields are application-generated. Monetary fields are numeric(18,2) and percentages are numeric(9,6) unless stated otherwise. All tables require created_at timestamptz not null, created_by uuid not null, updated_at timestamptz not null, updated_by uuid not null, and version int not null default 1; those common audit fields are omitted from the field tables below to keep each entity focused.

RuleImplementation
Party is the root identityEvery natural person, proprietorship, partnership, LLP, company, HUF, trust, society, co-operative, guarantor, DSA, vendor and partner is a party.
Legal borrower is explicitA sole proprietorship may use promoter PAN and a trade name, but the borrower role must show whether the legal obligor is the proprietor natural person or a registered legal entity.
Roles are contextualThe same party can be applicant, co-applicant, promoter, beneficial owner, director, partner, guarantor, collateral owner, DSA, vendor or partner on different applications.
Evidence is versionedKYC, document, consent and external-verification results are append-only versions. Status can change; prior evidence cannot be overwritten.
Regulatory data is purpose-boundConsent records must store purpose, scope, retention and revocation because RBI’s Digital Lending Directions require explicit, need-based consent, revocation controls and data minimisation for DLAs/LSPs.
FieldTypeConstraintsNullableReferences
party_iduuidPrimary keyNoNone
party_typeenumValues: natural_person, business_entity, huf, trust, society, cooperative, vendor, channel_partner, regulated_entityNoNone
display_nametext1-200 chars; normalized for searchNoNone
primary_panvarchar(10)Uppercase PAN format; unique where present and activeYesNone
primary_gstinvarchar(15)GSTIN format; unique with is_active=true where presentYesNone
primary_mobilevarchar(15)E.164 or India 10-digit normalized; unique only within customer realmYesNone
primary_emailtextLowercase email formatYesNone
risk_segmentenumretail_sme, micro_sme, small_sme, medium_sme, partner, vendor, employee, unknownNoNone
party_statusenumprospect, active, blocked, deceased, merged, archivedNoNone
blocked_reason_codetextRequired when party_status=blockedYesreason_code.code
merged_into_party_iduuidRequired when party_status=merged; cannot equal selfYesparty.party_id
FieldTypeConstraintsNullableReferences
party_iduuidPrimary key; party.party_type=natural_personNoparty.party_id
full_nametext1-200 charsNoNone
date_of_birthdateMust imply age 18 or higher for signatory; product policy may require 21-70YesNone
genderenumfemale, male, transgender, not_disclosedYesNone
father_or_spouse_nametext1-200 charsYesNone
panvarchar(10)Uppercase PAN; unique across active natural persons where presentYesNone
aadhaar_last4char(4)Last four digits only; never store full Aadhaar unless legally permittedYesNone
ckyc_idvarchar(14)CKYC identifier format where availableYesNone
pep_flagbooleanDefault falseNoNone
deceased_flagbooleanDefault falseNoNone
deceased_datedateRequired when deceased_flag=trueYesNone
FieldTypeConstraintsNullableReferences
party_iduuidPrimary key; party.party_type in business-capable valuesNoparty.party_id
legal_nametextName as per PAN, MCA, deed, GST or registrationNoNone
trade_nametextBusiness name used with customersYesNone
constitution_typeenumproprietorship, partnership, llp, private_limited, public_limited, opc, huf, trust, society, cooperative, otherNoNone
date_of_incorporationdateRequired except informal proprietorship where unknownYesNone
panvarchar(10)Entity PAN where available; proprietorship may use proprietor PAN by policyYesNone
cinvarchar(21)Required for companies when available from MCAYesNone
llpinvarchar(8)Required for LLP when availableYesNone
gstin_primaryvarchar(15)Primary GSTIN for underwriting; additional GSTINs go to tax_registrationYesNone
udyam_registration_numbervarchar(30)Udyam/UAP identifier; uppercaseYesNone
msme_classificationenummicro, small, medium, not_msme, unverifiedNoNone
industry_code_typeenumnic_2008, internal, gst_hsn_dominant, unknownNoNone
industry_codetextRequired when industry is knownYesNone
business_vintage_monthsint0-1200; computed or declaredYesNone
registered_address_iduuidCurrent registered addressYesaddress.address_id
operating_address_iduuidMain business locationYesaddress.address_id
entity_statusenumactive, inactive, dissolved, struck_off, gst_cancelled, under_insolvency, unknownNoNone
FieldTypeConstraintsNullableReferences
relationship_iduuidPrimary keyNoNone
subject_party_iduuidParty being relatedNoparty.party_id
related_party_iduuidRelated partyNoparty.party_id
relationship_typeenumproprietor_of, partner_of, designated_partner_of, director_of, shareholder_of, karta_of, trustee_of, authorised_signatory_of, guarantor_for, collateral_owner_for, group_company_of, relative_ofNoNone
ownership_percentnumeric(9,6)0-100; required for ownership relationshipsYesNone
control_descriptiontextRequired when control exists without ownership thresholdYesNone
effective_fromdateNot future-dated unless pending recordNoNone
effective_todateMust be after effective_fromYesNone
verification_statusenumdeclared, document_verified, registry_verified, rejectedNoNone
FieldTypeConstraintsNullableReferences
application_party_iduuidPrimary keyNoNone
application_iduuidOne applicationNoapplication.application_id
party_iduuidParticipating partyNoparty.party_id
roleenumprimary_applicant, co_applicant, proprietor, promoter, director, partner, authorised_signatory, beneficial_owner, guarantor, collateral_owner, nominee_contact, referenceNoNone
is_obligorbooleanTrue when party signs repayment or guarantee obligationNoNone
signing_requiredbooleanTrue when loan/security document signature is requiredNoNone
kyc_requiredbooleanTrue for borrower, BO, authorised signatory, guarantor, security providerNoNone
role_statusenumproposed, verified, rejected, removedNoNone

RBI KYC requires beneficial-owner identification for legal entities. The thresholds reflected in this schema follow the KYC Master Direction: more than 10 percent for companies and partnerships, more than 15 percent for unincorporated associations/bodies of individuals, and trust-specific author/trustee/beneficiary/control tests.

FieldTypeConstraintsNullableReferences
beneficial_owner_iduuidPrimary keyNoNone
business_party_iduuidLegal entity being assessedNobusiness_entity.party_id
person_party_iduuidNatural person BONonatural_person.party_id
bo_basisenumownership, capital, profits, voting_right, control, senior_managing_official, trust_author, trustee, trust_beneficiaryNoNone
ownership_percentnumeric(9,6)0-100 where measurableYesNone
threshold_applicable_percentnumeric(9,6)10 or 15 or null for control-onlyYesNone
kyc_profile_iduuidBO KYC evidenceYeskyc_profile.kyc_profile_id
verification_statusenumpending, verified, waived_by_compliance, rejectedNoNone
source_document_iduuidShareholding, deed, declaration or registry evidenceYesdocument_instance.document_id
FieldTypeConstraintsNullableReferences
address_iduuidPrimary keyNoNone
party_iduuidOwner partyNoparty.party_id
address_typeenumregistered, operating, residential, communication, factory, warehouse, collateral, billingNoNone
line1text1-200 charsNoNone
line2text1-200 charsYesNone
citytext1-100 charsNoNone
districttext1-100 charsYesNone
state_codechar(2)Indian state/UT codeNostate_master.state_code
pincodechar(6)Indian PIN formatNopincode_master.pincode
geo_latitudenumeric(10,7)-90 to 90YesNone
geo_longitudenumeric(10,7)-180 to 180YesNone
verification_statusenumdeclared, otp_verified, document_verified, field_verified, negative, undeliverableNoNone
valid_fromdateRequiredNoNone
valid_todateMust be after valid_fromYesNone
FieldTypeConstraintsNullableReferences
consent_iduuidPrimary keyNoNone
party_iduuidPerson/entity giving consentNoparty.party_id
application_iduuidRequired for loan-purpose consentYesapplication.application_id
consent_typeenumcontact, bureau_pull, gst_fetch, account_aggregator, bank_statement_upload, digilocker, ckyc_fetch, udyam_verify, itr_fetch, privacy_policy, marketing, data_sharing_partnerNoNone
purpose_codetextMachine-readable purpose; no generic purpose allowedNopurpose_master.code
scope_jsonjsonbData categories, date range, frequency, recipientNoNone
consent_text_versiontextVersion shown to userNoNone
captured_channelenumbranch, dsa_app, customer_portal, dla, partner_api, call_recording, paper_formNoNone
captured_attimestamptzRequiredNoNone
expires_attimestamptzRequired for time-bound fetchesYesNone
revoked_attimestamptzSet on revocationYesNone
evidence_uritextLink to OTP, clickwrap, recording, signed form or AA artefactNodocument_instance.storage_uri
statusenumactive, expired, revoked, superseded, invalidNoNone
FieldTypeConstraintsNullableReferences
kyc_profile_iduuidPrimary keyNoNone
party_iduuidKYC subjectNoparty.party_id
kyc_levelenumlead_basic, full_cdd, v_cip, reliance_ckyc, simplified, enhanced_due_diligenceNoNone
risk_categoryenumlow, medium, high, prohibitedNoNone
kyc_statusenumnot_started, pending, verified, rejected, expired, rekyc_due, blockedNoNone
verified_attimestamptzRequired when verifiedYesNone
periodic_kyc_due_datedateRequired for active customer relationshipYesNone
ckyc_idvarchar(14)CKYC identifier where retrieved or uploadedYesNone
v_cip_session_iduuidRequired when KYC method is V-CIPYesv_cip_session.v_cip_session_id
rejection_reason_codetextRequired when rejectedYesreason_code.code
approved_byuuidKYC checker or AML officerYesuser.user_id
FieldTypeConstraintsNullableReferences
screening_hit_iduuidPrimary keyNoNone
party_iduuidScreened partyNoparty.party_id
application_iduuidApplication contextYesapplication.application_id
screening_typeenumsanctions, pep, adverse_media, internal_negative, fraud_negative, watchlist, wilful_defaulter, defaulter_listNoNone
providertextVendor or internal listNoNone
match_scorenumeric(6,3)0-100YesNone
hit_statusenumopen, false_positive, true_positive, cleared_with_conditions, blockedNoNone
resolution_notetextRequired on closureYesNone
resolved_byuuidCompliance/AML checkerYesuser.user_id
resolved_attimestamptzRequired on closureYesNone
FieldTypeConstraintsNullableReferences
document_requirement_iduuidPrimary keyNoNone
checklist_iduuidRequirement setNodocument_checklist.checklist_id
document_typeenumpan, ovd, gst_certificate, udyam_certificate, partnership_deed, llp_agreement, moa_aoa, board_resolution, bank_statement, gst_return, itr, financial_statement, invoice, title_deed, valuation_report, legal_opinion, insurance_policy, loan_agreement, guarantee, nach_mandateNoNone
required_for_roleenumapplicant, co_applicant, promoter, bo, guarantor, collateral_owner, application, collateral, disbursementNoNone
mandatory_flagbooleanDefault trueNoNone
allow_waiver_flagbooleanDefault falseNoNone
min_copiesint1 or moreNoNone
validity_daysintPositive; null means not age-limitedYesNone
rule_sourcetextProduct/constitution/policy rule that created requirementNoNone
statusenumpending, received, verified, deficient, waiver_requested, waived, not_applicableNoNone
FieldTypeConstraintsNullableReferences
document_iduuidPrimary keyNoNone
document_requirement_iduuidRequirement satisfied by documentYesdocument_requirement.document_requirement_id
party_iduuidDocument ownerYesparty.party_id
application_iduuidApplication contextYesapplication.application_id
document_typeenumSame controlled vocabulary as document_requirement.document_typeNoNone
document_numbertextPAN, GSTIN, certificate number, deed number where applicableYesNone
issue_datedateRequired where document has issue dateYesNone
expiry_datedateRequired where document expiresYesNone
issuer_nametextIssuer or authorityYesNone
storage_uritextDMS object path; immutable versionNoNone
sha256_hashchar(64)Hash of stored objectNoNone
mime_typetextAllowed MIME listNoNone
verification_statusenumuploaded, extracted, verified, deficient, fraud_suspect, rejected, supersededNoNone
verified_byuuidRequired when verified/rejected by humanYesuser.user_id
verified_attimestamptzRequired when verified/rejectedYesNone
FieldTypeConstraintsNullableReferences
verification_iduuidPrimary keyNoNone
party_iduuidSubjectYesparty.party_id
application_iduuidContextYesapplication.application_id
providerenumpan_nsdl, gstn_vendor, udyam, ckyc, digilocker, aa, bureau, mca, cersai, bank_penny_drop, sanctions_vendor, internalNoNone
request_idtextProvider request idNoNone
request_payload_hashchar(64)Hash only for sensitive payloadNoNone
response_payload_uritextEncrypted raw response pathYesNone
normalized_statusenumsuccess, no_hit, mismatch, temporary_failure, provider_error, consent_required, rejectedNoNone
normalized_jsonjsonbParsed fields used by business logicYesNone
verified_attimestamptzProvider response timestampNoNone
ConstraintBuild rule
KYC cannot be a booleanUse kyc_profile with level, risk category, status, evidence and periodic review date.
BO checks cannot be optional for legal entitiesApplication cannot reach kyc_verified until all required beneficial_owner rows are verified, rejected or waived by compliance.
Consent must be revocableEvery data pull must reference an active consent_artifact; revocation blocks future pulls but does not delete records the RE must retain for audit/regulatory purposes.
Documents are immutableA corrected upload creates a new document_instance; old versions remain linked and marked superseded.
Dedupe must support fuzzy matchingKeep exact identifiers on party; keep fuzzy and cross-identifier results in dedupe_match within LOS/BRE so false positives are auditable.