Entity Relationship Diagram


Domain Ownership

Auth owns

  • users — creates row on first login
  • otp_sessions — created on trigger, invalidated on verify
  • user_sessions — one per device login, revoked on logout

User Profile reads/writes

  • users — profile fields only (first_name, last_name, email, dob, gender, address, occupation, employer)
  • Cannot write: phone, aadhaar (identity fields owned by Auth)

Wallet owns

  • customer_wallets — one per user, creation status tracked here
  • payment_orders — co-owned with Insurance for the payment session

Insurance owns

  • insurance_plans — seeded catalog from Narayana Health
  • insurance_policies — purchased policies
  • policy_dependants — family members under a policy

PII Storage Policy

These rules are non-negotiable and enforced at the application layer.
FieldStorage RuleAPI Response
phoneStored as +91XXXXXXXXXXReturned as-is
aadhaarLast 4 digits only stored in DBReturned as XXXX-XXXX-1234
refresh_tokenSHA-256 hash stored — never plaintextNever returned
otpHash stored — never plaintextNever returned
emailPlaintext, optionalReturned if set
Wallet responsesFull Juspay JSON stored as JSONB blob for debuggingInternal only

Wallet Creation State Machine


Payment Order Lifecycle

StatusTriggered By
CREATEDApp calls /nh/payment/session
SESSION_CREATEDBackend gets sdk_payload from Juspay
PENDINGApp polling, Juspay not yet terminal
SUCCESSJuspay returns CHARGED (insurance) or wallet.topup.status = SUCCESS
FAILEDJuspay returns FAILED
CANCELLEDUser cancels in SDK