Security and data handling
Where your audio goes, what is kept, who can read it, and what happens when you want it gone. Written from the code, not from a template.
Draft, pending legal review
This page describes how the system behaves today, written from the code rather than from an aspiration. It has not been through legal review, and the product changes. If a detail here matters to your decision, ask us and we will confirm it in writing against the current build.
Content last checked against the application source: 28 July 2026.
Where the audio goes
You record in the browser. The audio is sent to our server, which passes it to a speech-to-text provider, gets text back, and returns the text to you. Then it is done with: we do not store the audio. There is no audio bucket, no audio column in the database, and no recording history to browse.
- One primary speech-to-text provider. Long recordings are split into chunks with a small overlap and reassembled on our side.
- One fallback provider, used only when the primary returns a rate-limit or server error. Authentication and validation errors do not trigger the fallback; they surface as failures, so a misconfiguration cannot silently reroute your audio.
- Worth knowing, because most vendors do not say it: on the fallback path the audio chunk is uploaded to the fallback provider's storage to produce a URL their transcription service can fetch. That is their storage, under their retention, not ours.
- Before it listens, the transcriber is given a vocabulary prompt built from your department's identity and local place names, so local spellings come back right. That prompt contains place names, not incident content.
Where the text goes
The transcript is sent to an AI provider that runs the model turning it into structured NERIS fields. We send the transcript and a prompt; we get structured data back. We do not fine-tune a model on your data as part of that call.
We do not publish which speech-to-text and AI vendors we use; which engines to run, and how, is part of what you are paying us to get right. All of them are established US-based providers, and if your department needs the current names for a data agreement, ask us directly and we will share them.
What is stored, and where
Supabase Postgres. What lives there:
- Reports, including the raw transcript of what you said. That transcript is the evidence for what is in the report, and deleting it would make a filed federal record unverifiable, so it is kept with the report.
- Roster: names and roles of members, plus a PIN hash for officers and admins. PINs are hashed with bcrypt and a server-side pepper that is never stored in the database, so a database dump on its own does not yield PINs.
- Attachments (photos you add to a report) in a private storage bucket. There are no public read policies on it. Uploads go direct from your browser using a one-time signed URL our server mints; downloads are signed links. The shipped browser key cannot list or read the bucket.
- Anonymous trial drafts in a separate table with a separate lifetime (see below).
Who can read a report
- Every one of those tables has row-level security enabled with zero policies, which in Postgres means deny-all, and the grants for the public browser key are revoked. Nothing is readable straight from the browser; every read goes through our API.
- The API derives your department from your session on the server. It never takes a department id from the request body. That is the difference between "scoped" and "scoped until someone edits a request".
- Membership is re-read from the database on every request, so deactivating someone takes effect on their next action rather than when their token happens to expire.
- Sessions are short where it matters: officer and admin sessions expire after 12 hours; a firefighter's lasts 30 days, because the alternative is a login screen at 3am on a personal phone.
- On a shared station tablet, sessions are per-tab and are not shared between people using the device.
- Our own staff can technically reach the database; anyone honest about a hosted product will tell you the same. There is no engineering control that would let us claim otherwise, so we do not claim it.
The anonymous trial
If you record without an account:
- The draft is stored in a different table from any department's records. It is not in any department's dashboard, export, review queue, or statistics.
- It is deleted after 30 days unless you sign in and claim it. That is enforced by a job that runs daily and deletes the rows, not by a column nobody acts on. Reads also filter on the expiry, so an expired draft is invisible even in the hours before the job runs.
- It cannot be filed to NERIS. Not "is not"; cannot: the submit path only reads the department reports table, and an anonymous draft is not in it.
- It is excluded from training data. The endpoint that writes training examples requires a real department membership, which an anonymous caller cannot obtain. A test in our suite scans that file and fails the build if someone adds an anonymous branch to it.
- Your browser's anonymous id partitions drafts but does not authorize them. Reading a draft back also requires a secret key the server mints and stores only as a hash, in a cookie your browser cannot read from JavaScript. Someone who learns your anonymous id gets nothing with it.
The privacy policy states all four of those in full.
Deletion
- Anonymous trial drafts: deleted automatically after 30 days, as above.
- Attachments: can be deleted from a report.
- Filed reports: there is deliberately no self-serve delete button for a report in the product today. Ask us and we will delete a department's data from our database.
- Anything already filed into NERIS: that record belongs to NERIS, not to us. We cannot delete a department's federal filing on request, and a vendor who tells you otherwise is describing a system they do not control. Corrections go through NERIS.
Error reporting and analytics
- Error reporting (Sentry) is off entirely unless a reporting key is configured. When it is on, request bodies and cookies are stripped before an event leaves the process, an explicit list of sensitive keys (transcripts, report contents, NERIS payloads, audio, email addresses) is redacted at a single choke point, and user email is redacted from the identity. Session replay is off.
- Analytics (PostHog) is off entirely unless a key is configured. When it is on: no autocapture (autocapture would hoover up form text, which in this app is incident narrative), no session recording, and a scrubber that drops any property whose name looks like a name, email, address, transcript, narrative, phone, street, patient, city, ZIP, date of birth, or SSN, plus any string long enough to be narrative content.
- This marketing site sends nothing at all unless an analytics key is configured for it, and it has no server side and no database.
What we are not claiming
Because you will be asked these in a budget meeting and you should have the honest answer:
- We do not hold SOC 2, ISO 27001, or any equivalent certification.
- We have not had a third-party penetration test.
- We do not claim HIPAA compliance. Incident narratives can contain patient information; treat this product the way your department treats any other system that touches it, and involve whoever handles that question for you.
- We are a small company. The controls described above are real and you can ask us to demonstrate any of them, but they are engineering controls, not an audit.
Reporting something
If you find a security problem, tell us before you tell anyone else and we will fix it and credit you if you want the credit. Contact: audubon11@gmail.com or +18568737246.
Try it before you decide anything
The trial does not ask for an account, and what it stores is described above in full.