← Isomoira

Security

Last updated 7 September 2026

This is our threat model, in plain words: what we hold, who might want it, what stands in their way, and where the limits are. It names mechanisms rather than reaching for “bank-level”, because a claim you can check is worth more than one you cannot. Where something is not finished, it says so.

The short version

Your partner sees exactly what you chose to share, and nothing you did not. Our servers enforce that, not the app, and a suite of tests tries to break it on every change we make.

Merchant names, account names, notes, comments and payment handles are encrypted with a key that belongs to your household. Amounts, dates and categories are not, so the app can add them up.

We can read what the app can read. This is server-side processing, not end-to-end encryption, and we would rather say so than imply otherwise.

What we hold, and how it is stored

Everything the service keeps about a household, and the form it is kept in. “Encrypted” means encrypted with that household's own key before it is written to the database; “plain” means stored as ordinary values.

DataWhy we hold itHow it is stored
Your Apple sign-in identifier and display nameIdentity; the name your partner sees on an expensePlain
Transactions: merchant, descriptor, memoClassification; the record itselfEncrypted
Amounts, dates, categories, account types, privacy tiersBudgets and the ledger; the database has to add them upPlain numbers
Account names and last four digitsThe connection list and the privacy sheetEncrypted
BalancesSafe-to-spend; the Balance-only tierPlain numbers
Bank access tokens from PlaidPulling transactionsEncrypted separately, in our key service, never under a household key
The ledger: who paid, how it was splitWho is aheadPlain numbers and identifiers; it holds no text at all
Budgets and which expense went in which bucketPlansPlain labels
Notes, comments, and Venmo or Cash App handlesWhat you typed for yourself or your partnerEncrypted
App Store transaction recordsWhether the household has a subscriptionPlain
Push tokens and App Attest key identifiersBackground sync; proving requests come from a genuine copy of the appPlain identifiers
Settlement pages you chose to shareThe page itselfEncrypted; the link's address is stored hashed
The change feed each device downloadsKeeping your devices in stepEncrypted per household
The audit logSign-ins, tier changes, invites, exports, deletions, links created and revokedIdentifiers and outcomes only

Not held, anywhere: your bank credentials (Plaid handles them in its own interface; we receive an access token), card numbers (Apple), passwords (none exist), your email address (Sign in with Apple's relay address is not kept), your location, your contacts, or anything else from your phone.

How the privacy firewall works

The person with the most motive and the most context to look at your finances is your partner. That is the product's core threat, and the design starts there.

A red-team suite runs in our build pipeline on every change and will for as long as the product exists. It tries to fetch a hidden account, leak a private amount through a subtraction, reach across households, defeat the delete instructions after a tier change, find residue after someone leaves or deletes, and carry a private row out through a partner's export. If any of those succeed, the build fails and nothing ships.

Who we defend against, and how

Someone with your phone

Your sign-in tokens live in the iOS keychain, available only after the phone has been unlocked once since restart and only on that device. The app's local database is a rebuildable cache under iOS file protection; it is excluded from iCloud and Finder backups, so your financial rows never travel through Apple's backup pipeline, and a restored phone simply downloads them again. You can require Face ID to open the app. The app blanks itself in the app switcher and whenever the screen is recorded, mirrored or shared to another display. Widgets carry derived numbers only, and the lock-screen widget says “Looking good” unless you opt into amounts. Signing out on any device, or asking us to, revokes the session on the server, not just on the phone.

Someone on the network, or holding your credentials

A stolen database or backup

Every household has its own AES-256-GCM key. That key is itself wrapped by a per-household key in a separate key service, so a copy of the database contains ciphertext and no way to open it. Each encrypted value is bound to its own household, table, column and row: move a ciphertext to another row or another household and it fails to decrypt. The change feed is encrypted the same way. Backups are encrypted on our servers before they leave, the company storing them cannot read them, a restore is rehearsed every week, and copies age out within thirty days.

What an attacker holding the database alone would see: amounts, dates, categories, account types, and who paid; not merchants, account names, memos, comments, or who you are beyond an Apple identifier and a first name.

A compromised server

This is the honest limit. The running application decrypts what it needs to serve you, so a full compromise of the running box, its memory and its key-service credentials together, exposes the data of households active during the compromise. What contains that: the keys live in the key service and its unseal material is never on the box; every query the application makes is scoped to one member's household by construction, and a second wall in the database itself refuses rows from any other household even if a bug asks; an outbound firewall allows the server to talk only to Plaid, Apple and its own package mirrors, so a compromised process has nowhere to send anything; and the first lever in our incident runbook is a kill switch that stops the service within seconds while we assess and rotate.

A modified copy of the app

The server trusts nothing computed on a device. The ledger, the settlement page, the subscription check and the privacy policy all run server-side; the app's own arithmetic is held equal to the server's by shared test fixtures both run in our pipeline. Requests are bound to a strict list of accepted fields, every command carries an idempotency key so a replay does nothing twice, and the sensitive routes require App Attest as above.

Plaid and Apple

Plaid's interface handles your bank credentials; we hold one read-only access token per institution, encrypted in the key service. We remove that token, and with it our access, when you disconnect an institution, when a subscription has been lapsed for 30 days, when you leave a household, and when you delete your account. Messages from Plaid and Apple are verified against their signatures before we parse them, and a replayed message applies once.

Us

We can read what the application can read. We do not, except to help you at your request, and the audit log records every export, deletion, tier change and link operation. Our application logs pass through a filter that permits identifiers and outcomes only; merchant names, balances, tokens and payloads have no way into them. There are no third-party analytics or advertising SDKs, and no data brokers. Your export is exactly what your device receives. Deletion is real: a solo household is erased from every table, and a test asserts zero rows remain; when one member of a couple deletes, their name and every string they typed are erased while the shared amounts stay with the partner. Backups age out within thirty days.

What we can see, plainly

Running normally, our servers can decrypt your merchants and account names in order to send them to your devices. That is what server-side processing means. We chose it over a design in which the server could see nothing because the settlement ledger, budgets and preview-as-partner need a server that can compute over your rows, and because a very small company can run one well-hardened service honestly. We tell you the consequence instead of hiding it behind a phrase.

Trade-offs, stated

What is not finished

How we check ourselves

Every change runs the full test suite, including the red-team probes above, a dependency vulnerability scan, and a scan of the server image before it can deploy. An architecture test fails the build if any database access exists that is not scoped to a member. The same JSON fixtures are run by the app and the server, so their arithmetic cannot drift apart. A restore from backup is rehearsed every week. We do not hold a SOC 2 report or an external penetration test and do not claim to; this page and the tests behind it are the claim.

Reporting a security issue

Email hello@isomoira.com with “Security” in the subject. We acknowledge within 72 hours, keep you informed while we fix it, and credit you if you would like. We will not pursue good-faith research conducted against your own household's data. Please do not include anyone else's data in a report.

Contact

Questions about any of this: hello@isomoira.com. What we collect and your rights over it are at isomoira.com/privacy; the agreement that governs the service is at isomoira.com/terms; help with the app is at isomoira.com/support.