All notable changes to this project are documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
While the version is below 1.0.0, minor releases may include breaking changes;
each such change is called out under a Changed or Removed heading.
- An explicit
score_thresholdof0is now rejected. When a request setsscore_threshold_set = true,score_thresholdmust be> 0; an explicit0(or negative) returnsInvalidArgumentinstead of silently falling through to the service default. Previously the field was documented as "0= include everything" but the service treated it as "use default", so an explicit0was silently ignored. Clients that want the server default should leavescore_threshold_setunset (orfalse) rather than sending0. Affects the REST, Connect, and gRPC transports for create/anonymize, synthesize, and PDF redaction. - The NER build tag
hugotis renamed toner. Self-hosters who build the NER variant from source now usego build -tags ner ./...(was-tags hugot); the publishedanonde-nerimage is unaffected. The old name was misleading once the hugot transformer backend was removed (see below) — the tag only ever gated GLiNER. Theanonde_build_infometric label for NER builds is nowner(washugot).
anonde-ner-stackimage and thegliner-stackbackend. The NER lineup consolidates to a single NER image:anonde-ner(base GLiNER, ~770 MB) alongside the patterns-onlyanonde(~12 MB). The premium BASE+LARGE stack image (~2.1 GB) and its bundledANALYZER_BACKEND=gliner-stackensemble are no longer built, pushed, or documented. The LARGE GLiNER model itself stays reachable viaANALYZER_BACKEND=gliner-flatfor self-hosters who want it, so no detection capability is lost — only the prebuilt two-model image and its ensemble wiring.Dockerfile.anonde-ner-stack, themake docker-build-ner-stacktarget, thener-stackcompose profile, and the stack jobs in the release / build CI are all removed.- hugot / XLM-R transformer NER backend (
ANALYZER_BACKEND=hugotand theHUGOT_MODEL/HUGOT_MODELS_DIRenv vars). GLiNER strictly outperformed it on every benched corpus and was the production default; the hugot recognizer carried a second ONNX code path for no recall benefit. The hugot library stays a dependency — GLiNER reuses its model downloader and on-disk cache layout. The public library entry pointsanonde.DefaultAnalyzerEngineWithHugot/...WithHugotConfigand therecognizers.HugotNERConfigtype are removed; use the GLiNER constructors instead. - Ollama NER backend (
ANALYZER_BACKEND=ollama) and theOLLAMA_ENDPOINT/OLLAMA_MODELenv vars. The LLM-over-HTTP backend was never shipped in either image, carried no leak-rate bench numbers, and depended on an external daemon — off-brand for a deterministic local-redaction tool and pure installation-surface clutter. The public library entry pointanonde.DefaultAnalyzerEngineWithOllamais removed. Using anonde as a privacy proxy in front of a local Ollama (ANONDE_OPENAI_BASE_URL) is unaffected — that is a separate feature.
0.1.1 - 2026-06-13
Maintenance release. Re-publishes the three image variants
(anonde, anonde-ner, anonde-ner-stack) at 0.1.1.
- Selectable GLiNER label sets (
GLINER_LABEL_SET) — the NER image ships four curated open-set label sets and selects one at inference time:chat(default),clinical,finance, andlegal. All four map onto the same canonical entity types the pattern recognizers emit, so anonymizer operators and reveal/detokenize behave identically regardless of which set is active; an unrecognised value falls back tochat. Go-library callers setGLiNERConfig.Labels/LabelToEntitydirectly (e.g.recognizers.FinancePIILabels). See the README for the per-set coverage table.
- Default NER label set is now
chat(was the full clinical set in0.1.0).chatdropsage,profession,job title,date/date of birth, and the clinical / German-insurance labels because they over-redact ordinary conversational text ("18 years of experience" → AGE, "tech" → PROFESSION). Deployments that need the old behavior setGLINER_LABEL_SET=clinical.
0.1.0 - 2026-05-28
First tagged release. Three image variants published to ghcr.io:
ghcr.io/anonde-io/anonde:0.1.0 (patterns-only, ~12 MB),
ghcr.io/anonde-io/anonde-ner:0.1.0 (BASE GLiNER, ~770 MB), and
ghcr.io/anonde-io/anonde-ner-stack:0.1.0 (BASE + LARGE GLiNER, ~2.1 GB).
Multi-arch (linux/amd64 + linux/arm64).
- PII analyzer — 52 region-aware pattern recognizers covering 12+ jurisdictions (international IDs, US, UK, Germany, Italy, Spain, Australia, India, Poland, Singapore, Finland, Korea), with parallel dispatch and score-based conflict resolution.
- Optional in-process NER behind the
-tags hugotbuild — GLiNER and hugot ONNX recognizers. Requires CGO and a reachablelibonnxruntime.so. NER beats patterns for PERSON/ORG/LOC/AGE/PROFESSION/NRP on conflict. - Anonymizer operators — Replace, Redact, Mask, Hash, Encrypt, and Synthesize, with adjacent-span merging.
- Reversible token vault — in-memory and bbolt backends behind one
interface. Tokens are stable per
(tenant, doc)and reversible only through the reveal path. - HTTP server — three transports on one port: REST/JSON (grpc-gateway), Connect (Connect/JSON, Connect/Protobuf, gRPC-Web), and native gRPC. Wire JSON is snake_case; camelCase inputs are also accepted.
- Reveal / detokenize gated by
actor+purposeaudit metadata — the only path that returns cleartext. - OpenAI-compatible proxy at
POST /v1/chat/completions— anonymizes the prompt, forwards to the upstream provider, and de-anonymizes the response in OpenAI shape. v0.1 proxies OpenAI only, non-streaming only. - Content formats — text, JSON, NDJSON, logs, and PDF, with
format negotiation. Scanned (image-only) PDFs are OCR'd via
pdftoppm+tesseractwhen both are onPATH; bundled in the NER image variants, no-op fallback in the patterns-only image. Tunable viaANONDE_OCR_*env vars. - Docker images — three multi-arch (
linux/amd64+linux/arm64) variants:anonde(patterns-only, ~12 MB, pure Go),anonde-ner(BASE GLiNER, ~770 MB, CGO + bundled libonnxruntime), andanonde-ner-stack(BASE + LARGE GLiNER, ~2.1 GB). - Public benchmark matrix — leak-rate and F1 scoring across gold-annotated clinical, finance, legal, and general-PII corpora, re-run on every relevant PR with a guard rail against silent NER fallback.
- NER models are baked into the NER image; there is no outbound HuggingFace traffic at request time.
- All anonymization and de-anonymization runs locally — no third-party calls except the upstream provider when the OpenAI-compatible proxy is explicitly configured.
- Secret recognizers — API keys, tokens, credentials.
- Streaming SSE support for the OpenAI-compatible proxy (
stream: true). - Anthropic and Gemini upstreams for the proxy, selected by model prefix.