| BUG-01 | Idempotency key ignored A retried payment (same Idempotency-Key) debits the customer twice. | caught BDD, API, DB, Concurrency | 6 failingAPI Retry with the same key returns the original transfer and debits onceBDD A key can't be reused for a different paymentBDD A retried payment is charged onceDB A retried request leaves exactly one transfer row in the databaseConcurrency 10 parallel retries with one key create exactly one transferAPI Same key with a different amount is rejected with 409 and nothing moves
|
| BUG-02 | Funds check compares whole rupees only Balance 500.50 can send 500.90; the account goes negative. | caught BDD, API, DB | 7 failingBDD A transfer the payer can't afford is rejected and nothing moves [500.50, 500.51]API Insufficient funds is rejected at the paisa boundary and no money moves balance 500.50, send 500.90 → 422 INSUFFICIENT_FUNDSBDD A transfer the payer can't afford is rejected and nothing moves [0.00, 0.01]DB No customer account is negativeAPI Insufficient funds is rejected at the paisa boundary and no money moves balance 0.00, send 0.01 → 422 INSUFFICIENT_FUNDSAPI Insufficient funds is rejected at the paisa boundary and no money moves balance 500.50, send 500.51 → 422 INSUFFICIENT_FUNDS- … and 1 more
|
| BUG-03 | Negative amounts accepted A transfer of -100.00 pulls money from the receiver. | caught BDD, API, DB | 6 failingAPI Invalid opening balances are rejected with 422 INVALID_AMOUNT opening_balance "-5.00" is rejectedDB No customer account is negativeDB No ledger entry has a zero or negative amountBDD Invalid amounts are rejected [-100.00]API Invalid amounts are rejected and no money moves amount "-100.00" → 422 INVALID_AMOUNT, no money movesAPI Invalid amounts are rejected and no money moves amount "-0.01" → 422 INVALID_AMOUNT, no money moves
|
| BUG-04 | Transfer can be refunded twice Sender gets the money back twice. | caught BDD, API | 2 failingAPI A transfer cannot be refunded twiceBDD A transfer can't be refunded twice
|
| BUG-05 | Refund never debits the receiver Refund creates money; the double-entry ledger no longer balances. | caught BDD, API, DB | 9 failingDB Money is conserved: all balances (incl. the funding account) sum to 0.00BDD A day of payments and a refund leaves the books balancedDB Refund does not create money: payer + payee total is unchangedDB Every transaction's debits equal its creditsBDD A refund returns the money to the payerDB Refund writes a balanced DEBIT (receiver) and CREDIT (payer) in the ledger- … and 3 more
|
| BUG-06 | Contract drift on account balance balance returned as a JSON number (1000.5) instead of a string ("1000.50"). | caught API, Contract | 4 failingContract verify(PactVerificationContext) arya-mobile-app - a request for an existing accountAPI Opening an account returns 201 with id, balance, INR and ACTIVEAPI Balance is always a string with exactly two decimalsAPI GET /accounts/{id} returns what was opened
|
| BUG-07 | Lost update under concurrent transfers Balance is read outside the transaction and written back; parallel payments overwrite each other. | caught BDD, DB, Concurrency | 5 failingDB Every account's stored balance equals credits minus debits in the ledgerBDD A day of payments and a refund leaves the books balancedConcurrency 25 parallel transfers of 10.00: every rupee is accounted forConcurrency After parallel transfers the stored balances still match the ledgerConcurrency 20 parallel transfers of 10.00 from 100.00: exactly 10 succeed, never negative
|