Test environment setup¶
This runbook covers the operational steps for setting up and maintaining dev and UAT environments as working simulated bank instances. It covers provider stub deployment, seed data loading, synthetic transaction engine activation, and acceptance suite operation.
The architectural decisions behind these choices are in ADR-044 and ADR-045.
Environment overview¶
| dev | uat | prod | |
|---|---|---|---|
| External providers | Stubbed (MOD-157) | Stubbed (MOD-157) | Real |
| Seed data | dev profile (10 customers) | uat profile (100 customers) | N/A |
| Synthetic transactions | Tue + Thu, light | Daily 2×, full volume | Disabled |
| Acceptance suite | Nightly | Nightly | Not deployed |
| Neon database | dev branch | uat branch | main branch |
| Database teardown on deploy | Never | Never | Never |
Phase 1: Deploy the stub service¶
MOD-157 must be deployed before any module with an external provider dependency can run integration tests.
The CI/CD pipeline handles this automatically once MOD-157 has a Built status in the wiki. To deploy manually during initial setup:
After deployment, verify stub endpoints are reachable:
Verify SSM paths have been written:
aws ssm get-parameters-by-path \
--path /bank-kyc/dev \
--query "Parameters[*].{Name:Name,Value:Value}" \
--region ap-southeast-2
Phase 2: Load seed data¶
Seed data is loaded automatically on first deploy of MOD-158 to a fresh stage. For a new environment, deploy MOD-158 after the Neon database branch exists (requires MOD-103 deployed first):
cd MOD-158-test-seed-data-loader
pnpm run deploy --stage dev
# seed loader runs automatically via SST Custom Resource
To verify seed data is loaded:
aws ssm get-parameter \
--name /bank-platform/dev/seed-version \
--region ap-southeast-2
# → {"Parameter":{"Value":"1.0.0",...}}
To check what customers are in the database:
# connect to dev Neon branch and query
psql $NEON_DEV_URL -c "SELECT customer_id, full_name, kyc_status FROM customers.customers;"
Resetting seed data¶
Warning: this deletes all data in seed tables, including any synthetic transaction history.
cd MOD-158-test-seed-data-loader
pnpm run seed:reset --stage dev
# or for UAT (requires explicit confirmation):
pnpm run seed:reset --stage uat --confirm
The reset command: 1. Removes the SSM version key 2. Truncates seed tables in the correct dependency order (ledger_entries → accounts → customers) 3. Re-invokes the seed loader Lambda with the current version
Phase 3: Activate the synthetic transaction engine¶
MOD-159 is deployed by its CI pipeline once all mandatory dependencies are Built. The EventBridge schedule starts in DISABLED state and is enabled automatically when the CI pipeline confirms all dependencies are deployed.
To enable manually for dev (once dependencies are confirmed):
aws scheduler update-schedule \
--name synthetic-transaction-generator-dev \
--state ENABLED \
--region ap-southeast-2
To check the engine's last run and transaction count:
aws logs filter-log-events \
--log-group-name /aws/lambda/synthetic-transaction-generator-dev \
--start-time $(date -v-1d +%s000) \
--filter-pattern "transactions_submitted" \
--region ap-southeast-2
To trigger a manual run (useful after a seed reset):
aws lambda invoke \
--function-name synthetic-transaction-generator-dev \
--payload '{"manual":true}' \
/tmp/response.json \
--region ap-southeast-2
cat /tmp/response.json
Phase 4: Verify acceptance suite¶
MOD-160 runs nightly at 02:00 NZST. To run it manually:
aws lambda invoke \
--function-name acceptance-dispatcher-dev \
--payload '{}' \
/tmp/acceptance.json \
--region ap-southeast-2
cat /tmp/acceptance.json
# → {"scenarios_run":8,"passed":8,"failed":0,"skipped":0}
To check the CloudWatch dashboard:
Interpreting results¶
| Scenario status | Meaning |
|---|---|
passed |
End-to-end flow completed successfully |
failed |
Assertion failure — see scenario Lambda logs for detail |
skipped |
Dependency module not yet deployed in this stage |
error |
Scenario Lambda itself threw an unexpected error |
A skipped result is expected and normal when not all modules are deployed. It becomes a failure concern only if a previously-passing scenario starts being skipped (which would indicate an SSM output path was removed).
Stub test patterns reference¶
Use these inputs in integration tests to trigger deterministic stub responses.
eIDV stubs¶
| Document reference prefix | DVS/DIA response | Onfido response |
|---|---|---|
PASS- |
Verified, high confidence | Verified (webhook after 2s) |
FAIL- |
Identity mismatch | Rejected (webhook after 2s) |
REFER- |
Insufficient data | Manual review required |
Payment clearing stubs¶
| NPP destination account suffix | Clearing result |
|---|---|
0001 |
Cleared — settlement confirmed |
0002 |
Dishonoured — insufficient funds at receiving institution |
0003 |
Timeout — no clearing response within SLA |
| BECS payer BSB | Behaviour |
|---|---|
062-000 |
All presentments honour |
062-001 |
Second presentment dishonours |
062-002 |
All presentments dishonour |
Sanctions stub¶
| Name pattern | Result |
|---|---|
Contains SANCTIONED |
Confirmed sanctions match |
Contains PEP- |
PEP hit, no direct sanctions |
| Anything else | Clear |
Notification capture queries¶
Integration tests can query what notifications were dispatched:
# via the stub service API
curl "https://stubs-dev.bank-dev.internal/notifications/capture\
?customer_id=CUST-D001&type=email&after=2026-04-27T00:00:00Z"
# → [{"notification_id":"...","type":"email","recipient":"test+D001@bank-dev.internal",
# "subject":"Your account is ready","dispatched_at":"2026-04-27T09:15:32Z"}]
Notifications older than 30 days are automatically deleted from the capture table.
Troubleshooting¶
Stub returns 404 for a new provider¶
MOD-157 has not been updated to include the new provider's route. Update MOD-157 and redeploy.
Integration test fails with "balance insufficient"¶
The seed data balance for the test customer may have been depleted by synthetic transaction runs. Either reset seed data or use a customer with a higher seed balance (CUST-D001 has NZD 50,000).
Acceptance suite scenario skipped unexpectedly¶
Check that the expected module is deployed and its SSM output path exists:
UAT looks empty despite seed being loaded¶
Seed data version key exists but data is missing. This can happen if a schema migration truncated tables without bumping the seed version. Run seed:reset --stage uat --confirm to reload.