tarja
EN: a Python library that finds Brazilian personal identifiers in free Portuguese text and validates their check digits, so a number that merely looks like a CPF is not reported as one. Apache 2.0, no runtime dependencies. PT: biblioteca Python que acha identificadores pessoais brasileiros em texto livre em português e confere o dígito verificador, p/ que número c/ cara de CPF não seja reportado como CPF. Apache 2.0, sem dependência.
pip install tarja
import tarja
text = "Paciente CPF 529.982.247-25, cartao SUS 729 1417 7763 1701"
tarja.mask(text) # "Paciente CPF <BR_CPF>, cartao SUS <BR_CNS>"
EN: the notebook runs in the browser, nothing to install. PT: o caderno roda no navegador, sem instalar nada.
pages / páginas
- Presidio em português: por que o padrão não pega CPF
- tarja + Presidio, reference / referência
- pseudonymisation and the key / pseudonimização e a chave
- sources for every rule / fontes de cada regra
what it detects / o que ele detecta
EN: 17 entity types, in four tiers. N1 has a check digit that can be verified, so a wrong digit is not reported as a finding. N2 has a fixed format only. N3 needs a context word nearby. N4 would need named entity recognition and is deliberately not implemented. PT: 17 tipos, em 4 níveis. N1 tem DV conferível. N2 só tem formato. N3 exige palavra de contexto perto. N4 precisaria de NER e não está implementado de propósito.
| EN: tier / PT: nível | EN: examples / PT: exemplos |
|---|---|
| N1 | CPF, CNPJ (incl. alphanumeric / alfanumérico), CNS, CNJ, CNM, NIS/PIS, RENAVAM, título de eleitor, CNH, cartão, CIB |
| N2 | PIX (EVP), placa, telefone |
| N3 | CEP, IPTU, matrícula de imóvel |
| N4 | EN: name, address, free-text clinical data. Not implemented / PT: nome, endereço, dado clínico. Não implementado |
how well it works / o quanto funciona
EN: measured on tarja-bench v0.3, which is generated by rule and published with the library. Exact-match F1. PT: medido no tarja-bench v0.3, gerado por regra e publicado junto. F1 de casamento exato.
| EN: subset / PT: subconjunto | F1 |
|---|---|
| EN: controlled / PT: controlado | 0.978 |
| EN: adversarial / PT: adversarial | 0.825 |
| EN: semi-real / PT: semi-real | 0.977 |
EN: the semi-real subset fell from 0.990 in v0.2 to 0.977 in v0.3. Nothing in the library changed: v0.2 inserted each identifier with one canonical phrase per type, and v0.3 draws from three or four wordings per type, including abbreviated, lower-case and colon-free forms. The lower number is the comparable one. PT: o semi-real caiu de 0,990 na v0.2 p/ 0,977 na v0.3. Nada mudou na biblioteca: a v0.2 inseria c/ uma frase canônica por tipo e a v0.3 sorteia entre 3 e 4 redações, incluindo abreviada, em caixa baixa e sem dois pontos. O número menor é o comparável.
EN: on the 5,902 paragraphs of Brazilian federal law used as the semi-real background, which carry no personal data, tarja produced one spurious finding (a BR_MATRICULA_IMOVEL, an entity with no check digit). One event is not a rate: it is a cost measurement on legal prose, and it says nothing about administrative text, where N1 and N2 entities are common. Of those paragraphs, 2,000 were drawn as background. PT: nos 5.902 parágrafos de lei federal usados como fundo do semi-real, q não têm dado pessoal, o tarja produziu um achado espúrio (um BR_MATRICULA_IMOVEL, entidade sem dígito verificador).
EN: by difficulty, partial-match F1: D0 1.000, D1 0.957, D2 0.963, D3 0.997, D4 0.266, D5 0.895. Exact match is stricter and D4 sits at 0.210 there, so always say which mode a figure comes from. D4 is optical-character- recognition noise (O for 0, l for 1) and is the weak spot. It is published rather than hidden because a benchmark that only shows wins measures nothing. PT: por dificuldade, os números acima são de casamento parcial. No casamento exato, mais estrito, o D4 fica em 0,210, então diga sempre de que modo vem a figura. O D4 é ruído de OCR e é o ponto fraco. Está publicado em vez de escondido, porque benchmark q só mostra vitória não mede nada.
the command line, and why the exit code matters / a linha de comando, e por que o exit code importa
EN: tarja scan returns 1 when it finds something, 0 when the file is clean and 2 on error, so
the fail-closed idiom is a plain &&:
tarja scan report.txt && ./send.sh
EN: the exit code is decided over every valid candidate found, before any threshold is applied. Raising
--report-min-score hides rows from what you read and never turns exit 1 into exit 0. Until 0.8.0 that was
not true: the same filtered list fed the report and the exit code, so a display option could decide whether
data left the machine. That is one of five defects 0.9.0 closed, and it is the reason to upgrade.
EN: a wrong check digit is a separate question. By default scan drops those values and mask leaves them
in cleartext, both now counting them on stderr so the silence is gone. --suspect includes them in the
report and masks them. A wrong check digit means “not a valid identifier”, not “not personal data”: it is as
often a typo in a real one. On a last gate before text leaves a perimeter, pass --suspect, or
report_invalid=True in the library, and decide yourself.
PT: o tarja scan devolve 1 quando acha, 0 quando o arquivo está limpo e 2 em erro, então o
idioma que falha fechado é um && simples. O exit code é decidido sobre todo candidato válido achado,
antes de qualquer limiar: subir o --report-min-score esconde linha do relatório e nunca transforma
exit 1 em exit 0. Até a 0.8.0 isso não era verdade, e opção de exibição decidia se o dado saía da máquina.
PT: DV errado é outra questão. Por omissão o scan descarta esses valores e o mask deixa eles em claro,
os dois agora contando no stderr. O --suspect inclui e mascara. DV errado quer dizer “não é identificador
válido”, não “não é dado pessoal”: é, com a mesma frequência, erro de digitação num real.
what it does not do / o que ele não faz
EN: it does not detect names, addresses or clinical data in prose. A missing finding is not proof that there is no personal data. It does not resolve an identifier into a person and never queries an external service. PT: não detecta nome, endereço nem dado clínico em prosa. Ausência de achado não é prova de ausência de dado pessoal. Não resolve identificador em pessoa e não consulta serviço externo.
EN: source at github.com/macmaia/tarja. Contact: tarja@micah6ai.com