Goal Evidence Engine
Security
Goal Evidence Engine holds care records about people with disability. This page says how it is built, what is tested, and what is not finished. The last part is the part worth reading.
The app is a single web application. There is no separate mobile app to keep patched. Workers add it to the home screen on their phone and it behaves like an app from there.
Every screen and every action runs on the server. The phone holds no keys and talks to no other company. When there is no signal, notes are kept on the phone and sent when it comes back.
The application runs in Sydney. The database is in Sydney. Records do not leave Australia except for the report drafting described below and on the privacy page.
Every record carries the organisation that owns it. Every read and every write in the application filters on it, and the organisation is worked out on the server from who is signed in. It is never taken from the address bar, from a request body or from a token, because all three can be edited by whoever holds them.
The database also carries membership policies as a second layer. We will not tell you those policies are what keeps two providers apart, because the application connects with an account that bypasses them. The boundary that runs in production is the application code, so that is the thing that gets tested.
How it is tested. A database test suite of at least 121 assertions signs in as a user of one organisation and asserts they get zero rows of another organisation's data, on every table that holds any. A separate check reconciles every record in every such table against its owning organisation and fails on a single stray row. Both run on every change, alongside at least 201 browser tests that drive the real app and at least 893 unit tests. Those are floors a build is not allowed to drop below, so the real numbers are higher. A change that opens a hole between two providers fails a test rather than reaching anyone.
A submitted shift note cannot be edited, by anyone, including us. Neither can a link between a note and a goal. The database refuses it, not the application, so there is no route and no screen that can get around it. A mistake is corrected by adding a correction, so both stay visible. The one deletion path is clearing a provider's whole workspace at their request, which needs an administrator account and a second code. Single notes cannot be deleted at all.
Every quote shown as evidence for a goal is checked, character by character, against the note it came from before it can exist. A claim the check cannot back is held out of the report the worker copies. That check proves the words are really there. Whether they show real progress is a human call, which is what the review step is for.
Who approved a report, and when, cannot be rewritten once it is recorded. Who opened which participant record, and when, is logged and cannot be edited.
The draft narrative of a shift report is written by Anthropic's model, in the United States. Four things bound it.
Report writing can be switched off from a phone in under two minutes without stopping anyone from recording a shift.
Read this one carefully. The database provider takes a daily backup and keeps seven days of them. A script takes a separate encrypted copy off that provider entirely, because a deleted project takes its own backups with it, and that script is run by hand rather than on a schedule. That last part is the weak one, and it is being fixed rather than described away.
Point-in-time recovery is not enabled. It would bring the worst case down from about a day to a couple of minutes. It is a paid add-on that replaces the daily backups rather than adding to them, and it is not switched on, so the worst case stands: if this database ever has to be restored from a backup, up to a day of shift notes is gone. That is the number to plan around, and it is why a worker's phone keeps an unsent note until the app confirms it is saved.
Last restore drill: none has been run. There is a written, repeatable restore procedure. It has not been run end to end with a stopwatch, so there is no recovery-time figure on this page. When the drill is run, the measured number goes here and into customer contracts. Until then we would rather publish this sentence than a number nobody measured.
Everyone who touches customer data, what they do, and where they are.
| Subprocessor | What they do | Location | What limits it |
|---|---|---|---|
| Supabase | The database, the sign-in service and the audit tables. Every note, report and goal is stored here. | Australia (Sydney, ap-southeast-2) | This is where the records live. They are not copied to any other region. |
| Vercel | Runs the application itself. Handles each request and renders each screen. | Australia (Sydney, syd1) for the application. Static files are served from a worldwide network. | Notes and reports are not stored here. They pass through in memory while a request is served. |
| Anthropic | Writes the draft narrative of a shift report from the worker's own recorded notes. | United States | This is the one place your content leaves Australia. See the section below, which states it plainly rather than burying it. |
| Upstash | Counts requests, so that one account or one address cannot flood the app or burn the shared sign-in code budget. It holds counters and the identifier each counter is against: a user id, an organisation id, an email address on the sign-in path, and the network address a request came from. | The region this project's counter store was created in. | No note, no report, no goal and no participant record is in it. Counters expire on their own within the window they pace. It is not a copy of anything. |
We will tell customers before adding a subprocessor that will hold their content, so they have a chance to object.
Customers are told within 48 hours of us becoming aware of any actual or suspected security incident affecting their data. We give them what they need for their own assessment: what happened, what kinds of information were involved, what we have done and what we recommend.
The decision about whether to notify individuals and the Information Commissioner is the provider's, because the records are theirs and they are the ones with the legal duty. We support that decision. We do not make it for them and we do not delay it.
There is a written incident procedure covering severities, who is called, the switches that stop things quickly, and how to roll back a bad release.
A security page that lists only good news is not worth reading. As at the date below:
Each of these is a decision with a cost attached rather than an oversight, and each one moves as the product does. Ask and we will tell you where any of them stands today.
If you find a security problem, tell us and we will not come after you for looking. Write to the Privacy Officer at xmbraithwaite@gmail.com with enough detail to reproduce it. We will acknowledge it within two business days and tell you what we are doing about it.
Please do not access, change or keep anyone else's data while you are testing, and please give us a chance to fix it before you publish.
WCAG 2.2 AA is what we build against. We do not claim to have met it, because no one has audited the whole product against it, and a target is not a result.
What is built, and checked by the test suite on every change: every screen can be reached and operated from the keyboard, and each one starts with a link that skips past the navigation to the content. Every screen marks its main area, so a screen reader can jump straight there. A field that is refused says so through its own control rather than in a message that merely sits near it. Text is checked against a contrast ratio of at least 4.5 to 1 on the colour actually behind it, read from the rendered page rather than from the palette. Anything that moves holds still for a reader whose device asks for less motion. Controls you tap are at least 44 pixels on both sides.
If something here gets in your way, write to the Privacy Officer at xmbraithwaite@gmail.com and say what you were trying to do and what happened instead. A barrier is treated as a bug, not as feedback.