Documentation

Security and privacy

Version 1.1 ·Updated 2026-08-29

Next reviewed by 2027-02-28.

Written for it managers, business managers, and anyone filling in a vendor questionnaire.

What this covers, and what ataw is today

ataw is a student information system: enrolment, attendance, assessment, wellbeing and medical records on one student record. That is children's personal information, some of it health information. Some of it, such as parenting orders and child-safety records, is among the most sensitive material a school holds.

ataw is pre-production and holds no school's real records. One environment is deployed, for demonstration and development. This document describes the posture as built today, so that a school can see what exists before deciding to be the first. Where something is not built, it says so and says when it is due.

We are a small vendor. The honest way to be evaluated as one is to publish this rather than to answer it a school at a time, and to be specific about the gaps rather than to write around them. The first audit finds the gap either way, and everything else on the page loses its credibility with it.

Where the data lives

One virtual machine runs the application container, one PostgreSQL instance and one object store. Each school's records live in their own Postgres schema inside that one database. Nothing is replicated to a second region, and no data is sent to any third party for processing, analytics or model training.

Residency is an open item, and we will not claim a jurisdiction until the hosting arrangement is in writing. Onshore hosting is a procurement condition for Australian schools and we treat it as one; it is listed below with a date rather than asserted here.

Encryption, and what each layer protects against

The second column is the one worth reading. "Encrypted in transit and at rest" is true of almost every product and tells a reader nothing about which attacks it stops.

In transit, browser to ataw

TLS 1.2+, certificates issued by Let's Encrypt and renewed automatically by the platform's reverse proxy. HSTS is set for two years including subdomains.

Protects against Anyone on the same network as the school office reading or altering a session.

In transit, inside the host

Not encrypted. The application reaches Postgres and the object store over the container network without TLS.

Protects against Nothing. Both endpoints are on one host's private Docker network and are not published to the internet, so the exposure is an attacker who already has code execution on that host. It is on the list below.

At rest

Full-disk encryption on the host only. There is no column-level or application-level encryption yet.

Protects against A disk leaving the building. It does not protect against a compromised application, which is the threat that matters more.

Secrets

Resolved at deploy time and age-encrypted to a key generated on the server, which never leaves it. No secret is in git, in the container image, or in any environment file on a developer's machine.

Protects against A leaked repository, a leaked image, or a stolen laptop.

In the browser

A Content-Security-Policy that permits no external origin at all: fonts are self-hosted, icons are bundled server-side, and there is no analytics, tag manager or third-party script of any kind. Framing is refused outright.

Protects against Cross-site scripting, clickjacking, and data leaving to a third party by accident.

Access control

One Postgres schema per school
Every record table for a school lives in its own schema, reached through a database role that has privileges on that schema and no other. Postgres itself refuses the crossing, so the refusal does not depend on our query builder getting it right.
Proved by attempting the crossing
The test suite connects as the least-privilege application role and tries to read another school's rows directly. It asserts the database refuses. A separate test asserts the suite is not running as a superuser, because that assertion would otherwise pass for the wrong reason.
Nothing outside the data layer speaks SQL
A build check fails if any handler imports the database driver, holds a connection, writes raw SQL or names a schema. That is what stops a single handler quietly stepping around the isolation while every isolation test keeps passing.
Passwordless sign-in
Passkeys, with a one-time email code as the fallback. No password is stored, so there is no password to leak, reuse or phish.
Server-side authorisation on every route that serves student data
Every guarded route checks the session on the server. The browser-side route guard closes the anonymous case for convenience, and the server relies on its own check.
Classification declared per field
Each field carries one classification (internal, sensitive or restricted) and that single declaration drives encryption, retention, access tier, API response filtering and the telemetry deny-list. Parenting orders and court documents are restricted and reachable only by named roles.

Role-based access within a school, meaning which staff member may read which student's medical or wellbeing record, is designed and not yet built. Today the only environment holds no real records, so a session is the whole of the check.

Retention and disposal

Every record carries a retention class rather than a delete button. Removing a record from the working set and disposing of it are separate acts, because a registrar removing a duplicate has not made a decision about a forty-five year obligation and should not be able to.

  • Child-safety records: 45 years, counted from the child's date of birth rather than from when the file closed, because the obligation is owed to the child.
  • Attendance registers and NCCD evidence: 7 years past the year they record.
  • Immunisation status: 3 years past the enrolment it was collected for.
  • An enquiry that never became an application: 2 years. A person is created at first contact, so most person records belong to people with no ongoing relationship to the school. Holding them indefinitely is the thing the Children's Online Privacy Code exists to stop.
  • Legal hold overrides all of it. A hold is checked before a record's age and before whether it was deleted at all, because a hold that only applied to records past their date would protect nothing.

Where a record carries more than one class, the longest wins: a floor another class could bring forward is not a floor.

Backup and recovery

Production is backed up three times a day, at 03:15, 11:15 and 19:15 Melbourne time. Each run dumps the whole database in one transaction-consistent snapshot, which is every school at the same instant rather than a set of files taken minutes apart, compresses it and encrypts it. The job refuses to run rather than write an unencrypted copy. Eight days are kept.

The restore is tested, not assumed. On the first of each month the most recent backup is decrypted into a scratch database beside the live one, and the schema count and the school registry are checked against what was recorded when the dump was taken. A backup job that has been silently failing for six weeks looks exactly like one that works, and so does a bundle that restores into an empty database. Both the backup and the verification report to monitoring, so a run that stops happening raises an alert rather than being discovered when a restore is needed.

The backups do not leave the host. They survive a dropped volume, a bad migration, a deleted container and an operator mistake. They do not survive the loss of the machine itself, because there is no copy anywhere else. Offsite replication is the next piece of this work and it is not built.

The recovery point is therefore up to eight hours, being the gap between scheduled backups. There is no write-ahead-log archiving, so recovery lands on whichever backup you choose rather than on an arbitrary moment. No recovery time is stated: the restore path is tested monthly and has never been exercised against a school-sized database, and a number produced from a test dataset is a number that fails its first real use.

The test environment is not backed up, deliberately. It holds invented data and exists to be rebuilt.

Incident response

If we become aware of unauthorised access to a school's data, we will contact that school's nominated privacy contact directly, in writing, with what we know and what we do not. Australia's Notifiable Data Breaches scheme requires an assessment within thirty days and notification to affected individuals and the OAIC where serious harm is likely; a school is the entity with the relationship to those families, so our job is to give them what they need to make that assessment quickly.

We have no on-call rotation and no twenty-four hour response commitment, and it would be misleading to imply otherwise at our size. Reach us at security@seraco.io.

Sub-processors

The complete list. Nothing else receives any data.

The hosting provider

Runs the virtual machine the application and its database sit on.

Receives All of it, as the operator of the host.

Let's Encrypt

Issues the TLS certificate.

Receives The domain name. No school data.

Resend

Sends the one-time sign-in code, when email is configured.

Receives The recipient's email address and the code. No student data. Not yet provisioned; sign-in codes are currently held in the database and the application refuses to claim a code was sent when it was not.

There is no analytics provider, no error-reporting service, no customer-messaging widget and no advertising network. The content policy would block them, which is deliberate.

Children's Online Privacy Code and ST4S

The OAIC's Children's Online Privacy Code binds vendors from 10 December 2026. Two design decisions are made against it rather than retrofitted: a person exists from first contact, which means the enquiry retention class above is load-bearing rather than housekeeping; and no data leaves for analytics or model training, so there is no secondary use to disclose.

ataw has not been assessed under Safer Technologies 4 Schools. The material an assessment asks for is what this page is: data flows, sub-processors, access control, retention, and the gaps. We would rather publish it now and be assessed against it than publish a badge.

What is not built yet

Everything above that is missing, in one place, with a date. If you are comparing vendors, this is the section to compare.

Backups never leave the host

Production is backed up three times a day, encrypted, and the restore is verified monthly. Every copy sits on the same machine as the database, so a host loss takes the backups with it. Offsite replication is written and not yet provisioned.

Due Before the first school's data.

No stated recovery time

The recovery point is up to eight hours, being the interval between backups. No recovery time is published: the restore has only been exercised against a small dataset, and a number produced from one is a number that fails its first real use. It will be measured against a school-sized database.

Due With the first school.

No write-ahead-log archiving

Recovery lands on whichever eight-hourly backup you choose rather than on an arbitrary moment. Continuous archiving is what would shrink the recovery point from hours to minutes.

Due With the offsite work.

Data residency is not yet contractually established

Onshore hosting is a procurement condition for Australian schools, and it is a decision about hosting arrangements rather than about code. We will not claim a jurisdiction until the arrangement is in writing.

Due Before the first school's data.

There is no audit log

Who read which student's record, and when, is not recorded yet. The tenant registry, the job queue and the migration ledger are in place; the platform audit log is not.

Due With the capability and audit work.

The disposal job does not run

Retention classes and legal hold are modelled, and every record table carries the columns the disposal job needs. Nothing reaps them yet, because there are no production records to reap.

Due With the first record domain.

The content policy still allows inline scripts

The framework emits an inline script of its own to set the colour scheme before first paint. Removing the allowance needs a per-request nonce. Everything else in the policy is real: framing, plugins, base URI and form targets are all locked down and do not depend on script injection at all.

Due Next change to the policy.

No independent penetration test

Automated scanning runs on every change: dependency and secret scanning in the pipeline, and a security scan in the repository that fails the build on a high finding. A person attempting to break in would find things a scanner does not.

Due Before general availability.

Internal connections are plaintext

Named in the table above. Both endpoints are on a private container network on one host.

Due With the hosting work.

Questions this does not answer

Send them to security@seraco.io and we will answer in writing, then add the answer here. A question a school had to ask is a question the next school will ask too.