Skip to content

MOD-160 — Cross-module acceptance suite

Purpose

Nightly end-to-end acceptance scenarios that cross system-domain boundaries, validating that independently-deployed modules work together as a bank. Per-module integration tests verify a module behaves correctly given correct configuration; MOD-160 verifies the modules compose correctly — that data and events flow across boundaries and user-facing outcomes materialise.

FR scope: requirements: []. Tooling module.

Architectural decisions: ADR-045.

Architecture

EventBridge Scheduler (nightly 02:00 NZST)
  └── dispatcher Lambda
        ├── reads scenario manifest from src/config/scenarios.ts
        ├── for each scenario:
        │     check required SSM paths via dependency-check
        │     if any missing → status=skipped (not failed)
        │     else → invoke bank-acceptance-{scenario_id}-{stage}
        ├── aggregate {passed, failed, skipped, errored}
        ├── PutMetricData → BankPlatform/Acceptance/E2EAcceptanceSuitePass
        └── on any failure → SNS publish to bank-ops-acceptance-{stage}

Deployment scope

dev and uat ONLY. Production monitoring is MOD-076's domain. Stages allow-list + sst.config short-circuit + workflow option list + unit test.

Scenarios (initial set)

ID Description Required modules
s001 Customer onboarding with PASS eIDV MOD-009 / 010 / 013 / 157
s002 Account activation after KYC verified MOD-007 / 009
s003 Inbound credit posted + balance + notification MOD-001 / 003 / 063
s004 Outbound payment passes validation, posts, audit MOD-020 / 001 / 003 / 022
s005 Payment to SANCTIONED counterparty blocked MOD-013 / 020 / 157
s006 Daily accrual posts interest to ledger + balance MOD-005 / 001 / 003
s007 Notification dispatched, captured by MOD-157 log MOD-063 / 157
s008 FAIL eIDV identity → account stays Pending MOD-009 / 007

Each scenario declares the SSM paths the dispatcher checks before invoking. As modules land in dev/uat, more scenarios graduate from skippedpassed/failed.

How skipped works (the resilience design)

Per the spec: "scenarios that depend on modules not yet deployed are automatically skipped". Three distinct result categories:

status meaning metric counted
passed Flow completed, asserts green yes
failed Flow ran, an assert failed yes (E2EAcceptanceSuitePass=0)
skipped Required SSM path missing no
error Scenario Lambda itself threw yes (E2EAcceptanceSuitePass=0)

Custom metric E2EAcceptanceSuitePass = 1 only when every enabled (non-skipped) scenario passed. Skipped scenarios don't push the metric to 0 — that's the whole point. As more modules land, more scenarios run, more pass-bar moves up.

Reporting

  • CloudWatch metric: BankPlatform/Acceptance/E2EAcceptanceSuitePass, ScenariosPassed, ScenariosFailed, ScenariosSkipped (Stage dimension).
  • CloudWatch dashboard: bank-acceptance-{stage} — pass tile, per-scenario time series.
  • SNS alert: bank-ops-acceptance-{stage} — fires when any scenario fails or errors. Subscriber-side dedup (6 h) is out of scope here; topic is the publish point.

Lambda fleet

  • dispatcher (1×) — schedule target.
  • scenario-runner (8× — one per scenario_id, all sharing the same code archive). Each named bank-acceptance-{s001..s008}-{stage}.

The scenario-runner code currently routes to placeholder implementations in src/scenarios/index.ts that return {passed: false, reason: 'not yet implemented'}. This is the honest state — the dispatcher already gated on SSM paths (so this Lambda only runs when its target modules ARE deployed); the not-implemented state will surface as failed in the dashboard, prompting whoever lands those modules to write the assertion.

SSM outputs

Path Value
/bank/{stage}/mod160/dispatcher/{fn-name,fn-arn} Dispatcher Lambda
/bank/{stage}/mod160/schedule/name Schedule name
/bank/{stage}/mod160/alert-topic/arn SNS topic for failures
/bank/{stage}/mod160/dashboard/name CloudWatch dashboard name

Dependencies

  • MOD-157 — provider stubs make scenarios deterministic.
  • MOD-158 — seed customers/accounts exist for scenarios to use.
  • Optional: MOD-159, MOD-001, MOD-009, MOD-020 etc. — the scenarios that exercise these are skipped until those modules land.

Constraints

  • No prod deploy.
  • Scenarios that need additional IAM (HTTP calls to other modules, reads from MOD-158's Neon, etc.) extend the scenario-runner role's policy as they're written. Initial role has SSM read + logs only.
  • Adding a scenario: append a manifest entry to src/config/scenarios.ts AND implement in src/scenarios/index.ts. The dispatcher picks it up automatically because the scenario-runner-lambda stack iterates the manifest's scenario_ids when creating Lambdas.