Security

What we hold, what we cannot see, and the one place that stops being true.

Your receipts stay in your own cloud account.

We built this so that we hold as little of your material as possible. Here is exactly what that means, including where it stops being true.

Your storage, your keys

When you connect Dropbox or Google Drive, the access key is stored on your device, in the same secure store your passcode uses. It is never sent to us. We cannot list, open or delete anything in your account.

No overnight jobs

A consequence of the above: everything happens while the app is open. There is no server quietly reaching into your files at 2am, because there is nothing on our side that could. The monthly export email is something you send, not something we schedule.

Hosted storage is encrypted before it leaves

If you choose our hosted option instead, files are encrypted on your device first. We store the encrypted result and cannot read it. You get a recovery code at signup — save it, because it is the only way back in if you forget your password.

What we do hold

Your email address, your expense records if you are signed in, your category corrections and your form template mapping. That is the list.

Where this stops

Reading a receipt needs a model that we pay for, so the photo passes through our server on its way there. It is held in memory for the few seconds that takes and never written to disk, and it is not logged. The reading service does not use it for training. If that trade is not one you want, the app is the wrong tool — and we would rather say so here than have you find out later.

How that is enforced, not just promised

One endpoint sees a document

POST /api/extract takes bytes, returns fields, and keeps nothing. There is no database call on that path, no file written, and the error handler deliberately discards the caught error rather than logging it — because an HTTP client’s error object can carry the request body, and the request body is your receipt.

The key cannot be on your device

Reading a receipt needs a model we pay for, and an API key cannot sit in an app somebody can unpack. That is the whole reason a backend exists here. It is also why the extraction client lives in a server-only module: the boundary is enforced by the build, not by remembering.

Your password is not ours to lose

Signing in is handled by Clerk, a company whose whole job that is. Zilda never sees your password, never stores a hash of one, and has no session table to steal — it keeps only which workspace you are in. The reset link, the verification mail and two-factor are theirs too, which is the point: those are the parts that are easy to get subtly wrong.

Storage tokens are on a different side of the wall

Nothing in the backend can reach your cloud account, because nothing in the backend has ever been given a way to. The consequence is the honest one: no overnight jobs, no scheduled export email, and reconnecting storage if you lose a device.