-
Notifications
You must be signed in to change notification settings - Fork 0
Dataset
This page lists the default test users seeded by the PSP demo and the data needed to run card payments and bank transfers (ACH / SEPA / SWIFT) end to end, without data-entry errors. It is aligned with the seeders and with the built-in validation modules (card issuer, account information, rail engine), and it shows how movements are approved or blocked following standard PSP procedures.
These are fictitious test values. No real cardholder data (full PAN / CVV) is stored by the PSP: seeded cards are PAN-masked, and card numbers below are standard Luhn-valid test ranges only.
The login users are the same ones served by the login screen. The authoritative, always-current list comes from the endpoint, so it never drifts from the seeders:
GET /api/v1/auth/users (optionally ?featured=true)
Backing: auth.controller.ts -> getDemoUsers (auth.service.ts), collection
customerAuthenticationAssessment, seeded from backend/data/customerAuthentications.json.
Password for every demo user: demo-password. Regenerate the tables below from that endpoint plus
backend/data/parties.json, paymentCards.json and payoutAccounts.json whenever seeds change.
| Name | Username (email) | Password | Role |
|---|---|---|---|
| Luis Fernandez | luis.fernandez@back.es | demo-password | customer |
| Julia Santos | julia.santos@back.es | demo-password | customer |
| Amara Okafor | amara.okafor@back.es | demo-password | customer |
| Carlos Garcia | carlos.garcia@back.es | demo-password | customer |
| David Chen | david.chen@back.es | demo-password | merchant_officer |
| Rachel Torres | rachel.torres@back.es | demo-password | merchant_officer |
| Sarah Chen | sarah.chen@back.es | demo-password | level1_analyst |
| Michael Obi | michael.obi@back.es | demo-password | level2_investigator |
| Anna Kowalski | anna.kowalski@back.es | demo-password | level1_analyst |
| James Wright | james.wright@back.es | demo-password | level2_investigator |
| Diego Sans | diego.sans@back.es | demo-password | security_auditor |
| Sophie Martin | sophie.martin@back.es | demo-password | security_auditor |
| Alex Rivera | alex.rivera@back.es | demo-password | manager |
| Customer | Account alias | Currency | Rail | IBAN (full) | Available |
|---|---|---|---|---|---|
| Luis Fernandez | espressoworks-ledger | EUR | internal_ledger | — | 2847.50 |
| Luis Fernandez | Luis SEPA account | EUR | sepa | ES9121000418450200051332 | 3500.00 |
| Luis Fernandez | Luis Santander | EUR | sepa | ES7620770024003102575766 | 4800.00 |
| Julia Santos | Julia main account | EUR | sepa | GB29NWBK60161331926819 | 3800.00 |
| Julia Santos | Julia Barclays | EUR | sepa | GB94BARC10201530093459 | 5200.00 |
| Amara Okafor | okafor-digital-ledger | EUR | internal_ledger | — | 1540.75 |
| Amara Okafor | Amara Barclays | EUR | sepa | GB33BUKB20201555555555 | 4500.00 |
| Amara Okafor | Amara Monzo | EUR | sepa | GB69MONZ04000482991234 | 3200.00 |
| Carlos Garcia | Carlos BBVA | EUR | sepa | ES8023100001180000012345 | 4100.00 |
| Carlos Garcia | Carlos Santander | EUR | sepa | ES1120807182183625664112 | 3600.00 |
| Carlos Garcia | Carlos CaixaBank (suspended) | EUR | sepa | ES6621000418401234567891 | 0.00 |
| David Chen | fischer-web-ledger | EUR | internal_ledger | — | 9800.00 |
The four featured customers (Luis, Julia, Amara, Carlos) each hold at least two active bank accounts funded above 3000 EUR so card-payment and funds-gate tests pass. Their registered cards are spread across their own accounts (a card funds from exactly one account; an account may back several cards) and no card is funded by an account belonging to another party.
All IBANs above are ISO 13616 (mod-97) valid — use the full IBAN verbatim on the "New bank account" tab of
/system/transfer/bankor when registering a payout account. Copy the exact value; a different IBAN registers a different account and will not reconcile with the balances/tests documented here.
Each row is a card saved to the customer's wallet with the full card number to type at card-payment flows, its funding bank account, and status.
Why the full number matters. The surrogate token stored per card is derived deterministically from the card number:
token = "pm_" + HMAC-SHA256(cardNumber, key).hex[0:24] + last4(seefrontend/src/lib/cardTokenize.ts, keydemo-psp-tokenization-key-v1). The same card number always yields the same token, so entering the exact number below makes the system recognise the card as this customer's registered card. A different number derives a different token — the system would treat it as a brand-new card, silently breaking any test that assumes you are paying with a specific registered card. The four featured customers share no card number between them.Expiry. Any date in the future is accepted; a past date is declined with
54 expired_card. The demo clock runs ahead of real time, so check today's date in the app before reusing an old expiry. The stored expiry shown below is what the card would print; you may type any future date.CVV. A wrong value is declined with
82 invalid_cvv, so it is not "any 3 digits". The module runs incvvMode: both(default), which accepts EITHER of two values per card:
- Global demo CVV
123(validCvvat Admin -> Modules -> Card issuer). Works on every card. Use it for anything that is not specifically testing per-card CVV.- Derived CVV, the realistic one a real issuer recomputes in its HSM:
digits(HMAC-SHA256(CVK, cardToken | expiryMMYY | serviceCode))[0:cvvLength]. It is never stored (it is Sensitive Authentication Data), only derived on demand. The value per card is in the table below, and is what you need to testcvvMode: per_cardor the reveal flow.The derived CVV is environment-specific. The CVK is minted randomly at setup, so every fresh deployment (and any
--resetthat drops the key vault) produces a DIFFERENT set of derived CVVs. The values below are the ones in force right now; re-read them after a reset (see Re-reading the derived CVVs under the table). The global123is unaffected by resets.
| Customer | Brand | Card number (full) | Masked | Expiry | CVV (global) | CVV (derived) | Status | Alias | Funding account |
|---|---|---|---|---|---|---|---|---|---|
| Luis Fernandez | Visa | 4539 0010 0007 0144 | ****-0144 | 05/27 | 123 | 854 | active | Emergency | Luis SEPA account |
| Luis Fernandez | Visa | 4539 0010 0001 0348 | ****-0348 | 12/28 | 123 | 039 | active | Work | Luis SEPA account |
| Luis Fernandez | Visa | 4539 0010 0004 1202 | ****-1202 | 11/27 | 123 | 399 | active | Business | Luis SEPA account |
| Luis Fernandez | Visa | 4539 0010 0006 3040 | ****-3040 | 10/31 | 123 | 328 | blocked | Subscriptions | Luis Santander |
| Luis Fernandez | Mastercard | 5555 0010 0005 2262 | ****-2262 | 11/27 | 123 | 158 | active | Family card | Luis Santander |
| Julia Santos | Mastercard | 5555 0010 0001 1177 | ****-1177 | 10/31 | 123 | 801 | active | Online shopping | Julia main account |
| Julia Santos | Mastercard | 5555 0010 0007 5909 | ****-5909 | 02/30 | 123 | 941 | active | Work | Julia main account |
| Julia Santos | Visa | 4539 0010 0004 4685 | ****-4685 | 09/30 | 123 | 919 | active | Personal | Julia main account |
| Julia Santos | Visa | 4539 0010 0006 2224 | ****-2224 | 10/27 | 123 | 791 | active | Subscriptions | Julia Barclays |
| Julia Santos | Visa | 4539 0010 0007 2041 | ****-2041 | 08/30 | 123 | 452 | active | Shared home | Julia Barclays |
| Amara Okafor | Visa | 4539 0010 0009 2403 | ****-2403 | 09/28 | 123 | 179 | active | Family | Amara Barclays |
| Amara Okafor | Mastercard | 5555 0010 0001 1599 | ****-1599 | 11/30 | 123 | 249 | active | Business | Amara Barclays |
| Amara Okafor | Visa | 4539 0010 0008 5100 | ****-5100 | 06/30 | 123 | 201 | active | Personal | Amara Monzo |
| Amara Okafor | Mastercard | 5555 0010 0003 5739 | ****-5739 | 11/31 | 123 | 578 | active | Online shopping | Amara Monzo |
| Carlos Garcia | Visa | 4539 0010 0006 6266 | ****-6266 | 11/27 | 123 | 266 | active | Savings-linked | Carlos BBVA |
| Carlos Garcia | Visa | 4539 0010 0005 1243 | ****-1243 | 01/27 | 123 | 084 | active | Subscriptions | Carlos BBVA |
| Carlos Garcia | Mastercard | 5555 0010 0006 4093 | ****-4093 | 05/30 | 123 | 170 | active | Business | Carlos Santander |
The derived value is bound to the card token AND the expiry above. Type a different (still future) expiry and the derived CVV no longer matches: use
123, or re-derive for that expiry.
Two ways, both without touching the database:
-
Admin console. Admin -> Modules -> Card issuer exposes the reveal per card (
GET /api/v1/modules/card-issuer/cards/{cardId}/cvv, operations officer only, audited ascard.cvv.revealed). -
Internal loopback, handy to regenerate the whole table:
curl -s -X POST "$PSP_API/api/v1/modules/card-issuer/reveal" \ -H 'Content-Type: application/json' -H 'X-Integration-Source: psp-demo' \ -d '{"cardId":"<paymentCardInstanceReference>"}' # -> {"cvv":"854","revealed":true}
The card ids are deterministic (derived from the customer agreement), so they survive a reset even though the CVVs do not.
Both paths derive the value on demand and return it ephemerally; nothing is written. Card verification data is never stored, in cleartext or encrypted.
Enter these at checkout / card-payment flows. All are Luhn-valid standard test PANs accepted by the
built-in card validator. Use any future expiry (MM/YY) and CVV 123.
| Brand | Card number | Expiry | CVV | Expected outcome |
|---|---|---|---|---|
| Visa | 4111 1111 1111 1111 | 12/29 | 123 | Approved (00) |
| Visa | 4012 8888 8888 1881 | 12/29 | 123 | Approved (00) |
| Visa | 4242 4242 4242 4242 | 12/29 | 123 | Approved (00) |
| Mastercard | 5555 5555 5555 4444 | 12/29 | 123 | Approved (00) |
| Mastercard | 5200 8282 8282 8210 | 12/29 | 123 | Approved (00) |
| Mastercard | 2223 0000 1018 1375 | 12/29 | 123 | Approved (00) |
The first five are exactly the Visa/Mastercard numbers offered by the simulator card picker (Simulator -> Setup), so anything you pick there behaves as listed here. The two Amex entries in that picker are subject to the CVV caveat below.
The built-in issuer has no per-PAN decline list. Numbers such as
4000 0000 0000 0002or4000 0000 0000 9995(which decline at some real gateways) are approved here: the module decides on the card's own credentials, not on a table of magic numbers. To exercise a decline, use the triggers in the next section.American Express cannot be paid with the default configuration. Amex expects a 4-digit CVV while the global demo CVV is
123(3 digits), so every Amex attempt ends in82 invalid_cvv. To demo Amex, set a 4-digitvalidCvvat Admin -> Modules -> Card issuer, or disable the AMEX network there.
| To get | Do this | Response |
|---|---|---|
| Approved | Any card above, future expiry, CVV 123
|
00 approved |
| Expired card | Type an expiry in the past (e.g. 01/24) |
54 expired_card |
| Wrong CVV | Type any CVV other than 123
|
82 invalid_cvv |
| Missing CVV | Leave the CVV empty on a flow that requires it (checkout, payment link, simulator) | 82 cvv_required |
| Failed Luhn | Change one digit of the card number | 14 failed_luhn_check |
| Wrong length for the network | Add or remove a digit | 14 invalid_length_for_network |
| Unsupported network | Disable the network at Admin -> Modules -> Card issuer | 12 unsupported_or_disabled_network |
| Card not registered | Charge a card-on-file token the PSP does not know (server-to-server API payment) | 56 card_not_registered |
| No funding account | Charge a registered card whose funding account is missing | 57 no_funding_account |
| Cardholder name mismatch | Enable name verification, then type a different name | 05 cardholder_name_mismatch |
The registration and funding-account checks apply to a card-on-file charge, where the token is the only credential. A card the payer PRESENTS (full number, or CVV plus expiry on a hosted page) is validated on its own credentials, so a first-time card can pay.
Use these on the "New bank account" tab of /system/transfer/bank. The rail is auto-derived and the
coordinates validate against ISO 13616 (IBAN), ISO 9362 (BIC) and the NACHA ABA checksum.
| Rail | Country | Currency | IBAN / account | Routing / BIC | Expected |
|---|---|---|---|---|---|
| SEPA | DE | EUR | IBAN DE89 3704 0044 0532 0130 00 | BIC DEUTDEFF | Submitted (fee 0) |
| SEPA | FR | EUR | IBAN FR14 2004 1010 0505 0001 3M02 606 | (optional) | Submitted (fee 0) |
| ACH | US | USD | Account 123456789 | Routing 021000021 | Submitted (fee 0.25) |
| SWIFT | SG | SGD | Account 000123 | BIC DBSSSGSG | Submitted (fee 15) |
| SWIFT | SG | SGD | Account 000123 | BIC DBSSSGSG + correspondent CHASUS33 | Submitted (fee 25) |
| (invalid) | DE | EUR | IBAN DE89 3704 0044 0532 0130 01 | Blocked: IBAN fails mod-97 (AC01) | |
| (invalid) | US | USD | Account 1 | Routing 021000020 | Blocked: ABA checksum fails |
| (unsupported) | US | USD | (no IBAN, no routing) | Exception: unsupported corridor |
Each scenario states the input, the module that decides, and the standard code returned.
| Scenario | Input | Deciding module | Result | Standard code |
|---|---|---|---|---|
| Card approved | Visa 4111…1111, sufficient funds | card issuer + funds gate | Approved | ISO 8583 00
|
| Card do-not-honor | Visa 4000…0002 | card issuer (built-in) | Declined | ISO 8583 05
|
| Insufficient funds | amount over available balance | account information (funds gate) | Declined | ISO 8583 51
|
| SEPA transfer | valid EUR IBAN, EEA | rail engine + payment initiation | Submitted -> settled | ISO 20022 |
| ACH return | closed destination account | payment initiation | Failed | NACHA R02
|
| SEPA reject | invalid IBAN | rail engine (validate) | Blocked | ISO 20022 AC01
|
| SWIFT error | invalid BIC | rail engine (validate) | Blocked | SW01 |
| Unsupported corridor | no IBAN/routing/BIC | rail resolver | Exception | UNSUPPORTED_CORRIDOR |
| Fraud / sanctions | high-risk beneficiary (see fraudCases.json) |
FDS / HRP / AML providers | Blocked / review | internal risk code |
Three demo executions initiated by Luis (from pao00001…), one per Recipient variant, so the
detail page /system/payment/history/{ref} shows the correct link / full destination:
| Execution ref | Recipient variant | Detail shows |
|---|---|---|
e0000001-0000-4000-8000-000000000001 |
Saved beneficiary (Carlos, cab00002…) |
Link → /system/beneficiaries/cab00002… + payout account |
e0000002-0000-4000-8000-000000000002 |
Registered payout account (pau00001…) |
Link → /system/accounts/pau00001…
|
e0000003-0000-4000-8000-000000000003 |
Unregistered external IBAN | Full IBAN ES1215830001109043445477 (Marie Dubois, ES) |
- Rail auto-derivation: EUR + IBAN + EEA country -> SEPA; USD + routing + account + US -> ACH; BIC cross-border -> SWIFT. The user can override the rail; validation still applies.
- Unregistered destinations: the full destination IBAN is persisted on the execution encrypted at
rest (QE:none
DEK-exec-dest-iban, L2 only — GDPR Art. 32 / PSD2, not PCI) and shown to the owner; a masked form is kept plaintext for lists. Registered destinations link by reference instead. -
KYC demographics (SD-13 Party) apply to every user, staff included:
partyDateOfBirth,partyNationalityandpartyPostalAddressare backfilled deterministically byseedParties, so staff/system/profilepages are as complete as customers'. KYC verification + govId stay in SD-53 (customers); KYB is merchant-level.partyPostalAddressandpartyDateOfBirthare GDPR PII, QE:none (L2 only) — encrypted at rest like the email/phone; shown to the party via a reveal toggle. -
Seeded demo executions move the seeded balance:
seedPaymentExecutionsapplies each completed transfer's debit/credit to the payout-account balance (after the opening deposit is logged), so the account-movement ledger reconciles (opening − Σ sent + Σ received). Only settled movements affect the running balance; failed/exception/pending transfers never shift it. - Every transfer emits a
businessProcessEventand acomplianceProcessEventsharing the execution reference as correlation id (PCI DSS Req 10 audit trail).
The three seed merchants now carry realistic beneficial-owner cap tables: Espresso Works (60/40, 2 owners), Leafy Wallet (50/30/20, 3 owners), Fischer Web Studio (80/15 free-float, 2 owners). Owners reference existing seeded parties (b0000001, b0000002, b0000057-b0000061). The primary owner equals the legacy merchantOwnerPartyReference. The operations_officer demo user now also administers KYC/KYB records and beneficial owners (data correction); merchant_officer keeps the KYB decision. capabilityModuleConfiguration seeds decisionMode (KYC=automated, KYB=manual).
Added 2026-07-24.