# OpenSpec Change: enterprise-api-plugin-banking - **Change ID**: enterprise-api-plugin-banking - **Package**: `@suaveplan/api-plugin-banking` - **Category**: api/commerce - **Target path**: `api/commerce/api-plugin-banking` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/api-plugin-bank.md` --- ## Summary Deliver `@suaveplan/api-plugin-banking` on the genesis branch from scratch at enterprise quality. The plugin provides open-banking connectivity: account aggregation, transaction listing, balance queries, and bank-initiated payment initiation (PIS). Pluggable bank adapter interface (Open Banking UK / PSD2 / Plaid). Routes mounted under `/banking`. Per-table SurrealQL. Typed event bus for `banking:transaction:received`, `banking:payment:initiated`. Rate-limited, auth-gated, audit-logged, idempotent on payment initiation. PSD2 SCA step-up enforced on payment routes. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/api` (`workspace:^`) | `definePlugin` | | `@suaveplan/api-shared` (`workspace:^`) | Helpers | | `@suaveplan/api-plugin-auth` (`workspace:^`) | `requireAuth` | | `@suaveplan/api-plugin-database` (`workspace:^`) | SurrealDB | | `@suaveplan/events` (`workspace:^`) | Event bus | | `@suaveplan/error` (`workspace:^`) | `BankingError` hierarchy | | `@suaveplan/idempotency` (`workspace:^`) | Payment initiation guard | | `@suaveplan/audit-logging` (`workspace:^`) | Audit trail | | `@suaveplan/rate-limiter` (`workspace:^`) | Rate limits | | `hono` + `@hono/zod-openapi` + `zod` | Routes | | `@opentelemetry/api` | OTel | --- ## Public API surface ```ts function createBankingPlugin(adapter: BankAdapter, config?: BankingPluginConfig): PluginDescriptor interface BankAdapter { listAccounts(tenantId: string, userId: string): Promise getBalance(accountId: string): Promise listTransactions(accountId: string, query: TxQuery): Promise initiatePayment(payment: PaymentRequest): Promise getConsentUrl(userId: string, scopes: string[]): Promise exchangeConsent(code: string): Promise } // Routes: GET /banking/accounts, GET /banking/accounts/:id/balance, // GET /banking/accounts/:id/transactions, POST /banking/payments, // POST /banking/consent, GET /banking/consent/callback ``` ### Error codes ```ts type BankingErrorCode = | "BANKING_ACCOUNT_NOT_FOUND" | "BANKING_CONSENT_REQUIRED" | "BANKING_CONSENT_EXPIRED" | "BANKING_PAYMENT_FAILED" | "BANKING_SCA_REQUIRED" | "BANKING_ADAPTER_ERROR" ``` --- ## File layout ```text api/commerce/api-plugin-banking/ package.json tsconfig.json vitest.config.ts surql/ (bank_account, bank_transaction, bank_consent, bank_payment tables) src/ index.ts events.ts types/ errors/ adapters/bank-adapter.port.ts services/banking/ routes/banking/ tests/integration.test.ts ``` --- ## Impact Prerequisites: `@suaveplan/api`, `@suaveplan/api-plugin-auth`, `@suaveplan/api-plugin-database`, `@suaveplan/events`, `@suaveplan/idempotency`, `@suaveplan/audit-logging`.