Security
Last updated: September 2, 2026
This page describes what ROE Engine actually does to protect your account and your portfolio data. Each item below is a measure that is in place today, not a plan. Where we have nothing to claim, we say so.
Passwords
Passwords are hashed with bcrypt at a work factor of 12, and bcrypt generates a distinct salt for every password, so two accounts that happen to choose the same password produce different stored hashes. We never store your password, and we cannot recover it — a reset issues a new one. New passwords must be at least 8 characters and include an uppercase letter, a lowercase letter, a number, and a symbol.
Two-factor authentication
Two-factor authentication is optional and uses a standard TOTP authenticator app. Your TOTP secret is encrypted with AES-256-GCM before it is written to the database, using a key that is held in an environment variable rather than in the database itself, so a copy of the database alone does not yield working secrets. Recovery codes are stored as SHA-256 hashes, and that list of hashes is itself encrypted with the same scheme; a recovery code is consumed the first time it is used. Neither the secret nor the recovery codes are ever stored in plaintext.
Sessions
Signing in issues a signed session token stored in an HTTP-only cookie; the signature means the contents cannot be altered in your browser. Every session records when it was established, and we record when your password last changed. Any session that predates the most recent password change or reset stops working immediately — so changing your password signs out every other device. The same marker is set when an account is deleted, which ends its sessions at once.
Data in transit
Every connection to ROE Engine is over TLS, both from your browser to the application (hosted on Vercel) and from the application to the database (hosted on Supabase). We send a Strict-Transport-Security header with a two-year lifetime that covers subdomains, which tells browsers never to attempt an unencrypted connection to us again. We also send a Content Security Policy that restricts which scripts, styles, frames, and outbound connections a page may load, along with clickjacking, MIME-sniffing, referrer, and permissions headers.
Data at rest
- Your portfolio data lives in a PostgreSQL database hosted by Supabase, which encrypts storage volumes at rest (see Supabase's security page).
- Row-Level Security is enabled on every table in the database. The application connects directly as the database owner and does not use Supabase's auto-generated data API; enabling row-level security with no policies attached means that API can serve nothing at all, even to a caller holding a project key.
- Owner statements and P&L PDFs you upload are stored in a private storage bucket, filed under your own user ID. They are never publicly readable: viewing one generates a signed link that expires 60 seconds after it is created.
- ROE Engine never connects to your bank, brokerage, or credit accounts. There is no such integration in the product, so there are no banking credentials for us to hold.
Payments
Card details never touch our servers. Subscriptions are started through Stripe Checkout and managed afterwards through the Stripe Billing Portal, both of which are hosted by Stripe — you enter your card on Stripe's pages, not ours. We store only the identifiers Stripe gives us for your customer and subscription, plus your plan and its renewal date.
Third parties that process your data
Four services see your data in the course of doing their job. The Privacy Policy lists every provider we use, including those that only receive a property address, anonymous page views, or nothing at all.
- Anthropic — owner statements and P&L documents you upload are sent to Anthropic's Claude API to extract the transactions from them. Anthropic does not use API inputs to train its models and retains them only as needed to provide the service (see Anthropic's commercial terms).
- Resend — delivers the email we send you: verification and password reset links, alerts, your portfolio digest, and anything submitted through our contact form.
- Sentry — receives error details (the message, a stack trace, and the request) when something breaks, so we can diagnose and fix it. While you're signed in, errors captured on our servers are also tagged with your account id, never your email or portfolio data. Screen recording (Session Replay) is wired into our setup but set to record zero percent of sessions — none has ever been captured.
- Upstash — holds the counters behind the rate limits below. It stores request counts keyed by IP address or account, not your portfolio data.
Rate limiting
Sensitive endpoints are rate limited so that a stolen password list or a script cannot be tried against them at speed. The limits cover signing in, registration, password reset and password change, email verification and resending it, two-factor setup and code entry, the contact form and newsletter signup, statement uploads, the AI advisor, account export and deletion, and every administrative action including account impersonation. Exceeding a limit returns a 429 with a retry time rather than a hint about whether the account exists.
What we don't claim
ROE Engine holds no SOC 2 report and no ISO 27001 certification. We follow the practices described on this page; we have not completed a third-party audit. If a certification is a requirement for you, we would rather you know that now than discover it later.
Reporting a vulnerability
If you believe you have found a security issue, email info@roeengine.com with enough detail to reproduce it. Please give us a reasonable opportunity to fix the issue before disclosing it publicly, and please don't run tests that degrade the service or touch other people's accounts. We read every report and will tell you what we found.