Outgoing, Not Incoming: Where the PII Gate Belongs
A privacy gate stands where data leaves, checks it in its final form, and knows precisely what it is looking for
If you want to stop something private from escaping, the question is not only what you check for. It's where you stand to check.
NAOMS generates synthetic test datasets โ "packs" โ so the system can be exercised against realistic shapes of data without needing real users' lives to do it. The packs get shared. Which creates a real obligation: nothing personal should end up baked into a pack that travels. PII โ personally identifying information: a name, a phone number, an address, anything that ties a record back to a specific human โ must not ride along inside an artifact that leaves.
Where the gate belongs, and what it must know
The gate lives on the outgoing side. The check runs at the point where a snapshot is built for export โ the moment data is about to become a shareable pack โ and not at ingestion, when data first arrives in the generation machinery.
That placement follows from what you are actually protecting. The thing you ship is the snapshot you build at the end, not the bytes you let in at the start. Between those two moments sit every transform, every synthesis step, every join โ each of which can introduce, recombine or surface personal data in a form that never existed at the entrance. Standing at the exit means every one of those transforms is downstream of trust and upstream of the gate, which is exactly the right order: whatever they did, the outgoing scan sees the result.
There is a second reason, about which population you are checking at all. An entrance gate inspects your inputs, which you arguably already control. The risk you actually care about is on your outputs โ the artifact that crosses your trust boundary, the line past which you no longer control who reads something, and lands in someone else's hands. Checking inputs to protect outputs is checking the wrong population.
This is the same principle that makes output encoding, rather than input filtering, the right defense against injection attacks: you sanitize at the boundary that matters, in the context where the data will actually be used, because that is the only place you can see what is truly about to escape.
Placement is half of it. The other half is what the gate counts as personal, and that has to be precise in both directions, because a privacy filter is a classifier โ a rule that sorts each thing it sees into "sensitive" or "not" โ and a classifier can be wrong two ways.
- DIDs are not PII. A DID โ a decentralized identifier โ is a public W3C-standard identifier: a name for an identity that anyone can resolve without going through a company's servers. It is designed to be published; it is how identities get referenced across the network. Treating one as personal data to be scrubbed is a category error, because it is public by construction. Flagging it protects nobody โ it only trains the gate to cry wolf, and a gate that cries wolf is a gate people start ignoring.
- A phone-number pattern must match phone numbers, and not every digit sequence that vaguely resembles one. A false positive costs the same as a false negative in the end: both are failures of the classifier, and a privacy gate wrong in either direction erodes the trust it exists to provide. Loosen it and real data slips through; tighten it carelessly and it becomes noise people route around.
Drop the thing that is public by design, sharpen the thing that is genuinely sensitive, and you get a single coherent stance: precision is a privacy feature. A gate that flags public identifiers and real secrets with equal alarm has no signal. One that knows the difference can be trusted to mean it.
Finally, the check is something a human can run on demand โ naoms dataset pii-scan โ so "is this pack clean?" is a question you ask directly of an
artifact you are holding, rather than a property you take on faith from a step
that ran long ago somewhere upstream.
What was wrong
The gate started at the other door. The original design was an incoming one: scan data as it arrived into the dataset-generation machinery and refuse anything that looked sensitive.
That is the intuitive design, and it is intuitive for a good reason โ it is early, and catching a problem before it is anywhere near a shareable artifact feels obviously right. But an entrance gate inspects at ingestion and then trusts everything downstream, which means it guards a door the leak does not have to use. Every transform between the entrance and the written pack is outside its view.
The definition was off in both directions too. DIDs were in the PII pattern set, so the scan raised alarms about identifiers that are public by construction. And the phone-number pattern was loose enough to fire on digit sequences that were not phone numbers. Between them, the alerts the gate produced carried less meaning than they appeared to.
How it was fixed โ and what we are not claiming
The late-May reform is the design described above: the gate relocated to the outgoing snapshot-build boundary, DIDs removed from the PII pattern set, the phone-number pattern narrowed, and the on-demand scan command added so a pack can be interrogated directly. Same intent as before, opposite door.
One honest limit on this account. We are describing the architecture of the reform โ the gate's relocation to the outgoing boundary, plus the scan command โ from the dated directive, not from a line-by-line read of the final landed change. And the dataset effort was a large body of work still building packs through that week: the PII gate move is one decision inside it, not a claim that the whole effort was finished.
The general lesson
Two principles fall out, and they generalize well past test datasets.
Guard the exit, not the entrance. When the thing you are protecting is what leaves your trust boundary, put the gate at the boundary where it leaves, in the data's final form. Input-side checks protect inputs; output-side checks protect outputs; and it is almost always the outputs you owe a duty of care to.
Define the threat precisely or the gate becomes theater. A classifier with no precision is worse than none โ it launders false confidence. DIDs are public; phone numbers are not; encoding that distinction is the design. The gate that knows what it is actually looking for is the only one anyone will keep trusting.
Both lessons are the same lesson, really, told twice: a guard is defined by where it stands and what it is looking for. Get either wrong and you have a checkpoint that inspects the innocent and waves the guilty through โ busy, diligent, and pointed at the wrong door.
Written by AI agents from real project logs; owned and edited by Mujo.