Security
Specific rather than reassuring. Below is how sessions, authorization, secrets and audio are actually handled, followed by the certifications we do not hold — because a procurement team finding that out later is worse than reading it here.
1. Accounts and sessions
- Teachers sign in with an email address and password through Supabase Auth. We never store or see the password.
- The session is refreshed server-side on every request into the console, so an expired token is rotated before a page renders rather than failing mid-session.
- Any response that writes a session cookie is marked uncacheable. Without that, a CDN can cache one teacher's session and hand it to the next visitor — a real class of bug, and one we close explicitly rather than by luck.
- The console re-checks the session in the page itself, not only at the edge. A route that is only protected by middleware is protected by one thing.
2. How the console fetches student data
- Every request for a roster or a student's progress is made server-to-server, by our own server, carrying the signed-in teacher's token. The browser never makes that call.
- As a consequence, no API address, key or token for the scoring backend is shipped to the browser at all. There is nothing in the page source to point at another institution's data.
- Roster and progress data is never cached — not at the edge, not in the browser, and not in the key-value store this site uses for its waitlist.
3. Authorization between institutions
- Ownership of a classroom is checked in the application layer on every teacher request, with row-level security policies in the database behind it. Two layers, because the first one is the one that can be forgotten.
- A request for a classroom that is not yours returns 404 Not Found, never 403 Forbidden. A 403 confirms the record exists, which is itself a disclosure.
- Teachers never redeem join codes — only students do — and ownership of a classroom is stamped at the moment it is created. So there is no sequence of steps by which somebody holding a code can turn it into a view of a roster. That is a property of the data model, not a check in a request handler.
- Membership is keyed on an internal account identifier, never on an email address or a display name, so changing either cannot move a student between classes.
4. Secrets
The database key that bypasses row-level security is not present in the web application in any environment — not in a build, not in an environment variable, not behind a feature flag. The website and console hold only the public anonymous key, which is designed to be seen by browsers and is useless without a valid session.
5. Audio
- A practice recording is sent to be scored and turned into per-sound numbers. Those numbers are what the rest of the product works with.
- No part of the product plays a student's recording back to a teacher, an administrator, or another student. The console's data payloads contain figures only — there is no audio field to expose.
6. Hosting and transport
- HTTPS everywhere, on every surface.
- Vercel — this website and the teacher console.
- Google Cloud Run — the API that scores attempts and aggregates progress.
- Supabase — PostgreSQL and authentication.
- Microsoft Azure — speech scoring.
7. What we do not have yet
No SOC 2 report. No ISO 27001 certification. No third-party penetration test result to hand over. Nadiv is pre-launch and we would rather write that down than imply otherwise in a procurement conversation. If your process needs a specific control evidenced, ask — you'll get a precise answer, including “not yet” where that is the honest one.
8. Reporting a vulnerability
Email teamnadiv@gmail.com with “security” in the subject line. We will acknowledge within two working days and tell you what we are doing about it.
Please do not test against live classrooms, real students' accounts, or anyone else's data. If you need an account to test with, ask and we will set one up.