IndieWallet
Privacy

What this app knows about you.

IndieWallet reads your royalty statements and adds them up. Your royalties never move through it: there is no bank connection, no account of yours it can reach, and no way for this app to send or receive a cent on your behalf. The only payment that will ever exist here is your own subscription, and Stripe handles that end to end — your card details go to them and never touch this server. What this app holds is your ledger and the settings that produce it.

Last updated 11 August 2026

Who runs it

One person. I'm Jackson Barone, an independent producer and artist. This is not a company, there are no staff, no investors and no analytics department. When you email about your account, I'm who reads it.

That cuts both ways, and this page says so where it matters: a single operator means your data is not being passed around, and it also means there is exactly one person who can reach it. That person is me.

What's in your account

  • Your entries — date, amount in US dollars, where it came from, which song or release, what kind of royalty, and your role on it.
  • Your catalog — song titles, releases, ownership splits, and any PRO registrations you track here.
  • Your projects and what they cost — studio time, features, artwork, mastering, ads.
  • Your column mappings — how a given distributor's spreadsheet lines up with the ledger, saved so the next statement takes seconds instead of minutes.
  • Your email address, and your display name if you gave one.

That's the list. There is no tracking pixel, no advertising identifier, no third-party analytics script, and no cookie on this site that isn't the one keeping you signed in.

Your password

Sign-in is handled by Supabase, and your password is stored there, hashed. It is never stored here and never written to any log.

But it does pass through this server on its way to Supabase, and I'd rather write that down than let you assume otherwise. The alternative design — the browser talking to Supabase directly — would have meant keeping a long-lived token in JavaScript where a script on the page could read it. The trade was made deliberately: the password crosses a server that already reads your books, so it isn't a new party learning a new secret, and in exchange the credential that lasts for weeks never touches JavaScript at all.

The import log — the part worth reading closely

IndieWallet recognises four distributors on sight. To teach it a fifth, I need to know what a fifth one's file looks like. The only place that information exists is in imports done by people who are not me.

So every import writes one record, and the rule that record is built under is this:

It records the shape of your statement. It never records what is in it.

What gets recorded

  • The column headings — "Sale Month", "Net Earnings", "ISRC".
  • How many rows and how many columns there were, how big the file was, and what its extension was.
  • What the app guessed the file was, how it guessed, and how confident it was.
  • Which column it treated as money, which column its own evidence pointed at, and whether those two agreed.
  • Which columns were ruled out as the money column and the fixed reason for each — "not numbers", "empty on most rows".
  • Whether the import worked, and if not, which of six ways it didn't.

What does not get recorded

  • Not a single cell from a single row. No amount, no song title, no artist name, no ISRC, no date.
  • Not the file's name. Distributor exports are often named after the person — SoundExchange_Statement_JaneDoe_Q2_2026.csv — so the name is dropped and only its length and extension are kept.
  • Not the text of parse errors, only how many there were. A parser complaining about a line tends to quote that line back, which would put a row of your earnings in by the back door.

Why you can believe that

Because of how it's built, not because I said so. The record is assembled from a list of named fields, one at a time — nothing copies an object wholesale, and nothing loops over an object's keys. The difference matters: the easy way to write this is to take what the importer already has and delete the dangerous parts, and that version is correct right up until someone adds a field upstream, at which point it leaks and nothing complains. This version can only ever record something new if a person adds it here, on purpose.

There is a second lock at the point of writing to the database, which refuses any record carrying a field that isn't on the list — refuses it outright rather than trimming it, because trimming would let a mistake through quietly.

And there is a test that takes every sample statement in the project, runs it through the log, and fails if any value from any data row comes out the other side. That test is itself deliberately broken and watched to fail, on a schedule, because a check that has never failed is a check nobody has evidence about.

The two exceptions, said plainly

Column headings can carry a name. Most are impersonal, but a label statement really can have a column called "Jane Doe Share", and that is a person's name sitting in the log. They're recorded anyway, because without the headings there is no way to teach the app a new distributor and the whole exercise is pointless. What I do instead of pretending otherwise is tell you here, and let you read back every record the app holds about your own imports, any time, from inside the app. Nothing about your imports is hidden from you.

The "this doesn't look right" box. If an import comes out wrong you can tell me so, and what you type is stored with that record. That is the only free text in the whole table, and nothing is stored there unless you deliberately write it. If you put details of your earnings in that box, they will be in the log — so don't, and you won't need to.

Who can see your data

The app connects to the database as a deliberately unprivileged account, and every table has a rule attached saying rows belong to the account that created them. Signed in as you, the app is not able to read anyone else's rows — not filtered out afterwards, not hidden by the interface; the database itself won't return them.

I hold a separate owner credential, kept apart from the running app, and that one can read everything. It exists because somebody has to be able to apply a schema change, restore a backup, and work out what went wrong when you write in to say something is broken. I use it for those things. No rule inside a database can constrain its owner, so I'm not going to claim one does — what I can tell you is that the honest reason it exists is support and repair, and that the import log was built the way it was specifically so that being able to read it doesn't tell me what you earn.

If you write in for help, assume I may look at your account to answer you. If you'd rather I didn't, say so in the email and I'll work from what you can tell me instead.

Backups, and where they land

There are two, and they are different in kind rather than duplicates of each other.

Supabase takes a daily one, automatically, and holds it themselves alongside the live database. About a week of them exist at any moment. This is the copy that gets used if something goes wrong with the database itself, and it is theirs to keep rather than mine to remember.

I take a second one, twice a day, onto my own computer. Every row is copied, read back, counted, totalled and compared against the original before the copy is called good. It writes plain spreadsheets as well as database files, which is the point of it: those open in Numbers or Excel on a machine with nothing installed, so they survive this app being abandoned in a way a database snapshot does not.

The second one is the least comfortable thing on this page and it is here rather than in a footnote. It means your data exists in a place that is a laptop, and a further place that is consumer cloud storage, rather than only on a hosting company's servers.

Precisely, because vagueness here would be the whole problem: the laptop runs full-disk encryption, so the copy on it is unreadable to anyone who picks the machine up. The cloud copy is in my personal iCloud Drive, which means Apple is holding a copy as well, under their terms and not mine. If that arrangement is not one you want your royalty history in, that is a completely reasonable position and I would rather you knew now than after.

Until recently the laptop copy was the only one, and it could fail quietly — it missed four runs in ten days when the machine was asleep at the scheduled hour, and nothing said so. Both halves of that are now fixed: Supabase's backup does not depend on my laptop being awake, and a failed run on the laptop now leaves a file on my desktop that stays there until a later run succeeds.

Other companies involved

  • Supabase — hosts the database and handles sign-in, password hashing and the emails for password resets. Your account and your ledger live there, and so does the daily backup described above.
  • Fly.io — runs the app itself. Traffic passes through it; nothing is stored there.
  • Spotify — when you use the catalog lookup to match your songs to releases and pull in artwork, the artist and song names you're searching for are sent to Spotify's public API. Nothing about your money is sent, and the lookup only happens when you ask for it.
  • Stripe — takes the payment if you subscribe, and is the seller of record for it, which means the charge on your statement is theirs and the sales tax is their responsibility rather than mine. They receive your email address and whatever billing details their checkout asks you for. Your card number goes straight to them and is never sent to, seen by, or stored on this server. What comes back here is four things and nothing else: two reference numbers that mean nothing outside Stripe's own systems, a word like "active" or "canceled", and the date your subscription next renews — which is there so the app knows when to stop letting you in, and for no other reason. Nothing about your royalties, your statements or your ledger is ever sent to Stripe.
  • Apple — not a part of the app, and listed anyway because the nightly backup above lands in iCloud Drive, which puts a copy of everything on Apple's servers. Leaving them off a list headed "other companies involved" because they are not an integration would be true by wording and false by any reading.

That's the whole list. Nobody is sold anything, nobody is given anything for advertising, and there is no arrangement under which your data is shared with anyone else. If that ever changes, this page changes first and you get an email — not a quiet edit and a new "last updated" date.

Getting your data out, and getting rid of it

Partly, right now, and this is the one place on this page where the app is behind what I'd like to be able to tell you. Two things export from inside the app today: any statement you imported, back out as a CSV, one import at a time; and the list of songs you haven't registered with your PRO yet. Everything else — entries you typed in by hand, projects, costs, ownership splits, goals, checklists — is in the database and nowhere else.

Until there's one button that hands you the whole lot, getting the rest out means asking me, and I'll send it in whatever format is useful without asking why you want it. I'd rather say that plainly than leave a sentence here about exporting everything that was nearly true. A ledger you can't get out of an app isn't really yours, and this is being built by somebody who has spent a career on the wrong end of that.

If you want your account deleted, email me and I'll delete it — the account, the ledger, the catalog, the import records, all of it — and tell you when it's done.

One honest caveat: backups already taken are fixed copies and can't have a single account surgically removed from them. They age out on their own. If that matters to you, say so when you write and I'll tell you exactly when the last copy holding your data expires.

This is a beta

IndieWallet is early and being tested by a small number of people who were asked directly. Things will break. When something goes wrong with an import I would genuinely rather hear about it than not — and the import log exists so that you can tell me without sending me your statement.

Reaching me

hello@indiewallet.app. There's no help desk and no ticket number — that address reaches the person who wrote the app, which is me.

Three things further up this page are promises to answer an email: deleting your account, telling you exactly what I hold about you, and telling you when the last backup containing your data expires. That is the address for all three. Say which one you want and I'll do it and tell you when it's done.