Security
Litly uses infrastructure, application and engineering controls to protect school data. Current assurance materials are available during procurement.
Hosting#
Amazon Web Services, in ca-central-1, for everything stored. AI inference is
the exception; see data residency.
- Database. PostgreSQL on RDS. Encrypted at rest, automated backups, deletion protection, and unencrypted connections refused. The application connects with full certificate verification, checking the server’s certificate chain and hostname.
- Files. S3, encrypted at rest, TLS enforced, all public access blocked.
- Secrets. Generated into AWS Secrets Manager and injected into the running container. Never in configuration files, never in the infrastructure templates, never in the repository.
- Deploys. Deployment artifacts are built from the main branch through CI; production promotion is manual. The container rolls out behind a circuit breaker and rolls back automatically on a failed health check. Database migrations complete before a task serves traffic.
Accounts and sessions#
Passwords are hashed with bcrypt at cost 12. Five failed attempts lock an account for fifteen minutes.
Sessions use a short-lived access token held in memory and a rotating refresh token in an HTTP-only cookie. If a refresh token is presented twice, the entire session family is revoked.
Staff can recover a password by email using a single-use link valid for one hour. Students cannot: a child’s password is held only as a hash and is reset by their teacher, so a student’s optional email address is not a route into their account. Using a reset link revokes every other session and clears the lockout.
Each student account is created with its own username and password rather than a password shared across a class. Both are assigned by Litly and shown to the teacher once, at creation, for printing and distribution.
Access control#
One guard resolves the caller’s membership of a board before any request handler runs. Downstream handlers do not accept a board identifier from the request.
Access is then checked per class, per document and per conversation. A caller without access receives “not found” rather than confirmation that the record exists.
Engineering controls#
These controls run in continuous integration:
- Audit coverage is enforced by the compiler. Every route’s access-log classification lives in one file that must be exhaustive over the API definition. A route added without one does not compile.
- Access-control gates are swept on every pull request. A conformance test walks every route naming a class, document or conversation — around eighty of them — and fails if any lacks an assigned gate. Twenty are then exercised twice, as the teacher who teaches the class and as one who does not, and the outsider must receive exactly “not found”.
- The licence gate has no exceptions. Every dependency must be on a fixed permissive list or the build fails.
- Every pull request runs build, type-check, formatting, lint, dead-code detection, the licence gate, backend integration tests against a real database, frontend unit tests, infrastructure unit tests, a synthesis of every infrastructure stack, and a container image build.
The access log#
Every read or change to a child’s record is recorded: who, when, which route, and why. Board administrators can filter and export the log, including filtered to a single student.
The log is append-only, enforced in the database, and is not erased when a student is deleted. Disclosures are kept seven years and refused attempts twelve months.
Safeguarding#
Student writing receives a separate safety assessment. A concern goes to class teachers, follows the board’s escalation settings if it is not acknowledged, and requires a written reason to close.
Safeguarding records follow the board’s safeguarding retention period and are excluded from student erasure requests.
Vulnerability reporting#
security@litly.ai, or /.well-known/security.txt. Include the affected service, steps to reproduce and potential impact. Good-faith reports will not result in legal action.
Breach notification#
To boards under agreement: within 24 hours of becoming aware of a personal data breach, with what is known at the time, and a fuller report within 72 hours.
“Becoming aware” means a breach has been confirmed. Notifications are updated as the investigation develops.