← All posts
Apps

Storing someone's documents without holding their data

By JDGX Labs · 12 August 2026 · 6 min read

BillNest is a vault for the paperwork behind the things you own — vehicle insurance, appliance warranties, service records, utility connections. Scans and photos of documents that matter.

Which makes it exactly the kind of app that should not be casually accumulating people's files on a server somewhere.

Where the files actually go

The obvious architecture is: user uploads a document, it lands in our storage bucket, we serve it back. Simple, and it makes us the custodian of a pile of other people's insurance papers and invoices.

We did something else. Attachments are copied into the user's own Google Drive, in a BillNest folder under their own Google account, counting against their own storage quota.

The app requests one Google permission for this: the drive.file scope. It is worth understanding precisely, because it is the whole point:

drive.file lets an app see and manage only the files it created itself. It cannot list, read or modify anything else in your Drive.

So BillNest can put a scan of your insurance certificate into your Drive, and read back the scans it put there. It cannot see your tax returns, your photos, or any other file. Not "does not" — cannot. The permission does not grant it.

We have no copy of those files and no way to reach them.

What we do hold

Being honest about this matters more than the marketing line.

The structured data — item names, registration numbers, policy numbers, service records, reminder dates — syncs to Cloud Firestore, isolated per account by server-side security rules. That is real data on our infrastructure and the policy says so plainly.

The primary copy lives on the device, in an app-private database, and the app works with no network connection at all. The cloud copy exists so your vault survives losing your phone.

The cost of the design

Here is where it stops being a neat architecture story.

When someone deletes their account, we cannot delete their Drive files for them.

If they delete from inside the app while it still holds Drive access, it cleans up the folder it created. But if they have already uninstalled and email us asking for deletion, the app is gone, the token is gone, and we have no reach into their Drive. Those files sit there until they remove them.

We had a choice: describe this vaguely and hope nobody asks, or say it outright. The deletion page says it outright — what is removed, what is not, and how to remove the rest yourself, with a link to the Drive folder and to the Google permissions page.

A privacy policy that only lists the reassuring parts is not a privacy policy. It is copy.

Two smaller decisions in the same spirit

The fields we deliberately did not build. BillNest has no field for Aadhaar, PAN, passport or any government identifier, and none for health records. Not "we handle them carefully" — they do not exist. That data carries a risk an ownership vault has no business taking on, and the cheapest way to protect something is to never collect it. An early version had a category that captured exactly this. We cut it before launch.

Item images. When an item has no photo, the app looks for a freely licensed illustration on Wikimedia Commons. To do that it sends a search term built from the item type — "Samsung refrigerator", "wireless router". That request carries no account identifier and nothing personal, and a photo you took yourself is never replaced by one. It is a small outbound request, and it is named in the privacy policy alongside the other three destinations, because a destination you do not mention is the one that gets you in trouble.

Architecture is a privacy decision

The thing worth taking away is that none of the above is a policy decision dressed up as engineering. They are engineering decisions that determined what the policy could truthfully say.

Choosing drive.file over full Drive access is a scope in a manifest. It is also the reason we can write "we cannot read anything else in your Drive" and have it be a statement about capability rather than intent.

Deciding not to build an Aadhaar field is twenty minutes of not writing a form. It is also the reason we never have to explain how we secure Aadhaar numbers.

You cannot retrofit either of those with a well-written policy. Decide them while the code is still soft.

← Back to the blog