LEARNER LEAD
Security

How the isolation guarantee is actually built

The landing page states that a school never sees another school's data. This page is the mechanism behind that claim, written for the person at your institution who has to sign off on it.

Last reviewed
24 August 2026

Tenant isolation

  • Enforced twice, independentlyEvery query runs inside a transaction that first sets a Postgres session variable identifying the tenant. Separately, every tenant-scoped table carries a row-level security policy that filters on that same variable. A bug in the application layer cannot reach another tenant's rows, because the database refuses them on its own.
  • The database role cannot bypass its own policiesPostgres exempts superusers and table owners from row-level security by default. The application connects as a role that is neither, and every table is created with FORCE ROW LEVEL SECURITY so the owner exemption is closed too.
  • A missing policy fails the buildA check runs in CI against the migration SQL and fails if any tenant-scoped table ships without ENABLE, FORCE and a policy. Isolation is a build gate, not a code-review convention.
  • Physical separation is named, not impliedTenants share tables, storage and one backup snapshot. That is the honest limit of a pooled model, and it is written down rather than glossed over. An institution that contractually requires dedicated infrastructure or its own encryption key is provisioned separately.

Data protection

  • Envelope encryption on the sensitive fieldsAadhaar and bank details are encrypted with AES-256-GCM. Each value gets its own data key wrapped by a master key, so rotating the master key rewraps keys rather than re-encrypting the database, and one leaked data key exposes one field.
  • A fresh key and nonce for every valueWithout this, two students sharing a guardian's Aadhaar number would produce identical ciphertext, and the column would leak who is related to whom without anything being decrypted.
  • Masking happens in the API, not the browserA field a role may not see is removed before the response is sent. Sending the full value and hiding it in the interface would leave it in the network tab, the response cache and any client-side logging.
  • Searchable without being readableLookups on encrypted fields use an HMAC-keyed blind index rather than a plain hash, so the index cannot be reversed with a dictionary of every possible Aadhaar number.

Accounts and sessions

  • argon2id password hashingMemory-hard, with explicit parameters rather than library defaults, so a dependency upgrade cannot quietly weaken them.
  • Short access tokens, rotating refresh tokensAccess tokens live fifteen minutes. Refresh tokens are opaque random bytes stored hashed, so a stolen token can be revoked immediately. Replaying an already-rotated token revokes the entire token family.
  • Login failures are uniformA wrong password, an unknown email and a deactivated account do the same work and return the same message, so the sign-in form cannot be used to discover who holds an account.
  • Rate limiting where it countsAuthentication and payment endpoints are throttled. One-time codes are hashed at rest, compared in constant time, single-use, and limited per phone number rather than per IP, because the cost of an unthrottled code endpoint falls on the person being messaged.

Accountability

  • The audit log cannot be editedThe application role holds INSERT and SELECT on the audit table and is explicitly denied UPDATE and DELETE at the database. A rule enforced in application code would be one stray call away from being untrue.
  • Audit rows outlive the people in themThe audit table carries no foreign keys. Deleting a user must not erase the record of what that user did, and it must not be blocked because they once did something.
  • Support access is time-boxed and visibleA support session requires a stated reason, is limited to thirty minutes by default and two hours at most, and shows the signed-in user a banner that counts down and cannot be dismissed. Every action taken during one is tagged with the operator who took it.
  • Recoverable, and testedAutomated snapshots with write-ahead log archiving give point-in-time recovery. The restore is exercised and recorded rather than assumed.

Where the data sits

Databases, caches, object storage and application servers run in the AWS Asia Pacific (Mumbai) region. The content delivery network caches public marketing assets at edge locations worldwide, and no institution data passes through it.

Primary region
ap-south-1 (Mumbai)
Database
PostgreSQL 18, encrypted at rest
Object storage
Keyed by tenant, time-limited URLs only
Backups
Daily snapshots, point-in-time recovery

Reporting a vulnerability

Send findings to the security address below. Tell us what you did, what you saw and roughly when. We will confirm receipt, keep you updated while we investigate, and credit you if you would like us to. Please do not run tests against a live institution's data or against anyone else's account.

Report a vulnerability