Files
suaveplan/openspec/changes/enterprise-gaming-api-plugin-bank/proposal.md
2026-05-27 23:29:53 +01:00

4.2 KiB

OpenSpec Change: enterprise-gaming-api-plugin-bank

  • Change ID: enterprise-gaming-api-plugin-bank
  • Package: @suaveplan/api-plugin-bank
  • Category: gaming/server
  • Target path: gaming/server/api-plugin-bank
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/api-plugin-bank.md

Summary

Deliver @suaveplan/api-plugin-bank on the genesis branch from scratch at enterprise quality. The package is a game-oriented virtual-currency bank built on top of @suaveplan/economy. It adds per-account-type interest accrual (savingsInterestRate vs. currentInterestRate), configurable currency code (default "GOLD"), transfer support, and deposit/withdrawal tracking with a full transaction audit trail. Four Hono route groups expose HTTP endpoints: /accounts, /interest, /transactions, /config. A GameBankService and InterestService are registered as plugin services. Genesis adds Zod request/response schemas, structured errors, OTel route instrumentation, and 100% coverage.


Current-state audit (genesis)

Package does not exist on genesis yet — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) BankError; BANK.* codes
@suaveplan/types (workspace:^) Clock
@suaveplan/economy (workspace:^) Wallet for balance management
@suaveplan/events (workspace:^) bank:deposit, bank:withdrawal, bank:transfer, bank:interest events
zod (catalog:forms) Request/response schemas
@opentelemetry/api (catalog:observability) Route span instrumentation

Public API surface

type AccountType = 'current' | 'savings'

interface BankAccount {
  id: string
  playerId: string
  type: AccountType
  balance: number
  currency: string
  createdAt: number
  lastInterestAt: number
}

interface BankTransaction {
  id: string
  accountId: string
  type: 'deposit' | 'withdrawal' | 'transfer' | 'interest'
  amount: number
  currency: string
  description?: string
  timestamp: number
}

function createGameBankService(options: BankServiceOptions): GameBankService

interface BankServiceOptions {
  currency?: string
  savingsInterestRate?: number   // per day, e.g. 0.005
  currentInterestRate?: number
  clock?: Clock
}

interface GameBankService {
  openAccount(playerId: string, type: AccountType): BankAccount
  getAccount(accountId: string): BankAccount | undefined
  listAccounts(playerId: string): BankAccount[]
  deposit(accountId: string, amount: number, description?: string): BankTransaction
  withdraw(accountId: string, amount: number, description?: string): BankTransaction
  transfer(fromId: string, toId: string, amount: number): [BankTransaction, BankTransaction]
  listTransactions(accountId: string, limit?: number): BankTransaction[]
}

function createInterestService(bank: GameBankService, clock?: Clock): InterestService
interface InterestService {
  accrueAll(): void
  tick(dt: number): void   // daily accrual on interval
}

// Hono plugin
function bankPlugin(options: BankPluginOptions): HonoPlugin

Error codes

type BankErrorCode =
  | 'BANK_ACCOUNT_NOT_FOUND'
  | 'BANK_INSUFFICIENT_FUNDS'
  | 'BANK_ACCOUNT_LIMIT'
  | 'BANK_INVALID_AMOUNT'
  | 'BANK_TRANSFER_FAILED'

File layout

gaming/server/api-plugin-bank/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    error-codes.ts
    constants/index.ts
    types/common.ts
    types/common.md
    services/
      game-bank-service/
        game-bank-service.ts
        game-bank-service.md
        game-bank-service.types.ts
        game-bank-service.test.ts
        index.ts
      interest-service/
        interest-service.ts
        interest-service.md
        interest-service.types.ts
        interest-service.test.ts
        index.ts
    routes/
      accounts.ts
      accounts.md
      interest.ts
      transactions.ts
      config.ts
    plugin.ts
    plugin.md
  tests/
    integration.test.ts

Impact

Downstream: @suaveplan/react-bank and @suaveplan/api-plugin-virtual-currency build on this. Prerequisites: @suaveplan/error, @suaveplan/types, @suaveplan/economy, @suaveplan/events.