Add TPIN creation, TPIN-authorised transfers, MPIN reset and transfer history

- Create TPIN: current MPIN -> OTP -> encrypted TPIN via /tpin/create/*,
  from Services and from the transfer screen on TPIN_NOT_SET
- IMPS initiate now sends encryptedTpin instead of encryptedMpin; handles
  INVALID_TPIN and TPIN_NOT_SET
- Share one RSA-OAEP encryption and key-retry path for MPIN and TPIN
- Forgot MPIN on sign-in and Reset MPIN in the Security Center
- Fund transfer history list and detail, reachable from Home
- Brand logo on sign-in and palette updates

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Abin Toppo
2026-09-29 17:54:43 +05:30
co-authored by Claude Opus 5.5
parent abb14d5768
commit f1def81eb7
50 changed files with 3039 additions and 385 deletions
+36
View File
@@ -8,6 +8,18 @@ export const endpoints = {
crypto: {
publicKey: '/crypto/public-key',
},
/**
* Forgot MPIN. Unauthenticated, like registration — the customer has no MPIN
* to open a session with. `initiate` checks the customer with the CBS and
* sends an OTP; `verifyOtp` swaps the OTP for a one-time reset token;
* `confirm` spends that token on the new, encrypted MPIN and revokes every
* open session. There is no resend endpoint: a fresh `initiate` is the resend.
*/
mpinReset: {
initiate: '/mpin-reset/initiate',
verifyOtp: '/mpin-reset/verify-otp',
confirm: '/mpin-reset/confirm',
},
/**
* Server-driven feature switches. Deliberately callable without a session —
* the sign-in screen's own controls are gated, so this has to resolve before
@@ -21,6 +33,20 @@ export const endpoints = {
me: '/auth/me',
logout: '/auth/logout',
},
/**
* Creating the Transaction PIN that authorises fund transfers. Signed-in
* only: org, customer, mobile, device and profile all come from the session,
* so none of them go in a body. `createInitiate` re-checks the current MPIN
* and sends an OTP; `createVerifyOtp` swaps the OTP for a one-time create
* token; `createConfirm` spends that token on the new, encrypted TPIN. There
* is no resend endpoint: a fresh `createInitiate` — MPIN and all — is the
* resend.
*/
tpin: {
createInitiate: '/tpin/create/initiate',
createVerifyOtp: '/tpin/create/verify-otp',
createConfirm: '/tpin/create/confirm',
},
accounts: {
/**
* Every account on the signed-in profile. No parameters — the profile comes
@@ -78,6 +104,16 @@ export const endpoints = {
initiate: '/fund-transfers/initiate',
verifyOtp: (transferId: string) => `/fund-transfers/${transferId}/verify-otp`,
},
/**
* The customer's own IMPS transfers, as the server recorded them — the status
* authority for how each one ended. The list is paginated and filterable by
* status, mode and an inclusive `fromDate`/`toDate`; the detail takes a
* `transferId` from the list. Payee identifiers arrive already masked.
*/
fundTransferHistory: {
list: '/fund-transfer-history',
detail: (transferId: string) => `/fund-transfer-history/${transferId}`,
},
dashboard: {
summary: '/dashboard/summary',
},