@fayz-ai/plugin-banking-br
v0.10.12
Published
[experimental] Fayz SDK — Brazilian open-banking connector (Tecnospeed PlugBank) feeding the financial ledger
Readme
@fayz-ai/plugin-banking-br
Brazilian open-banking connector. Syncs a bank statement into the SDK financial ledger and drives reconciliation (conciliação). Provider: Tecnospeed PlugBank.
Graduated from the app-local incubator, where it lived duplicated byte for byte
in beauty-saas and agency-os. Further provider drivers (Inter, Belvo, Pluggy)
go behind the same connector shape.
Install
import { createFinancialPlugin } from '@fayz-ai/plugin-financial'
import { createOpenBankingPlugin } from '@fayz-ai/plugin-banking-br'
plugins: [
createFinancialPlugin({ modules: { reconciliation: true } }),
createOpenBankingPlugin(),
]Addon scope: it contributes a connector into its host (plugin-financial) and
surfaces under Financial → settings → Integrations. No left-nav entry of its own.
What it owns
- DB: none of its own — the connection is a
plg_connectionsrow and the history isplg_sync_runs(migration003_onto_connections). The legacybank_integrations/bank_integration_sync_logtables still stand on the live pool (with a plaintextapi_token) until FAY-1360 retires them. - RPC:
plugbank_import_movements(p_payload jsonb)— the door the import passes through. Takes the tenant from the integration row, never from the request body, and is idempotent on the financial plugin'suq_plg_financial_movements_externalindex. - Edge function (declared in
functions[], deployed by the app):plugbank-sync— calls the PlugBank API, normalizes lines, imports through the RPC intopublic.plg_financial_movementstaggedexternal_source='plugbank'. - Fact:
financial.movement.imported, emitted by a trigger on the ledger so it exists whoever wrote the row. - UI: connect/disconnect, fetch a statement, import selected lines, run history.
Where the credential lives
Today (verified 2026-08-12): still in the pool. The live pool's
bank_integrations.api_token holds the PlugBank token in plaintext — migration
002, which drops the api_token / cnpj columns 001 created, is in this
repo but unapplied there, and the deployed plugbank-sync (v6) still reads the
column. The destination is the Fayz platform's encrypted store, redeemed by the
edge function per call — that move is FAY-1360, and the redeem path it needs is
FAY-1389. The reason the columns must go: bank_integrations is read from the
browser under tenant RLS, so any member of the tenant can read them — and a pool
is one Supabase project serving N tenants, so anything there holding
service_role reads every tenant's at once.
If a pool ever stored those values, rotate them. DROP COLUMN is a catalog
change; the old bytes leave the heap only at the next table rewrite.
How it composes with the SDK
- Depends on
@fayz-ai/plugin-financial. Imported lines are reconciled in Financial → Conciliação, which is the SDKReconciliationViewenabled viacreateFinancialPlugin({ modules: { reconciliation: true } }). - The matching model + columns (
external_id,external_source,reconciled_at,matched_movement_id) live in the SDK financial migration007_reconciliation.sql.
Deploy
- Apply the SDK financial migration
007_reconciliation.sql, the core027_domain_events.sql(it shipsplg_emit_event), then this plugin's001_openbanking.sqland002_credential_and_facts.sql. supabase functions deploy plugbank-syncwith secretsPLUGBANK_BASE_URL, plus the standardSUPABASE_URL/SUPABASE_SERVICE_ROLE_KEY. The per-tenant token is not a function secret: a secret is per-pool and a pool serves N tenants with N different bank accounts.- Register
createOpenBankingPlugin()in the app config and enable the financialreconciliationmodule.
The period picker in the import panel is deliberate, not a missing feature — whoever reconciles wants to choose the window. Scheduled pulls belong to the Fayz SCHEDULE worker (FAY-1347), which owns the clock for every connector.
