Skip to content

v0.2 — Data model & knowledge corpus (ACCEPTED)

Status: accepted 2026-11-12. Architecture context: v1.0. Fictional company: Kosha Financial (Indian neobank, partner-bank model). All people are synthetic.

0. Ground rules for realism

Rule Why it matters
Money is BIGINT paise, never float Float rounding is the #1 fintech bug interviewers probe
All timestamps timestamptz in UTC; rendered IST NEFT/RTGS windows and RBI TATs are IST-based
Full Aadhaar is never stored — only aadhaar_ref_token + last 4 UIDAI Aadhaar Data Vault rules
PAN stored as KMS-encrypted token + last 4; full value only for kyc:pii scope DPDP Act 2023 data minimisation
IDs are prefixed ULIDs (cus_01J…, txn_01J…) Sortable, non-guessable, self-describing in logs
Every format passes real validators: PAN AAAPL1234C (4th char P, 5th = surname initial), IFSC XXXX0YYYYYY, UPI RRN 12 digits, NEFT UTR, GSTIN with checksum, Indian mobile [6-9]\d{9}, pincode ↔ state Recruiters who know fintech will spot fake-looking data instantly
Generator is deterministic (--seed) Reproducible tests and demos

1. Schemas (PostgreSQL 16 + pgvector)

Schemas: core (customers/accounts/payments), ledger (double-entry), kyc, risk, ops (disputes, outbox, audit, idempotency), kb (knowledge base).

core.customers

customer_id · cif_number (10-digit) · first_name · middle_name · last_name · date_of_birth · gender · email · mobile · mobile_verified · persona (salaried | student | gig_worker | sme_owner | nri | senior_citizen) · occupation · employer_name · annual_income_band · segment (mass | affluent | premium) · residential_status (resident | nri) · preferred_language · onboarding_channel (app | web | assisted | partner) · relationship_start_date · status (prospect | active | on_hold | dormant | frozen | under_investigation | deceased_claim_pending | closed) · risk_category (low | medium | high) · created_at · updated_at

core.addresses

address_id · customer_id · address_type (permanent | correspondence) · line1 · line2 · city · district · state · state_code · pincode · country · is_verified · valid_from · valid_to

core.accounts

account_id · customer_id · account_number · ifsc (KOSH0000001…) · product_code (SAVINGS_REGULAR | SAVINGS_SALARY | CURRENT | FD | RD) · status (see §1a) · status_reason · mode_of_operation (single | joint) · opened_at · closed_at · ledger_balance_paise · available_balance_paise · hold_amount_paise · minimum_balance_paise · interest_rate_bps · overdraft_limit_paise · nominee_registered · last_txn_at

core.cards

card_id · account_id · network (rupay | visa | mastercard) · card_type (debit | credit | prepaid) · pan_last4 · token_ref · status (see §1a) · expiry_month · expiry_year · atm_limit_paise · pos_limit_paise · ecom_limit_paise · contactless_enabled · international_enabled · issued_at

core.vpas (UPI handles)

vpa_id · customer_id · account_id · vpa (ravi.k@kosha) · is_primary · status · created_at

core.beneficiaries

beneficiary_id · customer_id · nickname · account_number_masked · ifsc · bank_name · added_at · cooling_period_ends_at (new-payee limit — real anti-fraud control) · status (see §1a)

core.merchants

merchant_id · display_name · legal_name · mcc (5411, 5812, 4121, 5732, 4900, 6011…) · category · sub_category · city · state · vpa · gstin · acquirer_bank · risk_level

core.transactions (range-partitioned by month on initiated_at)

txn_id · account_id · customer_id · direction (debit | credit) · amount_paise (CHECK > 0) · currency · rail (upi | imps | neft | rtgs | card_pos | card_ecom | atm | nach | internal) · txn_type (p2p | p2m | salary | emi | bill_pay | refund | reversal | cash_withdrawal | interest_credit | charges | fd_booking) · status (see §1a) · status_reason_code · failure_reason_code (NPCI-style U30, U69, XB…) · hold_reason · expected_credit_by · utr · rrn · npci_txn_id · counterparty_name · counterparty_vpa · counterparty_account_masked · counterparty_ifsc · merchant_id · mcc · channel (mobile_app | web | pos | atm | api) · device_id · ip_address (inet) · geo_city · geo_lat · geo_lng · narration (statement-style UPI/DR/412345678901/QUICKBASKET/qb@axis/Payment) · remarks · initiated_at · posted_at · value_date · balance_after_paise · risk_score (0–100) · is_flagged

Indexes: (account_id, initiated_at DESC), (customer_id, initiated_at DESC), (merchant_id), unique (utr), pg_trgm on narration.

core.transaction_status_history

history_id · txn_id · from_status · to_status · reason_code · actor (system | npci | ops_user | risk_engine) · occurred_at — every transaction's full lifecycle, so "why was this on hold for 3 days?" is answerable.

§1a — Status lifecycles (all enforced by a state-machine table + DB CHECK; illegal transitions rejected)

Entity Statuses
Transaction initiated → authorised → processing → pending → success · credit_delayed (debited at remitter, beneficiary credit pending — the classic UPI "money gone, not received") · deemed_success (NPCI deemed-approved after beneficiary-bank timeout) · on_hold (risk/compliance hold) · under_review · pending_settlement · settled · failed · timed_out · declined (limits/insufficient funds/risk) · cancelled · expired (UPI collect request lapsed) · returned (NEFT/IMPS returned by beneficiary bank) · reversal_initiated → reversed · partially_reversed · refunded · chargeback_initiated
Account pending_activation · active · kyc_pending · dormant · inoperative (RBI: no customer-induced txn for 2 years) · debit_freeze · credit_freeze · total_freeze · lien_marked · on_hold · pending_closure · closed
KYC profile not_started · pending_documents · pending_vcip · in_review · on_hold · escalated · verified · rejected · re_kyc_due · re_kyc_overdue · expired
Card inactive · active · temp_blocked (user-initiated) · pin_blocked · blocked · hotlisted (lost/stolen) · expired · replaced
Dispute raised · acknowledged · awaiting_customer_info · under_investigation · on_hold · chargeback_raised · pre_arbitration · arbitration · resolved_customer_favour · resolved_merchant_favour · auto_reversed · withdrawn · closed
AML alert open · assigned · in_review · pending_info · on_hold · escalated · closed_false_positive · closed_no_action · closed_str_filed
Transaction review queued · in_review · on_hold · cleared · escalated_to_aml · blocked
Beneficiary pending_cooling · active · disabled · deleted

The generator produces realistic distributions (≈96% success, ≈1.5% failed/declined, small tails of credit_delayed, deemed_success, on_hold, returned, reversals) — and the long-tail statuses are exactly what disputes and support SOPs reference.

ledger.journal_entries / ledger.postings (double-entry)

entry_id · txn_id · posted_at · description posting_id · entry_id · gl_account (customer account or internal GL: UPI_SETTLEMENT, NEFT_SETTLEMENT, FEE_INCOME, INTEREST_EXPENSE, SUSPENSE) · amount_paise (signed) Invariant: Σ postings per entry = 0 (deferred constraint trigger). A nightly reconciliation test proves accounts.ledger_balance_paise = Σ postings.

kyc.kyc_profiles

kyc_id · customer_id · kyc_type (min_kyc | full_kyc | v_cip | ckyc_download) · kyc_status (see §1a) · ckyc_number (14-digit KIN) · pan_token · pan_last4 · pan_status (valid | invalid | not_aadhaar_linked) · pan_name_match_score · aadhaar_ref_token · aadhaar_last4 · ovd_type (passport | voter_id | driving_licence | aadhaar) · vcip_session_id · vcip_agent_id · liveness_score · face_match_score · vcip_geo_lat · vcip_geo_lng · pep_flag · sanctions_flag · fatca_crs_declared · risk_category · risk_rationale · verified_at · verified_by · next_review_due (high 2y / medium 8y / low 10y per RBI KYC Master Direction) · created_at

kyc.kyc_documents

document_id · kyc_id · customer_id · doc_type (pan_card | aadhaar_masked | passport | selfie | address_proof | signature) · s3_key · sha256 · status (accepted | rejected | expired) · rejection_reason · uploaded_at · expires_on

kyc.kyc_events

event_id · kyc_id · from_status · to_status · actor · reason · occurred_at (full state-machine history)

risk.aml_rules / risk.aml_alerts

Rules: rule_id · name · typology · params (jsonb thresholds) · severity · enabled Alerts: alert_id · customer_id · rule_id · typology (structuring | rapid_movement | mule_account | round_tripping | dormant_reactivation | high_risk_geo | velocity) · score · status (see §1a) · assigned_to · sla_due_at · triggering_txn_ids (text[]) · narrative · disposition · str_reference · created_at · closed_at Every alert is generated by actually running the rules over the generated transactions — the planted typologies are what fire them.

risk.screening_results

screening_id · customer_id · screened_name · list_source (UN_SC | OFAC_SDN | MHA_UAPA | INTERNAL_PEP — synthetic lists) · match_score · decision (clear | potential_match | true_match) · vendor_ref · screened_at

ops.disputes · ops.transaction_reviews

Disputes: dispute_id · txn_id · customer_id · reason_code (unauthorized | goods_not_received | duplicate | amount_mismatch | failed_but_debited | credit_not_received) · amount_paise · status (see §1a) · tat_due_at · compensation_paise (RBI TAT-harmonisation ₹100/day) · resolution · chargeback_ref · idempotency_key · created_by · created_at Reviews: review_id · txn_id · reason · priority · status (see §1a) · idempotency_key · created_by · created_at

ops.outbox · ops.audit_log · ops.idempotency_keys

Outbox: event_id · aggregate_type · aggregate_id · event_type · payload (jsonb) · created_at · published_at Audit (append-only; UPDATE/DELETE revoked): audit_id · actor_sub · client_id · roles · tool_name · args_hash · resource_ids · pii_unmasked · outcome · error_code · latency_ms · trace_id · occurred_at Idempotency: key · scope · request_hash · status · response (jsonb) · expires_at — written in the same DB transaction as the business write → exactly-once effect.

kb.documents · kb.chunks

Documents: doc_id · doc_code (CMP-SOP-004) · department · title · doc_type (policy | sop | runbook | playbook | api_reference | guideline | faq | template) · version · status (draft | effective | superseded) · effective_date · review_due · owner_role · approver · classification (public | internal | confidential | restricted) · source_format (md | pdf | docx | html | openapi) · s3_uri · sha256 · supersedes_doc_id · regulatory_refs (text[]) · tags (text[]) Chunks: chunk_id · doc_id · chunk_index · section_path (4 › 4.2 Enhanced Due Diligence) · content · token_count · embedding (vector) · tsv (generated tsvector) · metadata (jsonb) Indexes: HNSW on embedding, GIN on tsv. Postgres Row-Level Security on classification — a marketing user physically cannot retrieve a restricted compliance chunk.

2. Synthetic data volumes (proposed)

Entity Count
Customers 5,000 (personas weighted to Indian neobank mix)
Accounts ~7,500
Cards / VPAs ~6,000 / ~6,500
Merchants ~1,200
Transactions ~1.5M over 18 months (salary cycles, EMIs, festive spikes)
AML alerts ~400 (from ~2% planted bad actors + false positives)
Disputes ~600

3. Knowledge corpus — ~85 documents, 9 departments

Mixed formats on purpose (≈60 Markdown, 15 PDF, 6 DOCX, OpenAPI YAML + HTML API docs) so ingestion is real. Deliberate RAG traps: superseded versions of the same SOP (retrieval must prefer effective), cross-references, fee/limit tables, escalation matrices, RACI tables, and one "vendor-supplied" doc containing a planted prompt-injection string for security tests.

Dept Code Documents
Compliance CMP AML/CFT Policy · CDD & EDD SOP · Transaction Monitoring & Alert Handling SOP · STR/CTR Filing to FIU-IND SOP · Sanctions & PEP Screening SOP · Record Retention Policy (PMLA) · Regulatory Reporting Calendar · Payment Data Localisation Policy · Compliance Testing Charter · Whistleblower Policy
Onboarding / KYC ONB Digital Onboarding SOP · Video-KYC (V-CIP) Procedure · Min-KYC → Full-KYC Upgrade SOP · Periodic Re-KYC SOP · CKYC Upload/Download SOP · OVD Verification Checklist · NRI Onboarding SOP · Onboarding Rejection Handling · Minor Accounts SOP
Legal LGL Savings Account Terms & Conditions · Privacy Notice (DPDP Act 2023) · Data Processing Agreement template · Grievance Redressal Policy (RBI Integrated Ombudsman) · Law-Enforcement Request & Account Freeze SOP · Customer Consent Management Policy · Vendor Contract Standards · Digital Lending Guidelines Compliance Note
Risk & Fraud RSK Fraud Risk Management Policy · Disputes & Chargebacks SOP · Failed-Transaction TAT & Compensation SOP · Mule Account Detection Playbook · Account Takeover Response Runbook · Operational Risk Incident Reporting · CERT-In Cyber Incident Reporting (6-hour rule) · Risk Appetite Statement
Customer Support CS Support Tiering Playbook · Escalation Matrix · Response Macros Library · Card Block/Unblock SOP · Complaint Categorisation Guide · Deceased Claim Settlement SOP · Frozen Account Communication Guide · Support FAQ
Sales SLS Product Catalogue & Schedule of Charges · Corporate Salary-Account Tie-up SOP · Referral Programme Rules · Sales Conduct & Mis-selling Policy · Lead Qualification Playbook · Business Correspondent Partner Onboarding
Marketing MKT Brand Guidelines · Marketing Communications Compliance (RBI Fair Practices, ASCI) · Campaign Approval Workflow · Festive Campaign Playbook · TRAI DLT SMS Template Registration SOP · Social Media Policy
Engineering / API ENG Public API Reference (OpenAPI 3.1: accounts, payments, KYC) · Authentication Guide (OAuth 2.1) · Webhooks Guide (signing, retries) · Idempotency Guide · Rate Limits & Error Codes · Sandbox Guide · API Versioning & Deprecation Policy · Incident Management Runbook & SEV Levels · Changelog
Company CORP Company Overview & Org Chart · Code of Conduct · Information Security Policy · BCP / DR Policy · Employee Handbook · Corporate Glossary · Board-Approved Policy Register

Every document carries a header block: doc code, version, status, effective date, owner, approver, classification, regulatory references, revision history. Real public regulations are cited by name; the company and all its procedures are fictional, and every file says so.