Quebec's Law 25: an immutable audit log and a full data lifecycle
On this page
When a platform handles data about minor students, two questions always come up sooner or later: who did what, and when? And how long do we keep this data? I implemented both answers required by Quebec's Law 25: an immutable audit log and a complete data lifecycle.
Context
The SaaS platform I work on uses AI to correct students' writing, for schools across Quebec (it is also the platform behind the admin console). The data it handles is therefore personal information about minors.
In Quebec, Law 25 modernized the rules that govern such information. Among other things, it requires a privacy impact assessment (in French, évaluation des facteurs relatifs à la vie privée, or EFVP) for any information system project that handles personal information, and the destruction or anonymization of that information once its purpose has been fulfilled. The platform's assessment set clear requirements: trace sensitive actions and control the lifespan of the data.
The problem
Those requirements translate into very concrete needs:
- accountability: being able to tell, for each sensitive action, who performed it, when and on which data, with a history that nobody can tamper with;
- keeping nothing longer than necessary, without losing the ability to go back as long as the data is only archived.
Two needs pulling in opposite directions: on one side, never erase the history; on the other, be able to erase data for good.
The solution
An immutable audit log
Sensitive actions are recorded in an audit log: who, what, when, on which resource. The log is append-only: the API exposes no operation to modify or delete an entry. Once written, a record stays exactly as it is.
Immutability is a design decision here: no route, no service can rewrite history.
A complete data lifecycle
Data follows an explicit lifecycle, organized by period:
| Operation | What it does |
|---|---|
| Archive | Takes a period's data out of everyday use, without destroying it |
| Restore | Brings an archived period back when needed |
| Purge | Permanently deletes data that no longer needs to be kept |
| Reset | Clears a workspace to start over for a new period |
This separation makes things clear: archiving is safe, since it can be restored; purging is final, and that is the point.
Results
- The features required by the privacy impact assessment are in place: traceability of sensitive actions and control over retention.
- A reliable history: when a question or an incident comes up, we can trace who did what, and when.
- A controlled data lifespan, from archiving to purging, through dedicated operations rather than manual database changes.
Takeaways
- Compliance is a feature like any other, with its users, its edge cases and its tests. Treated as a box to tick, it turns into debt.
- Immutability is decided at design time: the surest way to make sure a record is never modified is to never write the code that would allow it.
- Think about deletion from day one. Purging data cleanly is much simpler when the data model was designed for it.


