Zero protocol · loopback only

Mr.Rao offline by design · v1.12.0

The contract never leaves the room.

PDFs, Word files, scans and email threads → clean Markdown, plain text or a Word document. NHS numbers, National Insurance numbers, SSNs, routing numbers, API keys: out, before you paste any of it into an AI — or before you file the document. No network calls. Arithmetic, not promises.

99 blank US tax forms, expected zero
1,500 English messages on the bench
AGPL-3.0 free software
127.0.0.1 the only address it listens on
session://local · redact
// ingest client_thread.eml

// 01 · engine

The number has to prove what it claims to be.

Every detector is a pattern plus a validator: the pattern proposes, the validator decides. Nothing is scored, nothing is thresholded, and the same text always gives the same result — every replacement can be explained by pointing at the rule that produced it.

01 / ARITHMETIC

Where there is a check digit, it has to add up

NHS number: mod-11. ABA routing number: the weighted 3-7-1 sum, plus the prefix ranges actually in use. Canadian SIN: Luhn. Australian ABN: mod-89. TFN: weighted mod-11. Passport MRZ: the ICAO 9303 check digits — document, birth, expiry and composite.

02 / NO CHECK DIGIT

And where there isn't, we say so

NINO, SSN, ITIN and UK postcodes carry no checksum at all. There the detector can only check the structure and rule out the ranges the issuer never assigned — it reduces false positives, it does not eliminate them.

So nothing is redacted on bare digits: either the punctuation identifies the format, or a context word sits next to the number. Measured: on 20,000 random nine-digit sequences the SSN structural check accepts nearly 90% of them.

03 / SUSPECTS

Zero is not the same as clean

“3 redactions · 2 to check”. Anything that looks like personal data but cannot be proven is flagged, not hidden — masked to a stub (RS••••••••••••2S), enough to find it in the document, not to read it.

// 02 · threat

The enemy is not the AI. It is the route.

To get a model to reason about a contract, almost every tool asks you to upload the file first. In that moment names, NHS numbers and account details are out of the building — on someone else's disk, under someone else's retention policy. Mr. Rao breaks the chain: it converts and redacts here.

⚠ The usual route

contract.pdf
→ upload to a SaaS converter
→ raw text
→ paste into ChatGPT
personal data: in the clear, out twice
PROTOCOL

● The Mr. Rao route

contract.pdf
→ 127.0.0.1 only
→ redaction + suspects
→ Markdown · human review
the file: it never left the machine

// 03 · how it is put to the test

Documents where the right answer is zero.

On a real document you cannot tell whether a replacement was warranted: you judge it by eye, and the eye gets tired. So the engine is measured first on paper that contains no personal data at all — there every replacement is an error, and there is nothing left to interpret.

01 / BLANK FORMS

99 US tax forms

Blank US federal tax forms, collected as a zero-truth set: printed forms, no taxpayer, no figures. The correct number of redactions is zero, so every replacement counts as an error and there is nothing left to interpret. This bench exists because of a defect found exactly that way: on a blank US tax form the engine once produced 22 replacements.

02 / REAL PROSE

1,500 English messages

Mailing-list messages in English: how it behaves on text people actually wrote — signatures, quoted replies, addresses in running prose — rather than on sentences built to make it succeed.

03 / THE RULER

Checked against the standards, not against itself

Each English validator ships with its own test vectors, and every vector states where the value came from — a published example from the issuing body, or a value built by applying the algorithm. The check digits in the test material are computed by a second implementation, independent of the engine, and verified against the published vectors for ISO 13616 and Luhn. A measurement that asks the product what is correct can never report that the product is wrong.

// 04 · what it does

Everything that stays in the room.

InputPDF, DOCX, XLSX, PPTX, HTML, CSV, images, EML — MarkItDown plus offline OCR
Anglo formatsNHS number, National Insurance number, SSN, ITIN, ABA routing number, Canadian SIN, Australian ABN and TFN, UK postcode, passport MRZ lines — each with its own checksum where one exists · they travel together as one pack, which can be switched off in a single move (--no-pack-en)
Also redactedEmails, phone numbers, names, addresses, payment cards (Luhn), IBAN (mod-97), URLs, API keys and secrets
OutputMarkdown .md, plain .txt and Word .docx, all already redacted · the .docx is rebuilt from the redacted text — it is not the original with black boxes drawn on top, and there is no text hiding under them
InterfaceIn English, picked up from your browser · the produced document follows the same language
Local securityHost allow-list, CSRF Origin check, read-only GET, bound to 127.0.0.1
LicenceAGPL-3.0 · the code can be read · nothing phones home

// 05 · operational honesty

What we do not promise — deliberately.

A security officer trusts whoever declares the limits. Ours are in the README, in PRIVACY.md and in the product itself.

Names in English: the narrow set

Titles, openings, sign-offs and email adjacency only. A name in running text survives — it is the first thing to know before trusting this on English prose, and the full reasoning is written out in PRIVACY.md.

This is not strong GDPR anonymisation

It is assisted redaction. The context of the document remains, and re-identification from context is still possible. Human review is required.

On faded photocopies coverage collapses

It is not the resolution: between 300 and 100 DPI, on a clean scan, coverage does not get worse. It is the quality of the mark. On a faded photocopy at 200 DPI — a document a person reads without effort — 47% of the data is redacted, 38% is lost silently, and of what stays readable the suspects flag 4 items out of 28. Measured, not estimated.

Two neural networks, but upstream

The package carries ~30 MB of .onnx models (RapidOCR, which reads scans) and a 3 MB one that guesses file types. They run offline and decide nothing. The flip side holds too: what the OCR misreads, the engine cannot judge well.

Formats outside these countries

The UK, US, Canadian and Australian formats listed above have dedicated detectors. A German phone number or a Spanish NIF does not: on those documents the filter sees less than it appears to.

Single user, local

No authentication. Exposing the port to a network without a proxy in front is a deliberate mistake.

Windows will say “unknown publisher”

The package is not Windows code-signed yet, so the warning appears — and you should see it. An application for free code signing has been submitted to the SignPath Foundation. Meanwhile every release ships SHA-256 sums and Sigstore attestations, which tell you which build produced the file — a stronger guarantee that Windows happens not to read. What will and will not change is written in the code signing policy.

Download. Extract. Stay offline.

Portable Windows build, no Python needed. Or clone the repository and run the tests yourself. If the engine gets something wrong on a document of yours (no real data in issues, please), say so: it is the only way it improves.

↓ MrRao-Portable.zip github.com/AntonioRao/mr-rao

// 06 · direct line

Reports, ideas, pieces that do not add up.

Written and maintained by Antonio Andrea Rao. Send an email or reach me on LinkedIn: no contact forms, no tracking — like the rest of the project.