Encryption
🔐 Encrypted in transit
All app, portal, and API traffic runs over TLS (HTTPS). There is no plaintext mode in production.
✉️ Messages encrypted at rest
Parent–driver–school message content is stored encrypted with AES-256-GCM, with a unique nonce and integrity tag per message — a database copy alone cannot read a conversation.
Each school's data is isolated
Every record belongs to exactly one school, and every server request re-checks that the signed-in user's school matches the record — on reads, writes, exports, and live-map subscriptions alike. Exports are scoped deny-by-default: a role only receives the columns and rows its job needs.
We attack this ourselves: an adversarial test suite that tries cross-school reads, stale permissions, and role escalation runs on every change, and the build fails if any of it gets through.
Account security
📱 Two-factor sign-in for school staff
Staff and admin accounts support authenticator-app 2FA (TOTP). School admins can see who has it enabled.
🚫 Brute-force lockout
Repeated failed sign-ins lock the attempt path — while a parent with the correct password always gets in.
⏱️ Short-lived, signed sessions
Access tokens are signed and short-lived; deactivating an account cuts its access — including live bus-location streams — immediately.
Data has a defined lifespan
Trip and location history is deleted automatically after its retention window (default: two school years, 730 days). Audit logs are kept longer (default: three years) because they answer "who did what". The sweep is a scheduled job, not a promise.
Under Egypt's Personal Data Protection Law (PDPL), a guardian can request a full export of their data, or erasure — we anonymize personal data within the 90-day legal window, and the erasure survives backups and restores.
Who saw my child's data?
Every time a staff member opens a child's full record or exports personal data, the access is recorded server-side in a sensitive-access register the school can review and show to a parent or regulator. Unusual patterns — one account opening many children's records in a day — are flagged for review.
Our standing commitments
🙅 No ads, ever
We never sell data, never show ads, and never use children's data for marketing. Schools pay for the product; that is the whole business model.
🎥 No session-recording of minors
No analytics tool that records screens, keystrokes, or sessions runs in the parent or student apps.
🖼️ Student media is never public
Photos and documents about students are only reachable through authenticated, school-checked, logged requests — never a public link or bucket. Our build fails automatically if anyone wires a public path.
Sub-processors
We keep the list short, and services stay disabled until a school turns them on:
| Service | Purpose | When active |
|---|---|---|
| Cloudflare | DNS, HTTPS termination and content delivery for this site and the API | Always |
| Railway | Runs the application servers | Always |
| Neon | Hosts the database where records are stored | Always |
| Expo | Push-notification delivery to phones | Always |
| Resend | Sending email — password resets, invitations, receipts | Only if the school enables email |
| Paymob / Fawry | Card and kiosk fee payments | Only if the school enables online payments |
| SMS / WhatsApp provider | Text-message delivery of alerts and codes | Only if the school enables that channel |
| Grafana Cloud (Loki) | Stores operational warning and error logs so faults can be investigated | Only if log shipping is configured |
| Google Sheets | Reads a school-owned sheet to import the student roster | Only if the school enables roster import |
| GitHub | Stores the nightly encrypted database backup for 7 days | Always |
| CARTO | Supplies the map background; receives the device’s IP address and the map area shown | Always, unless the school sets its own map tile server |
| Google Maps | Opens driving directions for the driver; receives the next pickup point’s coordinates | Only when a driver taps “navigate to next stop” |