A learning-management system holds data about minors. The simplest principle, and the hardest to keep: data you never collected cannot leak. Every extra field is one more field to protect.
What to keep
- Student email, name, grade band — to log in and attach lesson plans to the right person.
- Weekly lesson plans — this is the record, i.e. the evidence that teaching happened.
- Uploaded material — worksheets, tests.
What never to keep
- Home address, photos, phone numbers — no business reason needs them, and do not add them because "we might later".
- Photos of the child's work — tempting for convenience, but close to biometric data and unnecessary for marking.
For minors, only the parent holds an account. Deleting an account means setting active=0 and clearing the session — the system does this automatically, no manual step.
Backup: do not use cp while the server is running
All data lives in two places: the SQLite file and the uploads directory. But SQLite runs in WAL mode, so copying the file while the server is writing produces a truncated copy — a copy that looks valid but is missing the latest transactions. This is the kind of failure you only discover when you need to restore, which is too late.
- Server running: use SQLite's own backup command, not cp — it writes consistently while transactions are in flight.
- Server stopped: copying the whole data directory is enough, and is the simplest option.
- Remember the DB file and the uploads directory travel together — restoring only the DB gives you lesson plans linking to files that no longer exist.
Before going on the internet
Already in place: PBKDF2-SHA256 password hashing with 100,000 iterations and a per-user salt, HttpOnly and SameSite=Lax cookies, 14-day sessions, a lockout after 8 failed logins per 10 minutes per IP, random-token filenames on disk so paths cannot be guessed, an http(s):// requirement on source URLs, HTML escaping on all input, and a 25 MB per-file upload cap.
- Put it behind a reverse proxy with HTTPS (Caddy or Nginx). Never expose the app port directly to the internet.
- Change the default admin password before going live — sample accounts and sample passwords are the first thing tried.
- Still missing versus production: HTTPS at the proxy layer, a total disk quota, and deleting files from disk when a lesson is deleted.
The last two are worth stating plainly because they are technical debt, not bugs: without a total disk quota, one user can fill the disk; and without deleting files when a lesson is deleted, the disk retains data the interface says is gone.
The rest of the series: the legal frame and the weekly rhythm, choosing and training tutors, the 30-source international library.