GDPR Guardian, experimental first-level filter before the AI

No document kept, neither here nor on the server Source code FR

Input

How you work

Figures: internal measurement, optimisticpublic protocol 1.2, 27 October 2026.Figures: to come.

Settings

Experimental tool, no warranty: the output may still identify someone. Check it; you remain responsible for how you use it. Disclaimer

Ctrl + Enter anonymise · Ctrl + Shift + C copy · Ctrl + S download · Esc clear the input

Online service with an API key (on request: contact@gardienrgpd.fr), processed in memory in France, nothing of it is kept. Without a key: the local version.

Session queue

Each document is anonymised on its own: its placeholders apply to it alone.

    Empty.

    Result

    The result shows here:

    [PERSON_1] annoys [PERSON_2]. [PERSON_2] hits [PERSON_1].

    The roles survive, the identities do not, with no way back.

    Video

    Close

    The launch video

    Silent video: all its text is in the transcript. Short 4:5 cut for social feeds: MP4, 5.1 MB.

    The video’s index dates from its rendering; the current figure: Protocol and scores.

    The challenge

    Close

    Every day, real documents end up in AI assistants

    Contracts, HR files, medical reports, bank statements: they are pasted into AI assistants to be summarised, translated or analysed.

    Usually in good faith, and without knowing the rules. Personal data then lands with a third party, often with no legal basis or processing agreement, sometimes outside the European Union: exactly what the GDPR regulates. Once sent, it does not come back.

    The challenge comes down to three demands that pull against each other: keep the logic of the text, so the AI stays useful; make any way back impossible; stay fast and frugal enough never to be bypassed. Hence a workspace, not a page: drop, take back, move on, all day long.

    A first-level filter

    • What it does. It masks direct identifiers: names, contact details, numbers, IP addresses, dates of birth… It relies on known formats, check digits, context and your organisation’s own rules. The same result every time, a named reason for every placeholder, no way back.
    • What it leaves to the next level. Whatever depends on meaning: health, opinions, trade union membership, offences… (GDPR, Art. 9 and 10), and clues that, put together, point to someone (job, town, date). Today, our Claude skills hand these, on a best-effort basis, to a light model of your own AI: the pragmatic solution.
    • Next. A governed LLM stage, for what depends on meaning, under study. The intention: a model kept under control, written rules, decisions checked and measured like the first level. No date announced.

    The story

    Close

    Guillaume annoys Nadège

    Hiding the names is not enough: the AI must still understand who does what.

    Original

    Guillaume annoys Nadège. Nadège hits Guillaume.

    Naive masking

    [NAME] annoys [NAME]. [NAME] hits [NAME]. Who hit whom? An AI can only guess.

    GDPR Guardian

    [PERSON_1] annoys [PERSON_2]. [PERSON_2] hits [PERSON_1]. The roles survive, the identities do not.

    On the workspace’s example, the engine turns “Jean Dupont”, “Mr Dupont” and “DUPONT Jean” into one placeholder, [PERSON_1]; “Ms Claire Martin” becomes Ms [PERSON_2]. The title stays, as it helps to follow the text. The amount stays: it is not personal data. The invoice number may be masked as a precaution.

    Not always, though: measured on 26 October on 2,463 fictitious people, the deployed engine gives 92.2% of them a single placeholder; 192 are split across several and 44 share another person’s.

    Each document is anonymised separately, with its own key, destroyed afterwards: [PERSON_1] in one document is not necessarily the same person in another. Later: a set of documents processed under one code, the same placeholders throughout, still with no way back (key destroyed at the end).

    Architecture

    Close

    Online or on your machine: same software

    Same package, same version: online with an API key, or on your own computer so that GDPR Guardian sends nothing. The online service guards against abuse with a rate limiter that lives in memory only.

    Online

    1. Browser, AI agent, scriptREST or MCP over HTTPS, with an API key; this workspace calls the same API.
    2. TLS 1.2/1.3 · nginxOVH, in France: firewall, automatic updates, no core dumps, no access log.
    3. Unix socketin a memory-backed folder: no port open between nginx and the service.
    4. Container with no network at allread-only, no privileges.
    5. Front door and rate limiterthe IP address immediately becomes a keyed pseudonym (key renewed every 24 hours), held in memory, never written, forgotten after 10 idle minutes.
    6. A fresh process per requestisolated, memory capped, killed at its deadline; it cannot start anything.
    7. Resultin the response, the same way back, nowhere else. Agents’ deferred uploads: readable with a random 256-bit identifier given to the requester alone, deleted 2 min after reading, 30 min at most.
    8. Site daemona datagram without content (kind, format, size, duration, success, origin) feeds the live figures.

    On your computer

    1. Original documentin a folder you allowed; it does not move.
    2. GDPR Guardian, localsame Rust engine, no connection during processing; fully local option: a Docker container with no network.
    3. AI client, over MCP stdioClaude Code, Claude Desktop, Cowork, VS Code or Cursor: it passes the path and receives the anonymised Markdown.
    4. AI modelreceives the anonymised text; with the skills, a light model has read it first (two steps). GDPR Guardian sends nothing and asks the assistant never to open the original.

    Irreversible by construction

    • One key per document, then destroyed. 256 random bits; mentions of one person are matched through keyed BLAKE2b digests, never through their value. The key is never written; online, it disappears with the request’s process.
    • No mapping table. Nothing ties a placeholder to a name, neither on your side nor on the server: nothing to steal, nothing to restore, not even for us.
    • Explainable. No LLM, by design for a first level: every placeholder comes from a named rule (check digits, keyword, form label, your organisation’s own rule).

    One CPU core is enough

    0.56 ms for a 2 KB document, on one core (median). First two rows: Ryzen 7 5800H, shared laptop, Windows 11, on 25 October 2026; the others: Linux, earlier measurements, the service on 16 cores. A Rust core, with results identical to the Python reference engine; no GPU.
    Throughput per core, 2 KB documents, the cost of each call included3.4 MB/s
    A 10 MB text, one core2.1 s
    Service, 2 KB text, median measured on the server, without the Internet trip5.2 ms
    Same test, 99% of requests under8.6 ms
    Internal benchmark, no rate limiter: 100 PDFs of 10 MB sent at once8.7 s
    Service Docker image · Rust core103 MB · 3.6 MB

    Protocol and scores

    Close

    How we grade ourselves

    An index is only worth something if anyone can check and recompute it. These scores measure the first-level filter only. The results first, then protocol 1.1 point by point; the reference text is PROTOCOLE.md.

    Version 1.2, declared before its campaign. Two scores per mode, strong and essential: anonymisation and useful codes lost (decoys masked: order, invoice, product numbers that designate nobody). In strong mode this loss is shown without failing the measurement, since masking these codes is intended there; in essential mode, the 10% guard stays. The readability guards (neutral text over-masked at most 2%, precision at least 70%) apply to both modes. Version 1.2 will be measured on engine 1.0.2, released on 27 October 2026; until its campaign, the per-mode scores on the home page are an internal measurement. The 1.1 result stays published as it is.

    Run 1.1: results published when it ends.Published result: protocol 1.1 · engine 1.0.1+4bb5c465425e, run of 26 October 2026.
    NormalisedDifficult
    Confidence index96.9%not measured yet84.0%not measured yet
    95% interval96.2–97.6%not measured yet83.9–84.1%not measured yet
    Direct mentions fully masked99.3%not measured yet95.0%not measured yet
    Documents scoredper family, below548,907not measured yet
    Make-up4 families, equal weight4 families, equal weight3 groups, pooled
    Whole run1,019,385 documents sent, 8,178 of them real annotated documents from 14 corpora, both halves and the corpora published apart includednot measured yet

    Per family, protocol 1.1

    Standard profile, country FR (other languages: their own). “—”: not measured yet, or not applicable. ParlaMint annotates only the speakers and the people on its list: an upper bound. Guards (%): neutral text masked by mistake 0.07, decoys 3.7. Judilibre: 300 decisions, 11.5 masked spans per 10,000 characters.
    FamilyScored docu­mentsNo leak (%)Mentions masked (%)Precision (%)
    Normalised documents, the index
    Synthetic, 10 seeds, with decoys450,00097.299.698.8
    BODACC, French company notices1,33597.599.599.2
    BOAMP, French procurement notices1,40895.198.387.7
    ParlaMint-FR, National Assembly debates14397.999.8—
    Difficult documents, the second score
    Damaged everyday formats, 25 kinds284,08184.996.598.8
    Deliberate obfuscations, 25 kinds252,89586.694.598.8
    OCR noise (0/O, 1/l…)11,9319.272.898.6
    Published apart, outside both scores
    Old French newspapers, low-quality OCR27217.355.275.5
    MAPA FR, EU legal texts in French616.733.146.8
    Other languages: DE, ES, IT, NL, PT, EN6465.714.0—

    Known limits

    • A first-level filter, which lowers the risk without removing it; not a GDPR certification.
    • Leaks found with engine 1.0: a line break inside an identifier, the spaced-out letters of a PDF, slashes or double spaces between digits, the addresses of BOAMP notices, French bank details (RIB) written field by field.
    • Text only: the conversion of PDF, Word and Excel files is not measured; a scanned page with no text is dropped.
    • Names still missed by engine 1.0.2: written in lower case (“rdv avec julien dupont”), a rare surname that is also a common French word (“Albéric Fontanelle” without “M.”), “né Martin le 12/03/1985”, some pseudonyms.
    • Passwords: only direct forms are recognised (“password: …”, “my password is …”); as soon as a word comes in between (“the password for the account: …”), the secret may stay readable.
    • Through the API, a country chosen without France masks neither names nor addresses.
    • The engine also masks by mistake (Precision column).
    • The first level does not read meaning: neither sensitive data (GDPR, Art. 9 and 10) nor cross-checks (job title, place, date) that can re-identify someone. Today: the Claude skills’ second pass, best effort, not measured. Next: the governed LLM stage.
    Internal regression set, every release
    Automated tests, Windows · Linux6,678 · 6,626
    Tests in the offline image12
    Rust and Python parity documents, identical outputs1,000
    Red team: adversarial documents6,192
    Red team: mutation operators51

    1. What we measure, and for which use

    One question: in what share of documents does the service leave at least one direct identifier readable? The intended use, as registered: “texts organisations send to an AI: e-mails (headers, signatures, quoted threads), requests pasted into a chat, internal documents (minutes, HR letters, contracts, invoices, CRM notes, tickets), in French, as text or office files, written in good faith” (an employee is not trying to fool the tool); what the plan does not cover is declared in point 8. Every document in the French scope goes through the service’s text route (POST /v1/anonymize/text) with the default settings: country FR, standard profile, French placeholders. For every scored document, the truth is known (the “gold”).

    2. What a leak is

    A document leaks as soon as a single alphanumeric character of a direct-identifier mention stays readable in its place in the output: the last digit of a phone number is enough. Direct identifiers: a natural person’s name, a postal address (street or postal box, with postcode and town), a phone number, an e-mail address and the other direct identifiers (national numbers, IBAN, cards, plates…), whoever they belong to. Not counted: a company name (GDPR, recital 14; CJEU, C-92/09 and C-93/09), a town named as a place, a postcode followed by a town with no street. A sole trader is a person: their name, SIREN and SIRET count.

    The output is aligned on the input; whatever may be visible counts as visible. A document refused, failed, or whose output does not align counts as a leak. Documents with no direct mention are left out of the scores, but counted and published.

    3. The two scores, and how they are computed

    • Normalised documents, the headline score. For each of the four families (synthetic, BODACC, BOAMP, ParlaMint-FR), the share of scored documents with no leak; then an equal-weight average, a quarter each: the number of documents gives no weight. Declared target: 95% or more, a goal and not a condition; the figure is published whatever it is.
    • Difficult documents, the second score. The same measure over the whole red team, 51 operators in three groups, pooled: every mutated document counts once, so an operator weighs the number of documents it alters (in the 1.0 run, the three groups made 51.8%, 46.1% and 2.2% of the 548,907 mutated documents). It is the measure of the red-team family of protocol 1.0: the two can be compared.
    • Published with each score. Mention recall (share of direct mentions fully masked); per family, precision (share of masked characters that fall on personal data of the gold).
    • Guards. An engine that masked everything would score 100%: both scores are published only if, in the same run, neutral text masked by mistake stays at most 2% (synthetic), decoys masked by mistake at most 10%, and precision at least 70% on BODACC and on BOAMP. Overriding this must be declared publicly.

    4. The corpora

    • Synthetic FR. A public generator (Faker 40.43.0, fr_FR), 9 document types, 30 templates, with decoys that must not be masked (amounts, invoice and order numbers, legal references, company identifiers); 10 fresh seeds, 2026102501 to 2026102510, 45,000 documents each; about 6% come from two English templates (a ticket, an e-mail) in a French context. The development seed (20261024) is refused by the code.
    • Annotated real corpora. BODACC, French company notices naming a natural person, published in September 2026 (2,693 documents); BOAMP, public procurement notices 2022-2023 (3,000); ParlaMint-FR, National Assembly debates (300). Only their test half counts: a fixed split by SHA-256 digest of the document identifier, written on 25 October 2026; rules are tuned on the other half.
    • Red team. 12,000 base documents (seeds 2026102521 to 2026102530) run through 51 operators: 548,907 mutated documents. Damaged everyday formats, 25: a line break inside an identifier, the spaced-out letters of a copied PDF, spaces, separators, case, accents… Deliberate obfuscations, 25: substitute alphabets, look-alikes from other scripts, invisible characters, disguised e-mail addresses. OCR noise, 1: 0/O, 1/l, 5/S, 8/B confusions.
    • Published apart, in neither score. Old press (Europeana and HIPE, 655 documents; low-quality OCR: degraded performance); MAPA FR, EU legal texts (12 documents, 6 of them scored in the test half); other languages (MAPA DE, ES, IT, NL, PT, MEDDOCAN, German LER, TAB); and a negative control, Judilibre: 300 decisions already pseudonymised, with no gold, whose masked spans are counted.

    5. Plan size and interval

    Registered plan: 1,019,385 documents sent to the service (450,000 synthetic; 12,000 base documents and 548,907 mutated documents of the red team; 8,478 real documents, the corpora published apart and the control included). Its SHA-256 digests are registered: synthetic 0b91be78…, red team d984ee1b….

    95% interval: bootstrap resampling of documents, 2,000 draws, seed 20261025, percentiles 2.5 and 97.5; stratified by family for normalised documents, by group for difficult documents. It only covers the chance of the draw, neither gold errors nor the choice of families; for difficult documents it is too narrow (the variants of one base document are drawn as if independent).

    6. The run

    • Registered beforehand. The digests of the protocol, its specification, the tool, the bundle that runs, the real corpora and the frozen engine (version, packs, outputs on the probe) are published in the public repository before the launch; every result copies them; a bundle changed after it was built is refused.
    • The real production service, through its local Unix socket, with a local token read on standard input (never passed as an argument nor written by the tool). Visitors come first: the run gives way as soon as someone waits. Its documents count in the live figures of the home screen.
    • The measuring tool runs in a throwaway container of the service’s exact image: no network, read-only system, no privileges, 2 GB of memory without swap, no core file.
    • One engine per run. The service image, version, packs and outputs on a fixed probe of 200 documents are checked at the start, every minute, after any restart and at the end; any difference stops everything.
    • Real corpora in RAM only (/dev/shm, swap off), run first and then wiped. The tool never writes a text: only counters, bits and digests.
    • To the end. The run goes to completion, with no stopping when the figure looks good and no best attempt kept. An overload (429, 503) is waited for and retried, then pauses the run after 30 minutes on one document; it never counts as a leak.

    7. What is published

    Dated raw results, never overwritten (benchmarks/results/protocol-1.1-<date>.json and .md): both scores and their intervals, every family and group, every red-team operator, every seed, the families published apart, the history of earlier measurements of the test halves and declared departures.

    The protocol 1.0 result stays published: 61.8% (95% CI: 58.6–66.9%), 7 families, 1.0 result.

    8. Caveats

    • Test halves not blind. Measured at least nine times before, the 1.0 run included, their scores were known while engine 1.0.1 was tuned: real-corpus figures are optimistic. Fresh data is the commitment for the next version.
    • Real weight. The run sends more than a million documents, but three quarters of the headline score rest on the scored documents of the test halves of BODACC, BOAMP and ParlaMint-FR: 2,886 in the 1.0 run (1,335, 1,408 and 143); ParlaMint-FR alone, a quarter of the score, on 143. These corpora are not texts sent to an AI.
    • ParlaMint-FR, an upper bound. It annotates only the speakers and the people on its list: a name left unannotated does not count as a leak. With the synthetic family (the same templates the engine was tuned on), these two favourable families weigh half of the headline score.
    • The choice of the two scores was made on 26 October 2026, before any 1.1 measurement but after the 1.0 per-family figures, while engine 1.0.1 was being tuned, knowing that the everyday red team was the lowest family the first draft kept. On the dev halves, same engine, moving old press, MAPA FR and the red team out of the headline score, with the corrected BOAMP gold (−0.1 point), takes it from 59.7% to 82.8%; all these families stay published.
    • Not measured. The conversion of files, pasted requests and CRM notes (no template), re-identification through context: see the known limits. Measured BOAMP gold errors: 2.1% of mentions.

    9. Replay

    Everything is public: executable definitions (tools/protocol/spec.py), the tool and its tests. From the repository root, with no service:

    python -m tools.protocol plan --count
    python -m tools.protocol bundle --out gg-protocol.pyz
    python -m tools.protocol registration --bundle gg-protocol.pyz

    The first gives back the plan’s numbers and digests; the other two, the bundle (byte-for-byte reproducible) and the registered digests. Real corpora, the run and the merge into the site: section 10 of PROTOCOLE.md; digests published before the run: 1.1 registration, 1.2 registration; raw results and history: benchmarks/results.

    Use it

    Close

    Beyond this page

    The same service from your AI assistant or your own programs, with an API key given on request (contact@gardienrgpd.fr) with a data processing agreement; without a key, on your own computer, with the local version.

    The pragmatic solution, in two steps

    1. The Guardian first. It plugs into the AIs people already use: Claude through the MCP server and the skills, any MCP client, the API. The skills make it the rule: every document goes through the Guardian first. An instruction given to the AI, not a lock: a client without the skills, or text pasted into the chat, is not covered.
    2. Then a light model. A light model of your own AI reads the anonymised document only and, on a best-effort basis, flags or masks what the first level cannot see: health, beliefs, opinions, trade union membership, sex life, offences and similar clues.

    Not perfect, but pragmatic: a high level of protection for everyday use. That is our assessment, not a measurement: only the first level is measured (scores). Under study, nothing decided, no date: running this second step through the API of Mistral AI, a European provider, within the governed LLM stage.

    In Claude, over MCP, with your key

    Address: https://api.gdprguardian.com/mcp (or api.gardienrgpd.fr/mcp). Claude Code:

    claude mcp add --transport http gdprguardian https://api.gdprguardian.com/mcp \
      --header "Authorization: Bearer $GDPRGUARDIAN_API_KEY"

    claude.ai, Claude Desktop, Cowork: add this address as a custom connector, with the header Authorization and the value Bearer followed by your key. For a file, create_upload gives a command that you run yourself on your computer: the file goes straight to the service, without passing through the model; get_anonymized then reads the result, deleted 2 min after reading, 30 min at most. A text already pasted into the chat has already left: anonymize_text cannot bring it back.

    Through the REST API

    curl https://api.gdprguardian.com/v1/anonymize/text \
      -H "Authorization: Bearer $GDPRGUARDIAN_API_KEY" \
      -H 'Content-Type: application/json' \
      -d '{"text": "Mr Jean Dupont, 06 12 34 56 78",
           "label_language": "en", "explain": true}'
    
    curl https://api.gdprguardian.com/v1/anonymize/file \
      -H "Authorization: Bearer $GDPRGUARDIAN_API_KEY" \
      -F file=@contract.pdf -F label_language=en -F mode=essentiel

    Response: the anonymised text (or Markdown) and the report. Options: countries (FR by default, FR,BE, all), mode (fort by default, essentiel, personnalise; or strong, essential, custom), disable, rules, label_language, explain; the same over MCP.

    On your computer

    For very sensitive documents: the same software, free and without a key: the Claude skills archives (engine bundled, no network) or a container with no network; nothing leaves through GDPR Guardian. Installation: local version guide; questions: contact@gardienrgpd.fr.

    Limits of the online service

    Per key: one request processed at a time and two waiting, about 20 seconds of compute in advance, refilled at 0.5 s per second. Beyond that: a 429 and a delay to honour (Retry-After), which this workspace applies by itself while sending one document at a time; a saturated server (estimated wait over 10 s): 503; an upload too slow (15 s, plus 128 KiB per second of body): 408.

    Size: 50 MB per file, one million characters per text; per document, 12.5 million characters of result, 10,000 pages or slides, one million HTML tags (opening and closing), 100,000 Word paragraphs (table cells included). Very dense plain text, CSV or spreadsheets reach that ceiling before 50 MB (around 13 MB of text, 16 MB of CSV, 4 MB of spreadsheet): 413, naming the limit. An illustrated 50 MB document takes a few seconds; each may take 60 s plus 1 s per 250 KB (4 min 30 s at 50 MB).

    Minimum quality: readable text. Images and scanned pages without a text layer: not read (warning). PDF from low-quality OCR: processed, with the warning “Low-quality text (likely OCR)”.

    Open call

    Close

    To French public institutions

    “We, in the private sector, need a solution that is cheap to run and that we can trust completely.”

    “I would love one of our French schools, universities or public institutions to take up this subject, for the good of the whole community.”

    Guillaume CLEMENT, Flow Line Intégration

    AI use is not going away. A tool that protects data before it leaves should be a common good: audited, hosted and maintained over time, serving everyone, public bodies and companies alike. GDPR Guardian is ready to be taken over: MIT licence, open code, documented architecture, public protocol, published measurements. A school, a university or a public institution could:

    • audit the code and the method;
    • take over, host and run the service on public infrastructure;
    • make the governed LLM stage, the second step, a subject of study or research;
    • build the corpus of annotated office documents (PDF, Word, Excel) that is missing today to measure the conversion.

    To answer: contact@gardienrgpd.fr. No partnership exists to date: this is an open call.

    Thanks

    Close

    A tool given away, free to take further

    GDPR Guardian is offered to the world: anyone can use it, draw inspiration from it and build on it, with nothing imposed. We show our scores as they are, weaknesses included. Schools, universities, public institutions: our open call.

    Thanks to Flow Line Intégration, which offers and hosts the online service free of charge. Created by Guillaume CLEMENT, CTO Data & AI. Interface design: Claude Design.

    A feature request, a performance problem, an identifier that gets through: open an issue. Describe the shape with made-up data only, never real data: “an IBAN broken by a line break”. Security vulnerability: private report.

    Privacy

    Close

    No document kept, neither here nor on the server

    • Here. No cookie, no tracker, no third-party resource. The browser keeps only the mode you chose, with its categories and codes to keep (local storage): never a text. Your texts and results live only in this tab’s memory: “Clear everything” empties it, and so does closing the tab.
    • On the server. Each document is processed in memory in an isolated process, and nothing of it remains once the response has left; only the result comes back, to you alone. The file name does not travel: only its extension.
    • With a key and a data processing agreement. The online service processes your documents on your behalf: it is for holders of an API key, given on request with a data processing agreement. To send nothing: the local version.
    • IP address, in memory only, never written to disk, no access log. The web server keeps it as is (IPv4, or its /64 in IPv6) in its anti-abuse counters, which it recycles as traffic flows. The service replaces it at once with a keyed pseudonym, forgotten after 10 idle minutes (key renewed every 24 hours). To count visitors once a day: a keyed digest of the truncated address (/24, or /48 in IPv6) and of the browser’s user agent, key and digests forgotten every day.
    • Usage statistics: kind of operation, format, size, duration, success, origin; never the content, the file name or the IP address.
    • Controller: Flow Line Intégration (legal notice). Legal basis: legitimate interest in providing, protecting and securing the service (GDPR, Art. 6(1)(f), recital 49); the security measures meet Art. 32. Your rights (access, erasure, objection) and questions: contact@gardienrgpd.fr; complaints: the CNIL, France’s data protection authority.