Create a new bank. The slug (id) is the public-facing identifier and
must match ^[a-z][a-z0-9_-]{1,31}$ to keep it URL- and grep-friendly.
Returns BANK_ALREADY_EXISTS if a bank with the same slug is already
onboarded.
Resolve the bank whose dashboardDomain matches domain (normalized to
trimmed lowercase — the column is stored that way). The column is unique,
so this is a 0-or-1 row lookup. Returns null for an unknown host. Cached
per-host (keyed by the normalized domain), self-busted on create/update of
the owning bank's domain (both old and new host).
Slugs of every bank that has a dashboardDomain set — the apex "all
dashboard-configured banks" set. Banks without a dedicated host (e.g.
treasury-only banks) are excluded unless an operator configures a domain.
Cached under a single key; self-busted on any create/update that changes
a bank's domain membership.
Banks supporting rail, i.e. whose matching instructions column is
non-null. Ordered by name. This is the runtime membership replacement for
the old hard-coded per-rail bank-id arrays.
Update mutable fields on a bank. Pass null for nullable fields to
clear them. Omitting a field leaves it untouched. The slug (id) is
not editable — references across the system store the literal slug.
Admin-tier read + write over
bank. Operators onboard new partner banks here; the DB row set is now authoritative (the historical compile-timeBankIdliteral union is retained as a string alias for self-doc, not as a constraint).Bank-shaped vendors (
dart,fib) get special-case behavior across services — seeBankVendorindb/drizzle/schema/product_vendor.ts. New banks created here arrive without that pairing and stay non-bank from a route's perspective unless someone wires up a corresponding vendor entry separately.