Datos estructurados (ambos motores)
Correos, números de teléfono, tarjetas de crédito (validadas con el algoritmo de Luhn), URLs, direcciones IPv4 y secretos comunes.
Anonimal detecta PII en texto y la reemplaza según un modo elegido. Un detector solo encuentra fragmentos; el reemplazo se decide por separado. Todo corre localmente — los datos originales nunca salen de la máquina.
La detección depende del motor activo.
Datos estructurados (ambos motores)
Correos, números de teléfono, tarjetas de crédito (validadas con el algoritmo de Luhn), URLs, direcciones IPv4 y secretos comunes.
Identificadores LATAM (ambos motores)
DNI argentino, CUIT / CUIL (con dígito verificador) y números bancarios CBU.
PII en texto libre (solo motor ML)
Nombres de personas y direcciones en prosa corrida, vía NER — la parte que regex no puede ver.
Reglas personalizadas
Reglas provistas por el usuario: listas de ocultar-siempre / nunca-ocultar y tus propios
patrones {regex, placeholder}.
Un detector expone detect(text) → [Span]; los solapamientos se resuelven por el
fragmento más largo (los empates se rompen por prioridad de etiqueta).
anonimal_lite.Selecciona con ANONIMAL_ENGINE: auto (ML si está listo, de lo contrario lite) · lite
· ml. Las solicitudes pueden anular el valor por defecto en cada llamada con un campo engine.
Dos modos son opacos (de una vía) y uno es reversible. Se usa un único anonimizador por documento, por lo que el mismo valor siempre obtiene el mismo reemplazo (consistencia).
| Modo | Resultado | Reversible |
|---|---|---|
typed | [EMAIL] (placeholder por categoría) | no |
anon | «REDACTADO» (token opaco único) | no |
pseudo | EMAIL_1 (seudónimo numerado estable) | sí (devuelve un mapa) |
mask | j***@***.com / ****-****-****-1234 (según el tipo) | no |
hash | EMAIL_a1b2c3d4e5 (HMAC determinista) | no |
typed, anon, mask y hash producen una salida no reversible. Úsalos cuando
solo necesitas compartir o almacenar texto de forma segura. El modo hash es determinista:
define ANON_HASH_KEY para que el mismo valor se cifre idénticamente entre reinicios (vinculación estable
sin almacenar un mapa).
pseudo es el modo reversible. Reemplaza cada valor con un token estable
(EMAIL_1, PERSON_2, …) y devuelve un mapa token → original. El flujo:
POST /anonymize con mode: "pseudo" → obtén el output anonimizado más el map.output al LLM (la PII original nunca llega a él).POST /deanonymize con la respuesta del LLM y el mismo map → los valores
originales se re-hidratan de vuelta en el texto.Anonimal conserva el formato de archivos que ya son texto: txt, md,
log, srt, html, CSV (celdas anonimizadas, columnas intactas) y JSON
(valores de cadena anonimizados, claves nunca tocadas; la salida sigue siendo JSON válido). Un único
anonimizador por archivo significa un mapa consistente para todo el documento.
Convertir Word / Excel / imágenes / audio / URLs no es tarea de Anonimal — eso
le corresponde a Escriba, Extracta y Fisherboy, que le entregan texto ya convertido.
Anonimal, sin embargo, sí ofrece redacción de PDF real (/redact_pdf): tachado
genuino de los fragmentos detectados más eliminación de metadatos.
Todos los endpoints excepto /health están protegidos por require_auth (ver
autenticación). La URL base es tu despliegue, p. ej.
http://localhost:8920.
| Método | Ruta | Qué hace |
|---|---|---|
GET | /health | Estado + disponibilidad del motor ML. Siempre abierto. |
POST | /detect | {text} → fragmentos detectados. |
POST | /anonymize | {text, mode, engine?} → {output, map, summary}. |
POST | /deanonymize | {text, map} → texto original. |
POST | /anonymize_file | Carga de archivo + mode → contenido anonimizado (mismo formato). |
POST | /redact_pdf | PDF → PDF redactado (tachado + metadatos borrados). |
POST /anonymizeSolicitud:
{ "text": "email juan@acme.com, CUIT 20-12345678-6", "mode": "pseudo", "engine": "auto", "rules": null}Respuesta:
{ "engine": "lite", "mode": "pseudo", "output": "email EMAIL_1, CUIT ID_1", "spans": [ { "label": "EMAIL", "start": 6, "end": 19, "text": "juan@acme.com" } ], "map": { "EMAIL_1": "juan@acme.com", "ID_1": "20-12345678-6" }, "reversible": true, "summary": { "EMAIL": 1, "ID": 1 }}El map solo se completa para pseudo; reversible lo refleja.
POST /deanonymize{ "text": "reply to EMAIL_1", "map": { "EMAIL_1": "juan@acme.com" } }→ { "output": "reply to juan@acme.com" }. Un map faltante o vacío devuelve
422.
/anonymizeLlamar a POST /anonymize sin un mode devuelve el contrato legacy usado por
el Anonimal embebido — {text, detected_spans, redacted_text, summary} con un
placeholder por fragmento. Esto permite que Escriba y Fisherboy apunten su ANONIMAL_URL
al nuevo servicio sin cambiar una línea de código.
GET /healthDevuelve status, el motor y modo por defecto, y un bloque ml con
available, ready y error. Usado por el healthcheck del contenedor.
401 (token o sesión faltante/inválido), 413 (texto o PDF por encima del límite de tamaño),
422 (modo inválido / mapa faltante / rules_json inválido), 503 (motor ML o soporte de PDF
no disponible).
Anonimal acepta dos credenciales independientes en la API:
ANONIMAL_TOKEN. Cada solicitud debe entonces llevarlo,
ya sea como Authorization: Bearer <token> o como el header X-Anonimal-Token.
Así es como Escriba y Fisherboy se autentican en la red interna.ANONIMAL_AUTH_ENABLED=true, una cookie firmada de
la página /login también satisface el control de la API (para la interfaz web).Si no se configura ninguna, la API está abierta (asume localhost). /health
siempre es accesible para healthchecks.
Anonimal es el único dueño de la anonimización en la Escriba Suite; los satélites delegan en él.
ANONIMAL_URL definido llama a Anonimal por HTTP
(cobertura ML completa), autenticándose con X-Anonimal-Token.ANONIMAL_URL, un producto recurre a la
librería incluida anonimal_lite (solo regex, stdlib pura), por lo que aún puede anonimizar
de forma independiente.pip install "anonimal-lite @ git+https://github.com/diegoparras/anonimal.git@v0.4.0"from anonimal_lite import LiteEngine, Anonymizer, deanonymize
eng = LiteEngine()out = Anonymizer("pseudo").process(text, eng.detect(text))Hay dos flujos hacia Anonimal: una ruta humana (Extracta/Fisherboy le entregan
a Escriba vía sessionStorage['escriba.handoff'], y el botón “Anonimizar” de Escriba
llama a la API) y una ruta automática (un worker desatendido llama a la
API directamente). De cualquier forma, Anonimal sigue siendo el único lugar donde ocurre la anonimización.
/detect, /anonymize (campo rules) y /anonymize_file (rules_json)
aceptan un objeto de reglas: always (ocultar siempre), never (nunca ocultar) y
patterns ({regex, placeholder}). Los patrones son un superconjunto de las reglas de Escriba,
con RE2 opcional para protegerse contra ReDoS.