How it works

Every OCR line passes two layers:
  1. Rules with checksums: emails, phones, IBAN (mod-97), cards (Luhn), tax and national IDs, secrets after “password:” or “token:”, and person names (honorifics, “Name:” labels, Russian name forms).
  2. A PII model, run locally: GLiNER2 privacy filter. No outside service sees the unredacted text.
Matching boxes are blurred on the keyframe before it is stored or sent to a model.

Agent records

The same two layers run on the text values of every agent record a check sends to a model (judge, router) and on the record stored in the check log. Each value is checked with its field name (contact: Jo Doe), and matches become placeholders ([PERSON], [EMAIL]). Short values and identifiers get the rules layer; free text also goes to the local model when it is loaded. Precise rules still run on the original values, on the server. See Data sent to models.

What we measured

Caught: names, emails, phones, IBANs with and without spaces, card, SSN, German tax ID, Russian passport, INN, SNILS, date of birth.
Known gaps.
  • Missed a Russian street address.
  • Box edges can leave the first or last character visible.
  • The test screens were synthetic.
  • The evals ran with both layers. The hosted preview runs the rules layer only (to fit a small server), so expect lower recall there, especially for names and addresses.