Transaction enrichment engine¶
| ID | MOD-087 |
| System | SD07 |
| Repo | bank-platform |
| Build status | Deployed |
| Deployed | Yes |
| Last commit | ad2fcb849418b37610d14bc9c4f637a291674bd6 |
What it does¶
MOD-087 is the transaction enrichment foundation for the Expense Intelligence Platform. It receives raw transaction events from the core banking ledger and produces enriched transaction records with normalised merchant name, merchant logo, industry code (MCC), geolocation, and an initial spend category signal.
Enriched records are published to the internal event bus and consumed by MOD-088 (expense classification engine), MOD-089 (geo-spatial processor), MOD-091 (receipt processor), and the customer app layer. Every downstream module in the Expense Intelligence Platform depends on the output of MOD-087 — raw transaction data is not consumed directly.
Input schema (v1)¶
MOD-087 subscribes to bank.core.posting_completed (schema 1.1.0) via a cross-bus EventBridge rule provisioned by MOD-103. The event does not carry a raw_merchant_name field or a party_id.
posting_type filter (hard gate). MOD-087 processes only postings where posting_type = 'PAYMENT' (card and EFTPOS transactions). All other types (ACCRUAL, FX_CONVERSION, ADJUSTMENT, REVERSAL, PROVISION) are silently skipped — the handler returns without emitting bank.platform.transaction_enriched. Enriching a fee or accrual posting with a merchant name would be a data quality defect.
raw_merchant_name — v1 simplification (Ruling 4A). MOD-087 retrieves narrative from accounts.postings via a cross-schema SELECT and uses it as raw_merchant_name in both the dictionary lookup and the output event. Card-acquirer narratives ("Caltex Newtown", "PAK'NSAVE 0017") are the raw merchant name in practice; the dictionary normaliser's purpose is resolving variant forms. Documented as a v1 simplification. v2 path: extend posting_completed to carry a dedicated raw_merchant_name field (Option B in the original ruling), or let the external API (ExternalApiEnrichmentProvider) accept narrative + account_context — either is mechanical given the EnrichmentProvider interface.
party_id. MOD-087 retrieves party_id via a cross-schema SELECT on accounts.account_party_relationships WHERE account_id = ? AND relationship_type = 'PRIMARY'. This is the same ADR-064 published view contract pattern used across other cross-schema reads. A platform_enrichment_ro read grant on both accounts.postings and accounts.account_party_relationships must be provisioned by MOD-103 before MOD-087 can be deployed.
Merchant normalisation¶
Raw acquirer merchant names are often truncated, location-coded, or inconsistent across terminals. MOD-087 resolves these to a canonical merchant identity using an internal normalisation dictionary (v1) and an external merchant enrichment API (v2). Once resolved, a merchant record is cached in platform.enrichment_merchants so future transactions at the same merchant incur no enrichment latency.
v1 scope: Built-in dictionary (~50 NZ/AU merchant patterns covering canonical name + MCC). No external API call. logo_url, lat, and lng are nullable — populated once external API integration lands. Enrichment source is DICTIONARY or MCC_INFERENCE only in v1; MANUAL for seed rows.
Enrichment provider interface: All enrichment logic runs behind an EnrichmentProvider interface (src/shared/enrichment-provider.ts). v1 ships DictionaryEnrichmentProvider. v2 adds an ExternalApiEnrichmentProvider (Mastercard Merchant Insights or equivalent, routed via MOD-157 in dev) without modifying the Lambda handler. This is required for FR-762 architectural compliance.
initial_category is out of scope. MOD-088 (expense classification engine) owns spend categorisation. MOD-087 sticks to merchant identity and geolocation per FR-762 and FR-763.
Postgres table¶
platform.enrichment_merchants — merchant identity cache. Owned by MOD-087. See SD07 data model for full schema.
Published event¶
bank.platform.transaction_enriched on the bank-platform bus. Published after each enrichment. See the event catalogue for the full schema. Consumers: MOD-088 (expense classification), MOD-089 (geo-spatial processor), MOD-091 (receipt processor), customer app layer.
Compliance¶
PRI-001 LOG — every enrichment writes a structured audit entry recording posting_id, raw_merchant_name, enrichment_source, and MCC so data-minimisation audits can verify only the fields required for classification are retained.
Module dependencies¶
Depends on¶
| Module | Title | Required? | Contract | Reason |
|---|---|---|---|---|
| MOD-001 | Double-entry posting engine | Required | — | MOD-001 emits bank.core.posting_completed on the bank-core bus — the source event that drives every enrichment. MOD-087 subscribes via a cross-bus EventBridge rule on the bank-core bus. |
| MOD-043 | EventBridge domain event governance | Required | — | EventBridge domain event governance contract governs the bank.platform.transaction_enriched event published to the bank-platform bus; MOD-043 must be deployed for the event schema and delivery log to be active. |
| MOD-076 | Observability platform | Required | — | Observability platform provisions the OTel Lambda layer ARN and CloudWatch log groups consumed by the module logger. |
| MOD-103 | Neon database platform bootstrap | Required | — | Neon database and platform schema provisioned by MOD-103 must exist before this module can create platform.enrichment_merchants. |
| MOD-104 | AWS shared infrastructure bootstrap | Required | — | AWS shared infrastructure provisioned by MOD-104 (VPC, KMS key, EventBridge bus ARNs, per-module IAM role) is required before this module can be deployed. |
Required by¶
| Module | Title | As | Contract |
|---|---|---|---|
| MOD-088 | Expense classification engine | Hard dependency | contract/events/ |
| MOD-089 | Geo-spatial processor | Hard dependency | contract/events/ |
| MOD-091 | Receipt processor | Hard dependency | contract/events/ |
Policies satisfied¶
| Policy | Title | Mode | How |
|---|---|---|---|
| PRI-001 | Privacy Policy | LOG |
Enrichment processing is logged with source signals so data minimisation audits can verify that only the fields required for classification are retained. |
Capabilities satisfied¶
| Capability | Title | Mode | How |
|---|---|---|---|
| CAP-134 | CAP-134 | AUTO |
Normalises merchant name, resolves MCC, attaches location and logo, and emits the enriched transaction event consumed by MOD-088 and the customer app. |
Part of SD07 — Data Platform & Governance Infrastructure
Compiled 2026-05-22 from source/entities/modules/MOD-087.yaml