Bank access
Read-only, through an aggregator
Bank connections go through Plaid. You authenticate with your bank inside Plaid's own flow — we never see or store your bank credentials, and we hold no ability to move money. We request transaction data only; the access is read-only. Today that integration runs against Plaid's sandbox while we complete production access, so a live connection is not yet available.
Encryption
Encrypted in transit
Every connection — browser to app, app to database, app to the accounting engine — is TLS-encrypted. Our database provider encrypts data at rest on its managed infrastructure. Where a connector requires a stored API token, we encrypt it with AES-256-GCM using a key held only in the server environment, and if that key is not configured we refuse to store the token at all rather than keep it in the clear.
Isolation
Row-level security in Postgres
Your data lives in Postgres with row-level security enabled on every table that holds it. The policies scope each row to the account that owns it, enforced by the database rather than by application code — a query that forgets to filter still returns nothing that isn't yours.
Audit trail
Append-only by construction
Rule versions are append-only: editing a rule creates a new version with provenance, and a database trigger blocks UPDATE and DELETE on the old one. Imported source records are write-once — the trigger refuses an edit even from our own service credentials. Postings are insert-only and the database rejects one that carries a failed review or that doesn't balance.
Isolation
The re-derivation never reads your ledger
When we reproduce your month from the bank rows, your general ledger is not an input. It is opened once, afterwards, only to compare against. That is provable rather than promised: there is a test that runs the engine with the ledger removed and asserts identical output. It matters because next month there is no ledger, and a re-derivation that quietly leans on one is a demonstration rather than a close.
Control
A human approves every posting
The engine drafts; it never posts. An independent check re-derives each entry and a failed check blocks posting entirely. The posting itself is an explicit action recorded against the person who took it, alongside the rule version that produced the entry. AI is used to help author rules in plain English — never to compute or book a number.
Accounting system
QuickBooks is read-only, by construction
The QuickBooks client has one function that makes a request and it is a GET. There is no create, no update, no delete, no batch — nothing posts to QuickBooks, ever, because there is nothing there to call. A test fails the moment that stops being true, and disconnecting deletes the stored tokens rather than marking them revoked. The connection runs against an Intuit sandbox while their app review is under way, so it is not open to accounts yet; a file export is the way in until it is.
Secrets
Never in the browser
API keys and service credentials are read from the server environment and never reach the client bundle. The browser never talks to a bank, to our accounting engine, or to a model provider directly — every such call is made server-side.