Roster mapping protocol — school, EduSpaze, vendor
How a school's staff and pupils come to exist correctly inside a vendor's app, stay correct for a year, and disappear cleanly at the end of it. Both the school and the vendor are asked to comply with this. EduSpaze provides the mechanism and holds both sides to it. Last updated 2026-09-06.
Read alongside the vendor integration guide (the technical contract) and the school admin guide.
1. The agreement in one paragraph
The school owns identity. EduSpaze brokers it. The vendor never receives it. A pupil and a member of staff reach a vendor app as a *code* — RB-4213, STF-0007 — together with the school's id and the codes of the classes they belong to. No name, no email address, no date of birth, ever. The vendor builds its accounts on those codes; the school keeps them stable; EduSpaze guarantees that the same code means the same person on the launch, in the roster and in the telemetry that comes back.
Everything below exists to make one sentence true: the vendor can always answer "which class is this person in", and can never answer "who is this person".
2. The four things being mapped
| Object | Owner | Identifier the vendor sees | Changes when |
|---|---|---|---|
| School (tenant) | EduSpaze | tenant — the school's EduSpaze id | never |
| Pupil | the school | subject — Student.externalId, from the school's own SIS | never, if the school complies with §4 |
| Member of staff | the school | subject — STF-nnnn, minted by EduSpaze or set from the school's staff code | never |
| Class / group | the school | opaque id + a teaching label (5A, Reading group Blue) | at rollover, and when the school reorganises |
Pupil and staff subjects share one namespace, so a vendor keeps one subject column and one account table for both. Subjects are unique within a school: two schools may both use STF-0001, and the pair (tenant, subject) is the real key.
3. The lifecycle
Eight stages. Each names what each party does, and what EduSpaze records.
S0 · Agreement
| Party | Does |
|---|---|
| Vendor | Signs the Universal Data Sharing Agreement: what is passed, retention, deletion on deprovisioning. Declares its integration tier. |
| School | Approves the app commercially (pilot, bundle or direct) and names the person accountable for the roster. |
| EduSpaze | Records the tier and the agreement on the vendor's listing. Nothing is provisioned yet. |
Nothing in this protocol overrides the DSA; where they differ, the DSA wins and EduSpaze should be told so this document can be corrected.
S1 · The school prepares its roster
The school imports pupils (School → Students → Import, CSV) with externalId taken from its SIS. This is the moment that decides whether the next twelve months work — see §4.
Staff already exist as accounts; EduSpaze mints STF-nnnn for each the first time one is needed, or the school can set its own staff codes.
| Party | Does |
|---|---|
| School | Imports pupils with stable externalIds; creates classes and groups; assigns pupils to classes and teachers to classes. |
| EduSpaze | Validates the file, reports every rejected row with a reason, records the import on the school's audit log. |
| Vendor | Nothing. |
S2 · The school approves the app, and its scope
The school decides which pupils may use the app — by class, by group, or by year — and that decision creates the connections. A pupil with no connection does not exist to that vendor: they are absent from the roster, refused on launch, and rejected in telemetry.
Staff scope follows pupil scope. A member of staff may open a vendor app when they teach a class that is in scope. That is deliberate: it needs no second list to maintain, and it cannot grant a teacher access to a cohort they do not teach.
| Party | Does |
|---|---|
| School | Chooses the classes or groups in scope. Reviews it each term. |
| EduSpaze | Creates a connection per pupil, dates it, and records who approved it. |
| Vendor | Nothing. |
S3 · Credentials and the handshake
| Party | Does |
|---|---|
| Vendor | Issues an API key and a launch signing secret (Integration & API). Sets its launch URL (https). Implements signature verification exactly as published, and decides whether to opt in to launch v2 (class information on the launch). |
| EduSpaze | Stores only a hash of the API key; shows each credential once; refuses an http launch URL. |
| School | Nothing. |
A vendor that cannot verify a signature must not be given a key. This is the one step where "we'll fix it later" ends with pupils in the wrong classes.
S4 · Provisioning — the vendor builds its accounts
| Party | Does |
|---|---|
| Vendor | GET /me → the tenants it may ask about. GET /roster?tenantId=… → every connected pupil with class and group codes, and the staff who teach those classes. Creates one account per (tenant, subject). Stores the class ids. |
| EduSpaze | Answers only for that vendor's own connections, in that tenant. An unknown tenant answers the same as an empty one. |
| School | Nothing. |
The vendor creates accounts before anyone arrives. A first launch should find an account waiting, not create one in a hurry with whatever the URL happened to contain.
S5 · First launch
A pupil opens the app from the EduSpaze launcher; a teacher opens it from School → Connected Apps. Both arrive through the same signed handshake.
| Party | Does |
|---|---|
| EduSpaze | Signs subject, tenant, ts, nonce (v1) and, for a vendor on v2, role, classes and the pupil's class, className, year, groups. Records the launch on the school's audit log. |
| Vendor | Verifies the signature, rejects anything older than five minutes, remembers the nonce, then signs the person in to the account provisioned at S4. |
| School | Nothing. |
A launch is an authentication, not a provisioning event. A subject the vendor does not recognise means its roster is stale: re-sync, then admit them. It never means "create an account for whoever this is".
S6 · Steady state
| Party | Does |
|---|---|
| Vendor | Re-syncs the roster nightly with updatedSince. Posts telemetry (/heartbeat while active, /sessions from its own logs). |
| EduSpaze | Folds telemetry into engagement, shows the school minutes per pupil per app, shows a parent the same for their own child where the school allows it. |
| School | Keeps classes and groups current as pupils move. |
S7 · Change during the year
| What happened | What the vendor sees | What the vendor must do |
|---|---|---|
| Pupil moves from 5A to 5B | same subject, different class id | move the account; never create a second one |
| Pupil leaves the school | connection revoked → absent from the roster | stop accepting the subject; delete per the DSA |
| New teacher takes a class | a new staff subject in staff[] | provision their view |
| A class is added to scope | new subjects appear | provision them |
| Academic rollover | class ids change; academicYear moves on | keep the accounts, re-map the classes |
The rule underneath all of it: the subject is the person; the class is where they are today. A vendor that keys accounts on the class, or on a name it inferred, breaks at the first move.
S8 · Exit
| Party | Does |
|---|---|
| School | Revokes in EduSpaze — never by emailing the vendor, because only the platform revocation reaches the API. |
| EduSpaze | Drops the pupils from the roster, refuses their subjects on launch and telemetry, records the revocation. |
| Vendor | Deletes or anonymises what it holds for those subjects within the DSA's window, and confirms. |
An erasure request for one pupil follows the same path: the school anonymises the pupil in EduSpaze, the subject stops resolving, and the vendor deletes on that signal. Historic engagement stays as time-only, attached to a token that no longer identifies anybody.
4. What each party must comply with
The school must
- Give every pupil a stable
externalIdfrom the SIS, and never reuse or renumber it. This is the single obligation that everything else rests on. A re-import that changes the codes makes every pupil a stranger to every vendor and orphans their history. - Keep class and group assignments current — they are what the vendor places people by.
- Approve and review scope by class or group each term, and revoke through the platform.
- Never send a pupil's name, email or date of birth to a vendor out of band. If a vendor asks for one, tell EduSpaze: it is a breach of the DSA, not a favour.
- Keep a school administrator with a password, so a provider outage cannot lock the school out of its own settings.
The vendor must
- Key every account on
(tenant, subject). Not on a name, not on an email, not on a class, not on an order of arrival. - Verify the launch signature before trusting anything in the URL, reject a launch older than five minutes, and refuse a repeated nonce.
- Provision only from the roster. No self-signup, no invite links, no "just add this one pupil" inside a school's tenant.
- Treat a subject that has left the roster as revoked, and delete within the agreed window.
- Send no content. Telemetry carries when and how long, never what: no scores, no work, no free text. There is no field for it, and inventing one is a breach.
- Never attempt re-identification — not by cross-referencing, not by asking a pupil their name, not by inference from a class label.
- Tell EduSpaze before changing how it verifies launches, and opt in to v2 only after its verifier signs whatever it receives rather than a fixed list of parameters.
EduSpaze will
- Guarantee that one subject means one person, for as long as the school keeps its codes stable, across launch, roster and telemetry.
- Answer a vendor only about its own connected pupils, in the tenant it names.
- Refuse — identically and without explanation — any launch outside a verified domain, an inactive configuration, or a lapsed subscription, so no probe learns anything.
- Record every launch, every scope change, every revocation and every roster read on the school's own audit log, and show the school what each vendor was told.
- Never publish a change to the v1 launch contract. A vendor's working integration stays working; new information arrives only in a version they opt into.
- Show the school, in its own portal, exactly what a vendor is told about a pupil and a member of staff, in the same words as this document.
5. What is never shared
| Shared | Never shared |
|---|---|
| pupil subject, staff subject | name, email, username, date of birth |
| school id and name | home address, contact details, photographs |
| class and group ids, with teaching labels | year-level attainment, SEN status, safeguarding flags |
role (student, teacher, staff, school_admin) | anything a guardian said, or any note about a pupil |
| session start and end times | what a pupil did in the app: scores, answers, content |
If a vendor's product genuinely needs something on the right-hand column, that is a conversation with EduSpaze and the school before a line of code — not a field added to a payload.
6. When it goes wrong
| Symptom | Cause | Who fixes it |
|---|---|---|
| Vendor rejects a pupil at launch | roster is stale, or the connection was revoked | vendor re-syncs; if still absent, the school's scope is the answer |
| A pupil has two accounts in the app | vendor keyed on something other than the subject | vendor, by merging on (tenant, subject) |
| Everyone appears as new in January | school renumbered its externalIds | school, by restoring the codes — the vendor cannot repair this |
| Telemetry counted for nobody | subject not connected to that vendor | school's scope, or a stale vendor roster |
| A teacher sees a class they do not teach | class assignments in EduSpaze are wrong | school |
| Launch signature fails after an EduSpaze deploy | should never happen; the v1 contract is regression-tested | EduSpaze, immediately |
Whoever notices, tells EduSpaze. The audit log settles what actually happened, because both the launch and the roster read are on it.
7. What EduSpaze still has to build for this
Stated plainly, because the protocol above describes the intended process and part of it is not yet self-service:
| Gap | Consequence today | Needed |
|---|---|---|
| No school-facing way to connect pupils to an app (S2) | connections exist only in seeded demo data; a real pilot needs EduSpaze to create them | a scope screen: pick classes or groups, see who it covers, approve, and revoke |
| No staff scope | any teacher with the permission can open any connected app, rather than only the apps covering classes they teach | derive staff scope from pupil scope, as §S2 describes |
| No rollover handling | class ids change at the academic year and nothing prompts the school or warns the vendor | a rollover step, and a academicYear change flagged in the roster |
| No "what this vendor was told" view for the school | the school is asked to trust §5 rather than see it | a per-vendor disclosure page in the school portal |
| No SIS sync | externalId stability depends on a CSV export, which is exactly the obligation most likely to be broken | OneRoster or Google Classroom sync, replacing the upload |
The first two are what make this document enforceable rather than aspirational.
