How Corra de-identifies student data before an AI request
By The Corra team · · 2 min read · Engineering
De-identification in Corra means every name, family contact and roster identifier in a request is replaced with a placeholder token before that request reaches a language model, and swapped back only after the answer returns to your browser. This post walks the whole path, because "we de-identify" is a claim that only means something once you can see where it happens.
Step one: the request leaves your browser
When you ask for a feedback draft, the browser sends the relevant text plus the identifiers of the records involved to the Corra AI gateway, which runs on Cloudflare Workers. It does not talk to the model provider directly. That indirection is the whole design: there is exactly one road to the model and it passes through code we control.
Step two: the gateway builds a substitution map
The gateway loads the roster values relevant to the request — student names, family contacts, identifiers — and matches them against the text. Exact roster matching catches the names that actually belong to your class, pattern matching catches things shaped like emails, phone numbers and identifiers, and a fallback pass catches likely names the first two missed.
- Roster-aware matching is the strongest layer, because it knows the real values to look for.
- Pattern matching catches identifiers that were typed rather than pulled from a record.
- The fallback exists because a teacher’s note may mention a sibling, a neighbour or a previous teacher who is on no roster.
Step three: the model sees structure, not people
The outbound request carries placeholder tokens where identities were. The model still sees everything it needs — the writing, the rubric, the context, the relationships between people in the text — and none of what it does not need. The token map itself is encrypted, short-lived, and readable by no client, including yours.
Step four: re-identification happens in your browser
The response streams back through the gateway and the tokens are resolved to real names, so the draft you read says what you expect. The transparency panel shows what was hidden, so the guarantee is inspectable rather than a promise on a marketing page.
Why not do this in the browser?
Because browser-side de-identification is a courtesy, not a control. Anything running in the page can be disabled by an extension, broken by a bug, or skipped by a modified client, and the failure is silent — the request just goes out with real names in it. Putting the substitution on the server means the only way to reach the model is through the code that performs it.
What this does not protect against
De-identification removes identifiers; it does not make text anonymous in every sense. A note describing a small class in enough detail can be re-identifying to someone who knows that class, and a teacher who types identifying detail into a free-text box for a feature that does not use roster context is relying on the pattern layer rather than the roster layer. It is a strong control, not a magic one, and treating it as absolute would be the mistake.
Common questions
- Does the model provider ever see a student name?
- Not from Corra. Substitution happens on our edge before the outbound request is made, so identifiers do not reach the provider.
- Can I see what was de-identified?
- Yes. The copilot’s transparency panel shows which values were replaced for a given request.
- Can I turn de-identification off?
- No. It is not a setting. It runs on every request that touches roster data.