After the term rollover, staff can see students who are not theirs
In short
Staff seeing students outside their section, caseload or faculty is nearly always a recompute problem rather than a role-design problem: access was granted when an assignment was made and nothing revoked it when the assignment ended. Diff one staff account across the rollover boundary, listing every grant and where it came from, and the surviving grants name the fault.
Key takeaways
- Grants made at assignment time accumulate. Nothing in a term rollover removes them unless something is written to do so.
- Access should be a function of staff, student and date, evaluated at query time rather than stored as a list.
- An entitlement table is a cache, and a cache needs every invalidation event enumerated or it is just a stale copy.
- Reporting and BI views are the most common bypass, because they read the database rather than the API.
- Former students are a policy question with no default answer. Decide it, time-box it, and record who decided.
- Prove access with a generated expected set diffed against the API, not by reviewing role definitions in a meeting.
When a teacher, advisor or administrator can open a student who is not theirs, the role model is usually correct and the recomputation is missing. Access was granted when somebody was assigned to a section, a caseload or a faculty, and nothing took it away when that assignment ended. Every term adds a layer, and the rollover is simply when a year of accumulated grants becomes visible at once — often because a teacher opens last year's class list and finds this year's names in it, or the reverse.
That distinction decides the remedy. If the roles were wrong, you redesign roles, which is weeks of work and a migration. If the grants were never recomputed, you change when the decision is made — from write time to read time — and the roles survive untouched. The diagnosis takes an afternoon and it is worth doing before anyone reopens the permissions model.
Diff one staff account across the rollover boundary
Take a single account with a long history — a head of year, a counsellor, a teacher who has moved between departments — and enumerate everything it can reach, before and after the boundary. In a school of 1,200 students, an account that should reach 150 and reaches 900 is the whole finding, and the diff shows you which grants did it.
- Generate the expected set from the roster: the students this person should be able to see today, derived only from current enrolments, assignments and relationships. This is the ground truth and it has to be computed, not asked for.
- Generate the actual set by calling the API as that user, paginating fully. Do not sample. The extra students are always at the end of a list nobody scrolls.
- Diff the two. Every student in actual and not in expected is a grant to trace.
- For each extra student, find the grant that allows it: a role assignment, a section membership, a group, an override, a support role, or a report the user can run.
- Record when each grant was created and what was supposed to end it. In most systems the answer to the second half is nothing.
- Repeat the whole exercise against the reporting layer, separately. A user who is correctly scoped in the application and unscoped in a dashboard has full access, and the dashboard is usually nobody's idea of a permissions surface.
| Grant | Created by | Ends when | Usual rollover behaviour |
|---|---|---|---|
| Section or class membership | Timetable import, or a roster feed from PowerSchool or Canvas | The section ends | New sections are added; old memberships are rarely removed |
| Caseload or advisee list | Manual assignment by an administrator | Reassignment, which is a separate manual act | Survives, because nobody unassigns — they assign someone else |
| Department or faculty scope | Staff record attribute | The staff member moves | Both the old and the new scope end up on the account |
| Cover or temporary access | An absence, a trip, an incident | It was supposed to be a fortnight | Permanent by default; almost never has an expiry field |
| Support or impersonation role | Your own team, for a ticket | The ticket closes | Untouched by rollover, and usually unscoped by design |
| Reporting or dashboard access | A BI tool connected to the database | Nothing | Bypasses application scope entirely, at every point in the year |
Grant-on-assignment versus scope-at-query-time
Underneath the individual leaks there is one architectural choice, and most products make it early and by accident, in the first sprint where somebody needed a permissions check on a Friday.
| Property | Grant on assignment | Scope at query time |
|---|---|---|
| How access is stored | Rows in a permissions or entitlement table | Nothing is stored; it is derived per request |
| When it is correct | Immediately after the grant was written | Always, if the enrolment graph is current |
| What a rollover does | Nothing, unless a job removes the old rows | Changes the answer automatically, the same day |
| Cost | Cheap reads, expensive correctness | A join on every request, and an index to think about |
| Failure mode | Silent over-permission that nobody sees | Over-restriction, which a user reports within an hour |
The second column is the safer default because its failures are loud. A staff member who cannot see a student they need will tell you within the hour; a staff member who can see 400 students they do not need will never mention it. Where query-time evaluation is too slow, keep an entitlement table as a cache — but then treat it as a cache honestly: enumerate every event that invalidates it, and accept that a nightly rebuild leaves a mid-term transfer wrong for up to 24 hours.
The four leaks that survive a correct role model
- Stale section membership. The roster import adds new sections and never removes old memberships, so a teacher accumulates every class they have ever taught. It is invisible until somebody counts.
- Support and impersonation roles. Broad by construction, held by your own staff, and rarely time-boxed or logged at the read level. A school's security reviewer will ask about this one specifically, and the acceptable answer involves an expiry, a recorded reason and a read log.
- Reporting views. A Power BI, Looker or Metabase dashboard connected straight to the database applies none of the application's row-level scope. This is also the path by which student work leaves the boundary and reaches tools nobody scoped, which is the argument in where the line sits on training with student work.
- Exports and downloads. A correctly scoped export is still a file that leaves your control the moment it is saved, emailed or uploaded elsewhere — and a vendor's promise about what it does not keep is narrower than most teams assume, as what a no-retention term actually covers sets out.
There is a fifth surface that behaves like staff access but is not: guardian access. It is derived from the same graph, with relationships that change more often and more messily than staff assignments, and it needs the same date-aware evaluation. The consequences of getting that wrong reach families rather than staff — the scenario worked through in half the parents never install the app shows why the fallback channels matter as much as the app permission.
Former students, and the ambiguity nobody resolves
Some over-access is not a bug at all. Should a counsellor keep access to a student who left in March? Should a teacher be able to reopen last year's marks to answer an appeal, or write a reference in October for a student who graduated in June? Every institution has a real answer to these and almost none has it written where an engineer can implement it.
- Ask for the decision explicitly, per role and per record type, and record who made it. Software that quietly picks the permissive option is making policy on the institution's behalf.
- Implement the answer as a time-boxed grant with a review date rather than an indefinite one. Something like 90 days after the enrolment ends is a common shape, and any figure the school has actually agreed beats an unbounded default.
- Log reads for anything outside the current enrolment. The read log is what turns an awkward question into a factual answer six months later.
- Note that access scope also carries the data-protection argument for European operations: a legitimate-interests case rests on staff seeing only what their role requires. Which basis a school app should rely on is argued in consent or legitimate interest for a school app.
Over-permission does not generate complaints. It generates one incident, years later, in which every grant that was never revoked is read aloud in the same meeting.
What to build, in the order that pays
- The access predicate as one function, date-aware, used by every read path including search and reporting.
- A generated expected-set test that runs in continuous integration for 20 or 30 staff across a rollover boundary, seeded with the awkward cases: a teacher who changed department, a counsellor on leave, a student who transferred mid-term.
- Expiry on every temporary grant, with no way to create one without an end date. The absence of that field is why cover access is permanent.
- Read logging on records outside the current enrolment, retained deliberately and shown to the institution.
- A rollover runbook that includes permission recomputation as a named step with a verification query, rather than assuming the import handles it.
- The same predicate applied to anything an assistant retrieves. A retrieval layer that ignores row-level scope hands a staff member records their account cannot open, and where the model runs changes how provable that is — the deployment question in private LLM deployment.
Single sign-on sits deliberately outside this page: authentication decides who somebody is, and everything above is about what that identity may reach, which is a separate system and a separate failure mode. Building the predicate, the tests and the retrieval-side enforcement is the kind of work we scope under AI agents and automation when an assistant is involved. The rest of this silo sits under student data privacy, engineered, within our education and edtech work.
Frequently asked questions
Short answers to the follow-ups this page tends to raise.
Why can staff see student records they should not after a term rollover?
Because access was granted when an assignment was made and nothing revoked it when the assignment ended. Roster imports add new sections without removing old memberships, caseload changes assign a new person without unassigning the old one, and temporary cover access has no expiry. Rollover does not create the problem — it makes a year of it visible at once.
Should student access be checked at query time or stored as permissions?
Check at query time wherever performance allows, because the answer then follows enrolment automatically and its failures are loud rather than silent. A stored entitlement table is a cache: acceptable if every invalidating event is enumerated and a rebuild lag of up to a day is understood. The dangerous middle is a stored table nobody treats as a cache.
How do we test that staff access is correctly scoped?
Generate the expected student set for each staff member directly from the roster, then call the API as that user and diff the two. Any student in the actual set but not the expected one is a grant to trace. Run it in continuous integration across a simulated rollover, and include the awkward cases: department moves, mid-term transfers, staff on leave and former students.
Should teachers keep access to students who have left?
That is a policy decision for the institution, not a default for the software to pick. Ask for it per role and per record type, implement it as a time-boxed grant with a review date rather than indefinite access, and log every read outside the current enrolment. A common shape is a bounded window after the enrolment ends, long enough for appeals and references.
- access control
- student privacy
- term rollover
- system design
The work behind this page
Builds from our portfolio that this page draws on.
AskVault
An AI internal knowledge-search platform that answers employee questions from your own docs — grounded in citations, with knowledge gaps surfaced and deflection tracked.
Productivity AIFocuscare
End-to-end physiotherapy consultation automation: patient onboarding to AI-generated notes and follow-up scheduling.
Healthcare AIRead next
- Where the education record starts and stops, in the schemaThe education record is not a system boundary you can draw around one database. It is a property of fields, which is why transcripts, prompt logs, error payloads and backups keep landing inside it.definition
- You deleted the student, and the next roster sync put them backRunning the delete job a second time is the reflex and it is almost always wrong. Probe each store immediately after deletion and again after the next sync — the two results separate re-creation from incomplete deletion.diagnostic
- A records request came back with assistant transcripts nobody could redactThe transcripts were never classified, so nothing was designed to filter or delete them. The test is not which system wrote the row — it is whether any join you control gets from that row to a named student.diagnostic
- A student data privacy agreement, read as an engineering specificationSchools bind vendors with a standard agreement plus an exhibit naming every data element collected. Five of its clauses are build work, and the exhibit is a schema diff in disguise.definition
- Directory information is a per-student flag your code has to honourSchools designate their own directory information list, and any family can opt out mid-year. That makes it a dated per-student flag every outbound surface reads at render time.definition
- The school official exception, and what it obliges a vendor to buildA vendor holding student records stands inside the school's own permission, not outside FERPA. Each condition of that permission converts into something you build and evidence.definition
Working on something in this space?
Tell us where you are in a sentence or two. We'll tell you honestly whether we're the right team, and what a sensible first slice of the work looks like.
Start the conversation