ReasonBoard — Privacy & Safety
This is a self-hosted app. Whoever runs the server controls all data. This document describes what the app stores, what leaves the server, and how to remove it, so a school can set an appropriate policy — especially important when students are minors (GDPR, COPPA, Ethiopia's data-protection law, and local equivalents).
Two things about children's data are true of this app and worth stating plainly before the detail:
- Students never provide an email address or a password. A student is a
display name, a class, a 4-digit PIN, and their own work.
- **A teacher can download or erase any one child's record from the class
roster**, and erasing means erasing — see "Deleting data".
What is stored
Everything lives in one SQLite file on the server: data/studyboard.db.
About students (minors)
| Data | What it is |
|---|---|
| Identity | Display name, the class(es) they're enrolled in, when they joined |
| PIN | 4-digit sign-in PIN, scrypt-hashed — never stored in plaintext |
| Sign-in link | A personal /j/<token> token, so a student can sign in without typing anything. This token is a credential: anyone holding it can open that student's account. Teachers can reissue it (which invalidates the old one) from the roster |
| Progress | Lesson starts and completions, quiz scores, streaks, questions asked, timestamps |
| Exam attempts | Their answers, score, and when they started and submitted |
| Review schedule | Which lessons are next due for them, and how they last scored |
| Q&A | Questions asked during a lesson, and the answer given. Stored per lesson, not per student — the question text is kept and reused for the whole class, and is not linked back to who asked it |
| Device token | If the native app is installed and notifications are enabled |
Not stored for students: email address, phone number, date of birth, address, photograph, guardian details, or any other identifier. The app never asks for them, and there is nowhere to put them.
About teachers and schools
| Data | What it is |
|---|---|
| Teacher accounts | Name, username, scrypt-hashed password. Email address and a Google account id if they signed in with Google |
| Schools (orgs) | School name, invite code, owner, plan status |
| Invitations | Invite tokens, and the email address one was sent to if email was used |
| Classes | Class name, join code, grade, subject, the owning teacher, assignments and due dates |
| Lessons and materials | Generated lesson scripts, uploaded source text, figure images, the question bank |
| Narration | Generated (and teacher-recorded) audio clips, cached so each line costs once |
| Admin audit | Which administrator did what, when — including every student erasure |
| Usage metering | Per-day generation counts, token counts and cost. No lesson content |
On the device
The browser keeps small local preferences (selected profile, language, data-saver, which lessons are downloaded for offline) and a queue of progress recorded while offline, which is sent when the connection returns. Clearing site data removes all of it.
Diagnostics
The app reports client-side failures (a graphic that wouldn't draw, an uncaught error) to the server as a short code plus a truncated message. These are held in memory only, are lost on restart, and contain no student data.
Messages people send us
Teachers and students can write to the platform owner from inside the app (Settings → Report a problem, or 💬 Help on a student's home screen).
A student's message is free text written by a child, so treat it as their words. What is stored is the message, their name and role, their school, and a small technical snapshot captured at send time: which screen they were on, the lesson open at that moment if any, whether the device was online, the app version, the screen size, and the browser's user-agent string. Nothing else from the page is captured, and nothing typed elsewhere in the app is included.
Only the platform owner can read these. A reply is visible only to the person who sent the original message. A message written while offline is held on that device until the connection returns.
Erasing a child erases their messages too — see Deleting data below. A teacher's messages are kept when their account is removed, because those are records of the school's own operation.
If your school would rather students did not write free text to the platform, tell them to route problems through their teacher instead — the button cannot currently be turned off per school.
What leaves the server
| Goes to | What | When |
|---|---|---|
| Anthropic (Claude) | The material a teacher pastes or photographs, and lesson/Q&A prompts | Lesson generation, photo reading, answer grading, Q&A |
| OpenAI | Lesson narration text; optionally generation, if configured as a provider | Studio narration (OPENAI_API_KEY) |
| Google (Gemini) | Generation prompts | Only if configured as a fallback provider (GOOGLE_API_KEY) |
| ElevenLabs | Lesson narration text | Only if configured as the narration engine (ELEVENLABS_API_KEY) |
| Resend | A teacher's email address and an invite link | Only when a teacher invite is emailed (RESEND_API_KEY) |
| Your backup destination | A full copy of the database, including everything above | Nightly, only if BACKUP_UPLOAD_CMD is configured. See [docs/backup-restore.md](docs/backup-restore.md) |
Only the providers you configure with an API key are contacted. Nothing is sent to Anthropic (or anyone else) about a student — the model sees teaching material and questions, not rosters.
Do not paste private, sensitive, or personally identifying student information into the material box. Treat photo uploads the same way: a photo of a textbook page is fine; a photo of a class list is not.
Deleting data
| To remove | How |
|---|---|
| One child's entire record | Class roster → × next to their name. If that class is their only subject, their account, progress, exam attempts and review schedule are permanently erased. If they take other subjects, that history is kept and only this class's enrollment goes |
| A child's record, keeping a copy first | Roster → ⤓ downloads everything held about them as a JSON file, then remove them |
| A whole class | Deleting a class erases the students for whom it was the only class, along with all their data |
| A whole school | The platform console deletes the school and every teacher, student, class, lesson and record belonging to it |
| A lesson | The × on the lesson in the library (recoverable for 30 days, then purged) |
| Everything | Stop the server and delete data/studyboard.db — and any copies your BACKUP_UPLOAD_CMD has sent off-site |
| Offline copies on a device | Uninstall the PWA, or clear the browser's site data for the app |
| Messages a child sent | Erased with the child, automatically — their messages are part of the record, not separate from it. They are also included in the ⤓ download, so a parent asking "what do you hold?" gets their child's own words back |
Backups are the exception to every row above: an erasure removes the record from the live database, but a snapshot taken beforehand still contains it until that snapshot ages out (BACKUP_KEEP, default 2 nightly copies) or you delete it from your off-site destination. If you promise a parent complete erasure, say what your backup retention is.
Retention
The app does not expire student records on its own — a student's history stays until someone removes them, their class, or their school. Deleted lessons are purged 30 days after deletion. Narration audio that nothing has played for weeks becomes evictable and is dropped when the cache is over budget. Decide a retention period for student records (end of the school year is the usual choice) and apply it; nothing here will do it for you.
Content safety
Claude declines to produce harmful content by default. Because this is a teaching tool, also:
- Review AI-generated lessons before assigning them to a class — generation can
occasionally include an inaccuracy. The app tracks a "reviewed" state per lesson for exactly this.
- Keep generation behind an account (
REQUIRE_ACCOUNT_FOR_GENERATION=1) so
students cannot generate freely: generation costs money and is unmoderated input.
Recommended before enrolling minors
- Serve over HTTPS (also required for camera capture and PWA install).
- Configure off-site backups and rehearse a restore —
[docs/backup-restore.md](docs/backup-restore.md).
- Treat printed student sign-in cards as credentials: they don't expire on their
own. Collect them back, or reissue the links from the roster afterwards.
- Set a clear, written policy with parents/guardians before enrolling minors,
covering what is sent to Anthropic (and any other provider you configure), how long records are kept, and how to request a copy or a deletion. This document is the source material for that policy, not a substitute for it.