◂◂ POLICIES
The technical and organisational controls protecting student data in all three Trainers, how we respond to incidents, and — stated plainly — where our current limitations lie.
This policy describes how R2 Education protects the confidentiality, integrity and availability of information in the OLNA Trainer and the NAPLAN Trainer. It is published so schools and education authorities can assess us without having to send a questionnaire first — and so a parent subscribing directly can see the same detail rather than a reassuring paragraph.
In scope: all three Trainers, the homepage, the three databases, the server functions, hosting and CDN, the AI provider integration, the payment integration, the source repositories and deployment pipelines, and the operator's own practices.
Out of scope: school‑owned and family‑owned devices, networks, identity systems and premises. Endpoint security, network filtering and supervision of students remain the school's or the parent's responsibility. Payment card processing is out of scope because it happens entirely inside Stripe and never touches our systems — §11.2 explains what that means.
R2 Education is a small Australian operation, not a large vendor with a security team. This policy describes controls that genuinely exist and claims no certifications we do not hold. Section 19 lists our limitations without varnish. A school — or a parent — is better served by an accurate picture than an impressive one.
| Control | Status | Detail |
|---|---|---|
| Passwords as one‑way hashes (bcrypt) | IN PLACE | §6.2 |
| TLS/HTTPS on all traffic | IN PLACE | §8.1 |
| Encryption at rest | IN PLACE | §8.2 |
| Databases closed to public access by default | IN PLACE | §7.1 |
| Server‑side identity binding | IN PLACE | §7.2 |
| Role and class‑level access scoping | IN PLACE | §7.3 |
| Separate databases per Trainer | IN PLACE | §5.1 |
| Brute‑force rate limiting on sign‑in | IN PLACE | §6.3 |
| Sign‑in audit log | IN PLACE | §14.1 |
| Secrets held outside source code | IN PLACE | §12 |
| Automated point‑in‑time backups | IN PLACE | §15 |
| Version control and reviewed deployment | IN PLACE | §13 |
| AI fair‑use caps and output validation | IN PLACE | §10 |
| Documented 72‑hour breach notification | IN PLACE | §16 |
| Card details never touch our systems | IN PLACE | §11.2 |
| HTTP security response headers | PARTIAL | Complete except OLNA — §9.1, §19.3 |
| Origin‑restricted API access (CORS) | PARTIAL | §19.4 |
| Patch management | PARTIAL | §19.5 |
| Continuous automated monitoring | PARTIAL | §14.2, §19.7 |
| Australian data residency | NOT IN PLACE | §11.1, §19.1 |
| Multi‑factor authentication for staff | NOT IN PLACE | §19.2 |
| Independent penetration test | NOT YET | §19.6 |
| ISO 27001 / IRAP / SOC 2 | NOT HELD | §20.2 |
R2 Education is run by a single principal, accountable for every security decision and the contact point for every security and privacy matter. There is no separate security team and this policy does not pretend otherwise.
| Tier | Includes | Handling |
|---|---|---|
| Sensitive | Adjustment settings, teacher notes, password hashes, sign‑in logs with IP addresses, and OLNA stored writing submissions. | Server access only. Never returned to a client that does not need it. Excluded from leaderboards and every shared view. Schools instructed to keep health and welfare information out of free‑text fields. |
| Confidential | Student, teacher and parent accounts, question attempts, results, session history, class membership, and the parent contact and billing records held on a family subscription. | Visible only to the student concerned, their class teachers and school administrators, or — on a family subscription — the parent who holds it. Enforced server‑side. Billing records are operator access only. |
| Internal | AI usage and cost metering, aggregate statistics, infrastructure logs. | No question content, answers or writing. Operator access only. |
The full inventory of what is held, and what is deliberately not, is in sections 4 and 5 of the Privacy Policy.
All three Trainers have three tiers, with one deliberate security property: the browser never talks to the database.
A common failure in education apps is a browser that queries the database directly, where a modified client can ask for records it should not see. That is structurally impossible here: there is no database credential in the browser to abuse, and no table readable without one.
The OLNA Trainer, the NAPLAN Trainer and the Scholarship Trainer run on entirely separate databases, with separate credentials, separate server functions and separate hosting projects. A compromise of one does not reach the other, and a school using only one Trainer has data in only one system.
School accounts are created by a teacher or administrator — there is no public registration on that route, and never has been. A family subscription now starts from a sign‑up form on the Trainer's website, and rather than pretend that adds nothing, here is exactly what that surface is and is not.
The form creates accounts switched off. A pending account cannot sign in, holds no student work, and sees nothing. It becomes usable only when Stripe confirms a payment — the activation signal is Stripe's cryptographically signed webhook, not anything a browser sends us — so an automated, abandoned or fraudulent sign‑up yields a dead row, not a login. When the subscription lapses, the same signal switches the accounts back off.
Bulk automation is capped by construction: the endpoint carries a hidden honeypot field and a hard site‑wide ceiling on unpaid sign‑ups per day. Student usernames are generated by us, never chosen, so the form cannot be used to probe for existing student accounts. What we traded away is the old manual step — a family's login now works the moment payment clears, instead of within a business day — and the assurance that matters is unchanged: no student, and no member of the public without a confirmed payment, can mint a working account.
Passwords are stored only as bcrypt hashes with a per‑password salt. Plaintext is never written to a database or a log, and cannot be recovered by us or by anyone holding a copy of the database. A forgotten password is reset by a teacher, or by us on a family subscription, and never recovered.
Every sign‑in attempt, successful or failed, is recorded with username, role, source IP, timestamp and outcome. Over a rolling 15‑minute window:
The per‑IP limit is deliberately generous because a whole class typically shares one school IP through network address translation, and a tighter limit would lock out a classroom. It is more generous than a home connection needs, but the per‑username limit is the control that actually stops password guessing, and it applies identically to every account.
Failures return a single generic message that does not reveal whether the username exists, and internal error detail never reaches the browser.
Students should sign out on shared devices — a token left on a classroom machine, or on the family laptop, stays valid until it expires. Schools and parents should both make that a habit. See §19.2.
Every table has row‑level security enabled with no permissive policies — in PostgreSQL that denies access to every role except the privileged service role. No table is readable by an anonymous or public client, and there is no way around the server functions.
Where a view shapes data for a report, it is created with invoker security so it inherits the caller's permissions rather than its definer's. A view that silently bypasses row‑level security is a well‑known way to leak data out of an otherwise locked‑down schema, and we check for it specifically.
This is the single most important control in every Trainer. When a student records an answer, flags a question, submits writing or asks for their results, the student identifier is taken from the verified token on the server and any identifier in the request body is ignored. A modified client cannot read or write another student's records by changing an ID.
Where a request refers to a child object — an answer belonging to a particular practice test, say — the server checks that object belongs to the calling student before accepting the write.
| Role | Server‑enforced scope |
|---|---|
| Student | Their own records only. Cannot enumerate, view or change any other account. |
| Class teacher | Only students in their explicitly assigned class groups, resolved server‑side on every request. |
| School administrator | All students and teachers at the school, plus account management. |
| Parent | Only the students their own subscription covers, resolved server‑side on every request. A parent role carries no school scope at all: it cannot reach a class group, a school's student list, or any account outside its own subscription. |
Scoping happens in the server function, not the interface. Hiding a button is not access control; removing the data from the response is.
Responses carry only the fields the caller needs. The leaderboard, for instance, returns display names and aggregate accuracy only — deliberately excluding usernames, account identifiers, teacher notes, adjustment settings and individual answers, so a feature every student can see cannot become a data leak.
Each database's service key lives in its server function environment. It is never sent to a browser, never built into the application bundle, and never committed to source control.
All traffic — browser to site, browser to server functions, server functions to database, server functions to the AI provider — uses HTTPS with TLS 1.2 or higher. HTTP is redirected to HTTPS by the hosting platform, and certificates are issued and renewed automatically.
All three databases and their backups are encrypted at rest by the platform using AES‑256, with keys managed by the underlying cloud provider. Static site files contain no personal information.
Passwords carry the additional one‑way bcrypt protection in §6.2, so they stay unusable even to someone with full database access.
| Risk | Control |
|---|---|
| SQL injection | All database access goes through a parameterised client library. No query is built by concatenating user input. |
| Broken object‑level authorisation | Identifiers come from the verified token, and ownership of child objects is checked server‑side before any write (§7.2). |
| Cross‑site scripting | All user‑supplied and model‑generated text is HTML‑escaped before insertion into the page. |
| Oversized or malformed input | Server functions whitelist the fields they accept and truncate every text field to a fixed maximum before storage. Unexpected fields are discarded. |
| Information disclosure in errors | Authentication failures return a generic message; internal error detail is not returned to the browser. |
| Resource exhaustion / cost abuse | Per‑account daily caps on every AI endpoint (§10.2) plus sign‑in rate limiting (§6.3). |
| Dependency risk | A deliberately small footprint — a database client, a password hashing library and a token library, each pinned to a specific version (§13.3). |
| Malicious file upload | Not applicable. No Trainer accepts file uploads of any kind. |
Security response headers are configured per hosting project, and are currently uneven across the three:
| Property | Status | Headers sent |
|---|---|---|
| r2education.com.au (homepage) | COMPLETE | Content‑Security‑Policy, Strict‑Transport‑Security, X‑Frame‑Options, X‑Content‑Type‑Options, Referrer‑Policy, Permissions‑Policy, Cross‑Origin‑Opener‑Policy. |
| NAPLAN Trainer | COMPLETE | Content‑Security‑Policy, Strict‑Transport‑Security, X‑Frame‑Options, X‑Content‑Type‑Options, Referrer‑Policy, Permissions‑Policy, Cross‑Origin‑Opener‑Policy. |
| OLNA Trainer | PARTIAL | X‑Content‑Type‑Options, X‑Frame‑Options, Referrer‑Policy. No CSP, HSTS or Permissions‑Policy yet. |
Bringing the OLNA Trainer up to the same configuration is a small change to a static header file and is our next scheduled security task (§19.3). These headers are defence in depth: the controls in §7 do not depend on them.
All three Trainers are single‑file applications with inline scripts and inline event handlers, so their content security policies must allow 'unsafe-inline' for scripts and styles. That means the policy restricts where code may be loaded from — no script from a host we have not listed — but does not by itself stop an injected inline script. Neither Trainer uses eval(), so 'unsafe-eval' is withheld. The real defence against injection is the output escaping in §9, not the policy.
Requests to the AI provider carry only what the task needs: for generation, a year level, topic and difficulty; for writing feedback, the response text, the prompt and the year level. No student name, username, account identifier, class or school name goes into any AI request. The provider receives student writing without knowing whose it is.
Each account has a daily cap on each AI endpoint, calculated on the Perth calendar day — 20 writing responses per account per day, with lower caps on generation endpoints. If the cap check itself fails the request is allowed, so a database hiccup never locks a student out mid‑lesson.
Model responses must match a strict predefined schema before display. A malformed or refused response is discarded and the failure logged rather than rendered. Generated content is HTML‑escaped like any other untrusted input.
Every AI call is logged with function, model, outcome, token counts, cost, duration and calling account — and no question content, answers or writing. It exists for cost control and abuse detection.
Our AI provider's commercial API terms state that customer inputs and outputs are not used to train its models. We have not enabled and will not enable any arrangement under which student work trains a model.
AI features are non‑essential. If the provider is unavailable, the fixed question banks, practice tests and all reporting keep working.
| Provider | Function | Data received | Location |
|---|---|---|---|
| Supabase (on AWS) | Managed PostgreSQL and server functions. Two separate projects, one per Trainer. | All stored personal information. | OLNA Sydney ap-southeast-2NAPLAN Sydney ap-southeast-2 |
| Anthropic | AI generation, marking and hints. | Writing text, prompt, year level, topic, difficulty. No identifiers. | United States |
| Stripe | Payments, hosted checkout and billing portal for family subscriptions. Not used for school subscriptions, which are invoiced. | Parent name and email, card details entered directly on Stripe's own page, amount charged. No student data of any kind. | United States, with global processing |
| Resend | Transactional email to parents: welcome email after payment, password‑reset links. Never used to email a student, and never used for marketing. | Parent name and email; in a welcome email, that parent's own children's first name, username and year level. No results, no writing, no password. | United States |
| Cloudflare | Static hosting (Pages), CDN, TLS, network‑layer protection. | IP address and request metadata only. | Global edge, including Australia |
| GitHub | Source control and deployment pipelines. | Source code only. No student data. | United States |
| Google Fonts, jsDelivr | Typefaces and one open‑source library delivered to the browser. | IP address and browser type only. | Global CDN |
We choose providers that publish enterprise security programmes and independent audit reports — Supabase and its underlying AWS infrastructure, Cloudflare, GitHub and Stripe all hold SOC 2 Type II or equivalent attestations, and Stripe is additionally certified as a PCI DSS Level 1 service provider. We will not add a sub‑processor receiving personal information without updating this policy and the Privacy Policy and giving schools and subscribing parents 30 days' notice.
Stripe was added in version 1.1, when family subscriptions began; it receives no student data. Resend was added in version 1.3, when the Trainers began sending parents a welcome email and password‑reset links. Resend is the first sub‑processor to receive anything about a student — a child's first name, username and year level, in an email addressed to that child's own parent — which is why it is called out here as well as in the Privacy Policy (section 9).
All three databases are in Australia. The OLNA, NAPLAN and Scholarship Trainers' databases all run in Sydney ap-southeast-2. Writing is still marked in the United States.
AI marking is the one part that leaves the country: writing responses go to a United States service, with no name, username or account identifier attached (§11). A school or authority that cannot accept that can run either Trainer with AI writing marking switched off, everything else intact. If Australian residency is a condition of your deployment, email hello@r2education.com.au before deploying and we will confirm the position in writing.
Payment applies only to family subscriptions; school subscriptions are invoiced and involve no card at all.
Card details are entered on a checkout page hosted and served by Stripe, and travel from the parent's browser to Stripe directly. No card number, CVC, expiry or bank account detail is ever transmitted to, processed by, logged by or stored on any system R2 Education runs — not in a database, not in a server function, not in a log line.
What we store is an opaque Stripe customer and subscription reference, and the amount and date of each charge. Someone with complete access to both our databases could not obtain a single card number, because there are none there to obtain.
All code lives in private repositories. Every change is attributable to an author and a time, giving a full audit trail of what changed and why.
Third‑party libraries are pinned to specific versions rather than floating ranges, so a compromised upstream release cannot be pulled in silently. The footprint is intentionally minimal. We watch advisories for what we use and patch on the timeline in §19.5.
| Log | Contents | Retention |
|---|---|---|
| Sign‑in attempts | Username, role, source IP, timestamp, success or failure. | 12 months |
| AI usage | Function, model, outcome, tokens, cost, duration, calling account. No content. | 24 months |
| Platform logs | Request and error logs from hosting and database platforms. | Provider default, 7–30 days |
Logs never contain passwords, tokens, secrets or writing responses.
We review sign‑in failure patterns for credential attacks, AI usage for anomalous volume, and platform error rates for malfunction or probing. Provider alerting notifies the principal of platform incidents.
Limitation. Monitoring is periodic and manual, not continuous and automated. There is no SIEM and no 24/7 alerting, so a slow, low‑volume intrusion could go undetected longer than it should. Stated rather than glossed over — see §19.7.
Because the Trainers are practice tools rather than systems of record, no school's or family's essential records depend on them. We still recommend exporting results at the end of each term.
| Who | When | What |
|---|---|---|
| Affected school | Within 72 hours of forming a reasonable belief a breach affecting its data occurred | What happened, what information was involved, which students, what we have done, what we recommend. We notify even while assessment continues. |
| Affected parent (family subscription) | Within 72 hours, on the same basis | The same information, sent directly to the parent at the email address on the subscription. There is no school in the middle on this route, so we do not wait for one and we do not route it through anybody. |
| OAIC | As soon as practicable, per the Notifiable Data Breaches scheme | Where an eligible breach is likely to cause serious harm. |
| Affected individuals | In coordination with the school, or directly on a family subscription | The school leads communication with students and families; we supply the factual content and support. Where a family subscribed directly, we communicate with the parent ourselves. |
| Education department | On the school's request, or where required | We complete departmental incident reporting and cooperate fully with any investigation. |
We will not delay notifying a school or a parent while we investigate, and we will not minimise or withhold detail. Anyone whose child's information may have been exposed is entitled to know promptly and completely, even if our assessment is still running.
Email hello@r2education.com.au with "SECURITY" in the subject. We aim to acknowledge within one business day, immediately for anything reported as critical. If credentials may be compromised, a school should deactivate the affected accounts straight away rather than wait for us; a parent should email us and we will reset or disable the account the same day.
Full periods are in section 12 of the Privacy Policy. In summary:
We welcome reports from researchers, teachers, students and anyone else. We will not pursue legal action against someone who reports a vulnerability in good faith under this section.
We will keep you posted, fix confirmed issues as fast as we reasonably can, and credit you if you want credit. There is no paid bug bounty.
Every security policy should be read alongside what it does not claim. These are our current limitations, so a school or a parent can decide with their eyes open.
All three databases run in Sydney, so stored student information stays in Australia. Writing sent for AI marking still goes to the United States (§11.1). Where an authority cannot accept that, any Trainer can run with AI writing marking switched off — raise it before deployment. Priority: high, on request.
Sign‑in is username and password only. MFA is impractical for students, many of whom have no personal device — but a teacher or administrator account is a higher‑value target, seeing a whole class or a whole school. Optional MFA for staff accounts is on the roadmap, and a parent account will be offered it on the same release. Until then, schools should ensure staff use strong unique passwords and change them on any suspicion, and parents should do the same on their own account. Priority: high.
This limitation concerns sign‑in to the Trainers. It does not apply to payments: the Stripe account is protected by multi‑factor authentication today (§11.2), and a parent's card details are not reachable from a Trainer account in any case.
The homepage, the NAPLAN Trainer and the Scholarship Trainer send a full set including a content security policy; the OLNA Trainer sends three headers and no CSP (§9.1). Levelling it up is a small static‑file change and is the next scheduled security task. Note the inherent limit on both Trainers' policies described in §9.1. Priority: high, near term.
The server functions send a permissive cross‑origin policy. This does not grant access to data — every request is still authenticated and authorised server‑side, and a browser on another site cannot obtain a valid token. It does mean endpoints can be called from any origin by a client already holding a valid token. Restricting the allowed origin to our own domains is planned. Priority: medium.
Database and hosting platforms are managed services patched by the provider; application dependencies are updated by hand. Targets: 7 days for critical, 30 days for high, next release for medium and low. Automated dependency scanning is on the roadmap. Priority: medium.
No Trainer has been penetration tested by an independent third party. Security has been addressed by design (§5, §7) and by internal review, but that is not the same thing. We will commission one as the service grows and share results with schools that need them. Priority: medium.
See §14.2. No automated 24/7 alerting on anomalous access, so a slow intrusion could be detected late. Priority: medium.
R2 Education is one person. That is good for access control — exactly one human can reach student data — but it means no separation of duties, no peer review of every change, and a single point of failure for incident response. Schools and parents should weigh it. It is inherent to an operation this size, and disclosed rather than engineered away.
One practical consequence for families: account creation, password resets and cancellations by email are handled by one person, so they are same‑ or next‑business‑day, not instant. Cancelling through the billing portal is the exception — that is self‑service and immediate, and it never waits on us (Terms §14.3).
We will keep this section honest. Items come off only when the control genuinely exists, and new limitations get added as we find them. If something here matters to your assessment, tell us — it moves up the list.
Reviewed every six months, and additionally after any security incident, significant architectural change, or change of sub‑processor. The version and date at the top always reflect the current version.
R2 Education holds no ISO 27001, SOC 2, IRAP or other formal security certification, and will not imply otherwise. Our platform providers hold independent attestations (§11), but that is assurance over their infrastructure, not over our applications.
Free of charge, we will:
A parent subscribing directly has no procurement team to lean on, so ask us instead. We will answer any question in this policy in plain terms, tell you exactly what we hold about your child (Privacy Policy §14.2), and say so if the honest answer is that a control is not in place — section 19 exists for that reason and we would rather point you at it than talk around it.
Contact hello@r2education.com.au.