Its host cache is busted by every write here; wire it with the same valkeyClient.
null for apps that never call update.
Protected ReadonlydbStaticinstanceThe process default: built from each dependency's own instance().
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. The bank's dashboard workspace is created with it; a dashboard
domain opens the dashboard unless dashboardEnabled says otherwise.
Finds or creates the bank a provider's accounts receive deposits at and
fills the rail templates it lacks, per planProviderBank. A new bank
gets its workspace with the dashboard off. A second call writes nothing.
Linking a program to the bank is the caller's, through ProgramAdminService.
What ensureProviderBank would write, without writing it. The bank is
programBankId's when the program names one, else the oldest bank with the
receiving bank's routing number, else a new one under a slug derived from
its name. rails holds only the rail templates that bank lacks; one an
operator already set is never in it. A routing number that fails the ABA
checksum is refused here, so a dry run reports what a write would.
Search banks — always paginated, pageSize defaulting to 50, ordered by
name unless orderBy says otherwise. total is a count(*) OVER ()
window over the full filtered set and hasNext the limit(pageSize + 1)
sentinel, so the bank is a first-class entity selector alongside customers
/ organizations / identities. q is a free-text match over the bank name +
slug (externalId).
A caller that wants every match pages through with searchIterator, or
bounds the page to what it asked for ({ ids, pageSize: ids.length }).
There is deliberately no "omit the page size to get everything" mode: the
cap it hides is invisible at the call site and only bites once the table
outgrows the default.
OptionaldashboardDomains?: string[]OptionaldashboardEnabled?: booleanOptionalids?: string[]OptionalorderBy?: DbOrderByCriterion<Optionalpage?: number1-based page; defaults to 1.
OptionalpageSize?: numberOptionalq?: stringUpdate 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.
dashboardDomain, dashboardEnabled and theme are the workspace row's:
a call naming only those writes nothing on bank. Giving a bank its first
domain opens its dashboard, and clearing the domain closes it, unless
dashboardEnabled is passed.
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,greendot) 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.