Security
What Aurora holds, and what it never sees
Written for whoever at your organization has to sign the software off. Everything below describes something that exists in the code — a migration, a route, a nightly job — rather than a policy we intend to follow. Two of the answers are uncomfortable and are here anyway.
No card numbers · No money held · No SOC 2 report, and we do not claim one
The short version
Four facts. The rest of the page is those four facts with their workings shown.
- Aurora never sees a card number. Stripe and PayPal host the checkout on their own domains and hand back a reference to a payment that has already happened.
- Aurora never holds your money. Stripe pays out to the bank account you connected and PayPal credits the balance you connected; there is no Aurora account it rests in on the way.
- Every row belongs to one organization, and Postgres enforces that rather than every query remembering to. A query that forgets returns nothing, not somebody else's donors.
- Photographs uploaded to a need can be read by anyone who has the file's URL. That one is worth reading twice, and the reason is two sections down.
What is public, and what needs a login
The question everybody is really asking, answered in one grid rather than spread over eight paragraphs.
| Detail | Anyone with the link | Your team, signed in |
|---|---|---|
| A live need's title, amount and photograph | Visible. That is what the widget is for — a supporter has to be able to read what you need without an account. | Visible, plus who gave and when. |
| The same need once it has been filled or switched off | Nothing. No title, no amount, no photograph, no story — only your organization's name, which whoever sent the link already had. | Visible in your own history, where it stays. |
| An uploaded photograph's file | Readable by anyone holding the URL. Deliberate, load-bearing, and explained below. | Only your team can upload one, replace it or remove it. |
| Donor names, email addresses and amounts | Not rendered on the widget, on a need page or in a link preview. The widget's public payload is built from a query that never touches the donations table. | Visible, and exportable to CSV whenever you want it. |
| Requests sent through your public forms, and the contact details on them | Not rendered anywhere public, at any point in their life. | Visible to your team until the erasure job reaches them. |
Why the photographs are the exception
Need images live in a bucket that anyone can read, and it has to be that way. The widget renders inside other people's websites, and email clients fetch images without signing in to anything. Put the bucket behind access control and you get a broken image everywhere the need appears — in the widget, in a shared link preview, in a newsletter that has already gone out.
So a photograph is exactly as private as its URL, and nothing else about it is protected. If the picture shows somebody your organization serves, treat uploading it the way you would treat putting it on your own homepage, because it is the same decision. Writing to that bucket is a different matter: only members of the organization named in the file's path can add, replace or remove anything in it.
How the separation is enforced
Four mechanisms. None of them is a convention somebody has to remember.
Isolation is a database rule, not a coding convention
Row-level security is on across the schema, so “this need, this donor, this donation and this file belong to one organization” is enforced by the database rather than by every query remembering to say so. Uploaded files are keyed the same way: your organization's id is the first segment of the storage path, and the write policy checks membership against that segment before it will accept anything.Two-factor cannot be enrolled and then quietly skipped
Two-factor is optional. The moment anyone on your team turns it on, the dashboard checks the session's assurance level before it hands over a single row and sends that account to the verification screen if the factor exists and has not been used. If somebody loses their authenticator, clearing it is something we have to do for them — there is no self-serve way round it.The widget cannot read the page it sits on
It is an iframe served from our domain, so your page's cookies, form fields and markup are not reachable from inside it — and the same wall works the other way round. The permission to be framed is granted on the widget route alone. Every other page in the product, dashboard and login included, is sent with headers that refuse framing outright.Switching something off switches it off everywhere
A filled or deactivated need stops rendering its title, its amount, its photograph and its story. The page does not 404 — that is a dead end for somebody who was sent the link on Tuesday and opened it on Thursday — it becomes a pointer to what you need now, and it asks search engines not to index it. The link preview is generated from the same check rather than from a stored copy, so a scraper that comes back gets the neutral card instead of the item.
What we erase on a clock
Retention nobody has to remember, and the precise limits of it.
Thirty days after a request sent through one of your public forms reaches a closed state — fulfilled, declined or expired — a nightly job nulls out the contact details on it. That is the email address and the phone number, and on a story submission it also includes the name of the person the story is about, which is the most sensitive field on the row and belongs to somebody who never filled the form in.
Two things about that job are worth stating plainly, because the useful version of a retention promise is the version with its edges on it.
It finds a row by its email address, and every submission made through Aurora carries one — the form marks it required and the API behind the form rejects a submission without a valid address, so a request cannot be filed anonymously and then sit unswept forever.
It only touches contact details.The requester's name, the team they named and the text of what they wrote are not erased on any schedule. Neither are donation and donor records: those are your financial records, and they stay for as long as you have an account.
What we are not claiming
The paragraph most likely to be quietly deleted in a year. It should not be.
We are not going to put compliance badges on this page that we have not earned. Aurora has not completed a SOC 2 audit.
PCI compliance for the card itself belongs to Stripe and to PayPal rather than to us — the reason there is no card data in our database is architectural, not certified, and those are two different claims that a badge would blur together.
If your board, your funder or your insurer needs a formal attestation before you can proceed, ask us. You will get an honest description of where we actually are, which may well be the wrong answer for you.
Reporting something you have found
Email support@auroradonate.comwith “Security” in the subject line. Tell us what you found and how to reproduce it. We will confirm receipt.
We will not take action against anyone who reports something in good faith and who does not read, change or delete other people's data while finding it. There is no bug bounty programme, and we would rather say so than let you assume one.
Put your first need in front of a donor
Create your account and build a widget for free. Free — Aurora takes nothing from any gift, and we ask your donors for an optional contribution instead — or $0.99 an update, with your donors never asked.
