Security
The Balancely pipeline is deliberately boring: process in memory, persist as little as possible, hash everything that needs hashing, and keep the auditable surface tiny. Here's the concrete posture.
Every uploaded PDF is processed in memory by the route handler and discarded the moment the workbook is built. We don't move files to object storage, we don't snapshot them in logs.
Lean storage mode: only the audit summary (filename, document type, totals reconciled, parser confidence) lives in the database. Individual transactions stay client-side.
bcryptjs at 10 rounds. The plaintext password never leaves the request body — it's hashed before insert. We can't see your password and we can't recover it.
Verification codes (6-digit OTPs) and password-reset tokens are SHA-256 hashed in the database. A database read alone can't verify an account or reset a password.
iron-session AES-256 encrypts the cookie with a 32+ char secret. HttpOnly and SameSite=lax. No session is stored server-side — the cookie itself is the session.
OTPs expire after 10 minutes and self-invalidate after 5 wrong attempts. Reset links expire after 60 minutes and consume on first use. Issuing a new code invalidates the previous one.
Our OAuth state parameter carries an HMAC-SHA256 signature with the session secret and a 10-minute TTL. Callbacks that don't verify are rejected before any token exchange.
PDFs are sent to the parser as binary inlineData, never spliced into the system prompt. A malicious PDF can't talk to the model.
Common questions
No. Statements pass through Statement AI for parsing only; the file and its contents are not retained after the parse completes. Our processing agreement with the underlying model provider excludes your data from any training program.
Compute and database both run in the US East region for low parser-to-database latency. We can move regions for enterprise plans on request.
The Danger Zone in /dashboard/settings will permanently remove your user row and all audit-log entries. The button is currently disabled while we finalize the account-deletion flow.
Reconciliation catches it. The reconciler sums the parsed transactions per bucket (payments, returns, charges, interest) and compares to the totals printed on the statement. Anything off by more than 2¢ flags the workbook as unreconciled.
Server-side: filename, file size, parser used, parser confidence, reconciliation result, timestamps. No transaction descriptions or amounts. Logs go to Vercel and (optionally) Sentry — both private.
We process limited personal data (your email + a display name) under contract for the purpose of providing the service. No marketing email use, no third-party sale, no analytics on statement contents. Privacy contact: privacy@balancely.ca.
Email security@balancely.ca with reproduction steps. We respond within one business day for verified reports and credit researchers in release notes.
In scope
Out of scope
Want the full privacy story? See our Privacy Policy and Terms.
Get started