{"id":51406926,"url":"https://github.com/karolpolikarp/anonimizator","last_synced_at":"2026-07-04T12:00:28.663Z","repository":{"id":369125907,"uuid":"1288400806","full_name":"karolpolikarp/anonimizator","owner":"karolpolikarp","description":"Lokalny anonimizator polskich danych osobowych (PII) — PESEL, NIP, REGON, IBAN, nazwiska. 100% na Twoim komputerze, zero centralnego serwera.","archived":false,"fork":false,"pushed_at":"2026-07-03T17:17:02.000Z","size":51,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-03T19:15:58.583Z","etag":null,"topics":["anonymization","gdpr","offline-first","pesel","pii","polish","privacy","rodo"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karolpolikarp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-07-03T15:04:42.000Z","updated_at":"2026-07-03T17:17:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/karolpolikarp/anonimizator","commit_stats":null,"previous_names":["karolpolikarp/anonimizator"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/karolpolikarp/anonimizator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolpolikarp%2Fanonimizator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolpolikarp%2Fanonimizator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolpolikarp%2Fanonimizator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolpolikarp%2Fanonimizator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karolpolikarp","download_url":"https://codeload.github.com/karolpolikarp/anonimizator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolpolikarp%2Fanonimizator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35120682,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["anonymization","gdpr","offline-first","pesel","pii","polish","privacy","rodo"],"created_at":"2026-07-04T12:00:17.653Z","updated_at":"2026-07-04T12:00:28.634Z","avatar_url":"https://github.com/karolpolikarp.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anonimizator\n\n[![CI](https://github.com/karolpolikarp/anonimizator/actions/workflows/ci.yml/badge.svg)](https://github.com/karolpolikarp/anonimizator/actions/workflows/ci.yml)\n[![Release](https://img.shields.io/github/v/release/karolpolikarp/anonimizator)](https://github.com/karolpolikarp/anonimizator/releases)\n[![Licencja MIT](https://img.shields.io/badge/licencja-MIT-blue.svg)](./LICENSE)\n\nLokalny anonimizator polskich danych osobowych (PII). Zamienia PESEL, NIP, REGON, numery kont,\nnumery dowodów, e-maile, telefony, adresy oraz imiona i nazwiska na neutralne placeholdery —\n**zanim** tekst trafi do czatu z modelem językowym, e-maila, zgłoszenia czy bazy danych.\n\n**Nikt niczego nie serwuje centralnie i nie przetwarza Twoich danych.** Pobierasz aplikację\nz tego repozytorium i uruchamiasz na własnym komputerze — cała anonimizacja odbywa się\nlokalnie, w Twojej przeglądarce. Możesz rozłączyć internet i sprawdzić.\n\n![Aplikacja Anonimizator — tekst źródłowy po lewej, zredagowany wynik z podświetlonymi maskami po prawej](docs/screenshot.png)\n\n## Pobierz i używaj (bez instalacji)\n\n1. Wejdź w [**Releases**](https://github.com/karolpolikarp/anonimizator/releases) i pobierz\n   `anonimizator-offline.zip`.\n2. Rozpakuj i otwórz `index.html` **podwójnym kliknięciem** — aplikacja działa prosto z dysku,\n   bez serwera, bez instalacji, bez internetu.\n3. Wklej tekst albo upuść plik (`.txt`, `.docx`, `.pdf`) — po prawej dostajesz wersję\n   zredagowaną do skopiowania. Pliki Word i PDF są czytane w całości lokalnie, jak wszystko tutaj.\n\nAlternatywnie sklonuj repo i odpal z kodu (sekcja „Dla programistów\" niżej).\n\n## Formy użycia — jeden silnik\n\n- **Aplikacja w przeglądarce** (`apps/web`) — patrz wyżej; 100% offline.\n- **Biblioteka npm** (`packages/core`, pakiet `anonimizator`) — zero zależności, działa w Node,\n  Deno, Bun i przeglądarce.\n- **CLI** — `anonimizator plik.txt`, także stdin → stdout do potoków.\n- **Opcjonalny lokalny NER** (`services/ner`) — usługa spaCy PL na Twoim komputerze,\n  podnosząca wykrywalność rzadkich nazwisk (szczegóły niżej).\n\n```\nNazywam się Jan Kowalski, PESEL 44051401359, ul. Polna 12/3, tel. 600 700 800.\n                                    │\n                                    ▼\nNazywam się [IMIĘ I NAZWISKO], PESEL [PESEL], [ADRES], tel. [TELEFON].\n```\n\n## Dlaczego mało fałszywych trafień\n\nTam, gdzie format ma **sumę kontrolną** (PESEL, NIP, REGON, IBAN, nr dowodu), anonimizator ją\n**weryfikuje** — przypadkowy ciąg 11 cyfr (sygnatura akt, numer sprawy) nie zostanie uznany za\nPESEL. Dodatkowo strażnik kontekstu rozpoznaje odwołania do przepisów („art. 123 456 789\",\n„poz. …\", „Dz.U. …\") i nie maskuje ich jako telefonów. Redakcja jest **idempotentna** — ponowny\nprzebieg po zredagowanym tekście niczego nie psuje.\n\n## Co wykrywa\n\n| Dane | Metoda | Placeholder |\n|---|---|---|\n| PESEL | 11 cyfr + suma kontrolna | `[PESEL]` |\n| NIP | 10 cyfr (też z myślnikami) + suma kontrolna | `[NIP]` |\n| REGON | 9/14 cyfr + suma kontrolna | `[REGON]` |\n| IBAN / nr konta | mod 97 lub kontekst „konto/rachunek\" + 26 cyfr | `[NR-KONTA]` |\n| Nr dowodu | 3 litery + 6 cyfr + suma kontrolna | `[NR-DOWODU]` |\n| E-mail | wzorzec adresu | `[EMAIL]` |\n| Telefon | 9 cyfr, opcjonalnie +48 | `[TELEFON]` |\n| Kod pocztowy | XX-XXX | `[KOD-POCZTOWY]` |\n| Data urodzenia | data z kontekstem „ur./urodzony\" | `[DATA-URODZENIA]` |\n| Adres | ul./al./os./pl. + nazwa + numer | `[ADRES]` |\n| Imię i nazwisko | słownik ~200 imion + ~230 najczęstszych nazwisk (z odmianą) + wyzwalacze kontekstu („nazywam się\", „Pan/Pani\") | `[IMIĘ I NAZWISKO]` |\n\n## Ograniczenia (przeczytaj przed użyciem)\n\nWykrywanie **imion i nazwisk warstwą podstawową jest heurystyczne** — rzadkie nazwisko bez\nimienia ze słownika i bez wyzwalacza kontekstu może przejść niewykryte. Lukę domyka opcjonalny\nlokalny NER (niżej), ale zasada pozostaje: to narzędzie pomocnicze — **zawsze przejrzyj wynik\nprzed udostępnieniem**.\n\n## Opcjonalny lokalny NER (rzadkie i odmienione nazwiska)\n\nZdanie „Wczoraj Bąkiewicz podpisał umowę z Szczepankowską\" nie zawiera ani imienia ze słownika,\nani wyzwalacza kontekstu — warstwa regex go nie zamaskuje. Rozwiązaniem jest **NER** (model\nspaCy PL rozpoznający osoby z kontekstu zdania), uruchamiany **na Twoim komputerze**:\n\n```bash\ncd services/ner\ndocker compose up -d      # usługa na 127.0.0.1:8090 (tylko localhost)\n```\n\nPotem w aplikacji webowej zaznacz „Użyj lokalnego NER\". Architektura jest **fail-safe**:\n\n- NER dostaje tekst JUŻ po redakcji strukturalnej — **nigdy nie widzi** surowego PESEL/NIP;\n- gdy usługa nie działa / nie odpowiada / przekroczy timeout, wynik zostaje na warstwie\n  regex + sumy kontrolne — ochrona nigdy nie spada do zera;\n- circuit breaker przestaje odpytywać padniętą usługę (3 porażki → 30 s przerwy).\n\nZ biblioteki: `import { redactPIIFull } from 'anonimizator/ner'` —\n`await redactPIIFull(tekst, { url: 'http://127.0.0.1:8090' })`.\nSzczegóły: [`services/ner/README.md`](./services/ner/README.md).\n\n## Użycie — biblioteka\n\n```bash\nnpm install anonimizator\n```\n\n```ts\nimport { redactPII, hasPII, describeFindings } from 'anonimizator';\n\nconst { redacted, found } = redactPII('Mój PESEL to 44051401359');\n// redacted → 'Mój PESEL to [PESEL]'\n// found    → [{ type: 'PESEL', count: 1 }]\n\nhasPII('czysty tekst');            // false\ndescribeFindings(found);           // ['PESEL']\n```\n\nOpcjonalny drugi parametr pozwala wybrać typy i podmienić placeholdery:\n\n```ts\n// maskuj tylko PESEL i e-mail\nredactPII(tekst, { types: ['PESEL', 'EMAIL'] });\n\n// własny placeholder (bez cyfr i „@\" — inaczej łamiesz idempotencję)\nredactPII(tekst, { masks: { PESEL: '[UKRYTO]' } });\n\n// spójna pseudonimizacja: ta sama osoba → ta sama etykieta (także w odmianie)\nredactPII('Kowalski pozwał Nowaka. Kowalskiemu zależy na ugodzie.', { pseudonyms: true });\n// → '[OSOBA-A] pozwał [OSOBA-B]. [OSOBA-A] zależy na ugodzie.'\n// (w CLI: flaga --osoby; w aplikacji: „Rozróżniaj osoby\" w panelu „Co maskować\")\n```\n\nEksportowane są też walidatory sum kontrolnych: `isValidPesel`, `isValidNip`, `isValidRegon9`,\n`isValidRegon14`, `isValidIban`, `isValidDowod`.\n\n**Ważne:** `found` zawiera wyłącznie typ i liczbę wystąpień — **nigdy oryginalne wartości**,\nwięc można go bezpiecznie logować.\n\n## Użycie — CLI\n\n```bash\nnpx anonimizator dokument.txt                  # wynik na stdout, statystyki na stderr\nnpx anonimizator dokument.txt --out czysty.txt\ntype dokument.txt | npx anonimizator           # Windows\ncat dokument.txt | npx anonimizator            # Linux/macOS\n```\n\n## Dla programistów\n\n```bash\nnpm install\nnpm run dev        # http://localhost:5173 (hot reload)\nnpm run build      # statyczne pliki w apps/web/dist — działają też otwarte prosto z dysku (file://)\nnpm test\n```\n\nAplikacja nie ma backendu, analityki ani żadnych zapytań sieciowych — cała logika wykonuje\nsię w przeglądarce. Jedyny wyjątek to świadomie włączony lokalny NER (żądania idą wyłącznie\npod adres localhost wskazany przez użytkownika).\n\n## Struktura repozytorium\n\n```\npackages/core/    # silnik redakcji (TS, zero zależności) + klient NER + CLI + testy (Vitest)\napps/web/         # statyczna aplikacja (Vite, bez frameworka), działa z file://\nservices/ner/     # opcjonalna lokalna usługa NER (Python/FastAPI + spaCy PL, Docker)\n```\n\n## Testy\n\n```bash\nnpm test          # sumy kontrolne, maskowanie, fałszywe trafienia, idempotencja,\n                  # opcje types/masks, fail-safe NER (mock), circuit breaker\n```\n\n## Roadmapa\n\n- [ ] NER bez Dockera: model ONNX odpalany bezpośrednio w przeglądarce (transformers.js) —\n      pełny recall nazwisk bez instalowania czegokolwiek.\n- [x] Konfigurowalne placeholdery i wybór typów do maskowania (v0.2.0).\n- [x] Obsługa plików DOCX w aplikacji webowej — ekstrakcja tekstu lokalnie (v0.3.0).\n- [x] Obsługa plików PDF — pdf.js w buildzie single-file, w pełni offline (v0.4.0).\n      PDF-y bez warstwy tekstu (skany) dostają jasny komunikat — OCR nie jest wspierany.\n\n## Pochodzenie\n\nSilnik redakcji został wydzielony z produkcyjnego kodu [JakiePrawo.pl](https://jakieprawo.pl),\ngdzie maskuje dane osobowe w pytaniach użytkowników, zanim trafią do modelu językowego\n(zgodność z RODO). Reguły i testy regresji pochodzą z realnych przypadków.\n\n## English (summary)\n\n**Anonimizator** is a local-first redactor for Polish PII (personal data): PESEL, NIP, REGON,\nIBAN and national ID numbers are validated against their checksums (very few false positives);\ne-mails, phones, addresses and person names are matched heuristically, with an optional\nself-hosted spaCy NER service for rare surnames. Ships as a zero-dependency npm library +\nCLI (`anonimizator`), and a single-file offline web app (grab `anonimizator-offline.zip`\nfrom Releases and just open `index.html` — nothing ever leaves your machine). MIT licensed.\n\n## Licencja\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarolpolikarp%2Fanonimizator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarolpolikarp%2Fanonimizator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarolpolikarp%2Fanonimizator/lists"}