ANSSI-PA-102 compliance layer for LLM inference. Runs locally. No network calls in the core path.
Project description
Colandix
Sanitize text before and after your LLM. Runs locally. No network calls in the library.
Maps to French national guidance ANSSI-PA-102 for generative AI security.
Colandix is a filtering layer that sits at the boundary between your application and the model. Safe content passes through. PII, secrets, and injection attempts do not reach the model.
Install
pip install colandix
Development setup with uv:
uv sync --all-groups
Optional pipelines (NER / SpaCy)
SpaCy pipelines are optional. Without them, regex, entropy, injection, and topic detectors still run; NER stays inactive.
| Extra | What it installs |
|---|---|
ner |
spacy only; then python -m spacy download <pipeline> (see spacy.io/models) |
ner-fr |
fr_core_news_md via PyPI (matches shipped profiles) |
ner-de, ner-en, ner-es, ner-it, ner-pt |
spacy only; install the pipeline with python -m spacy download de_core_news_md (etc.) |
ner-all |
fr_core_news_md wheel only; use python -m spacy download for other languages |
pip install "colandix[ner-fr]"
# or
pip install "colandix[ner]" && python -m spacy download fr_core_news_md
Bundled profiles default to fr_core_news_md. For another language, set extra.model and entities in your YAML (English uses PERSON, not PER).
Quickstart
from colandix import GuardPipeline
guard = GuardPipeline(profile="generique")
res_in = guard.scan_input("my prompt")
response = call_llm(res_in.sanitized_text)
guard.scan_output(response)
Tutorial: notebooks/demo_colandix.ipynb.
What it does
The colandix library sits between your app and the model.
flowchart LR
userInput[User_input] --> scanIn[scan_input]
scanIn --> sanitized[sanitized_text]
sanitized --> llm[LLM]
llm --> modelOutput[Model_output]
modelOutput --> scanOut[scan_output]
scanIn --> decisionIn["action + events"]
scanOut --> decisionOut["action + events"]
- Scans inputs and outputs with configurable detectors (PII, secrets, entropy, prompt injection, topics, optional NER).
- Rewrites sensitive spans in
sanitized_textwith typed tags ([EMAIL_REDACTED],[PHONE_REDACTED],[PERSON_REDACTED], etc.). - Decides an aggregate
action:pass,warn,human_review, orblock. - Logs pseudonymized metadata; no raw prompts in logs.
What a scan returns
| Field | Role |
|---|---|
result.action |
Aggregate decision (Action enum). |
result.sanitized_text |
Text to send to the LLM after masking. |
result.events |
Audit trail (evidence truncated for SIEM). |
result.blocked |
True when action == block. |
guard.find_all_candidates(text) |
Debug: list possible regex/NER hits. |
Injection and entropy detectors affect the decision only; they do not rewrite sanitized_text.
Redaction rules: colandix/redaction.py, Architecture.
Profiles
| Profile | Use case |
|---|---|
generique |
Everyday PII + injection. |
strict |
Broad PII and secrets + NER (requires SpaCy pipeline). |
sante |
Healthcare PII + medical topic guardrails. |
dev |
Credentials, secrets, sensitive dev topics. |
rh |
HR-sensitive wording and data. |
juridique |
Legal / confidentiality patterns. |
YAML sources: colandix/profiles/. Trigger reference: docs/triggers-par-profil.md.
ANSSI PA-102 alignment
Scope: content filtering and rewriting at the model boundary.
Official guide (PDF): ANSSI generative AI security recommendations.
| Ref | Topic | Coverage | Status |
|---|---|---|---|
| R25 | Input/output filtering | Regex, NER, entropy, injection, sanitized_text. |
Yes |
| R26 | Application interactions | TopicDetector (allowed / blocked). |
Partial |
| R27 | Human control | Action.HUMAN_REVIEW. |
Partial |
| R29 | Logging | Structured logger, no raw user text. | Partial |
| R31 | Critical modules | Profile separation (dev, juridique, ...). |
Partial |
| R34 | Sovereign hosting | Runs offline in the orchestration path. | Yes |
Controls outside this package (TLS, IAM, org processes): docs/compliance.md.
LLM integration
from colandix import GuardPipeline
from colandix.exceptions import ColandixBlockedError
guard = GuardPipeline(profile="generique")
try:
res_in = guard.scan_input(prompt, raise_on_block=True)
response = call_llm(res_in.sanitized_text)
guard.scan_output(response, raise_on_block=True)
except ColandixBlockedError:
return "Content blocked."
Replace call_llm with your SDK. Use raise_on_block=False to branch on result.action yourself.
Custom YAML
guard = GuardPipeline(profile_path="/path/to/profile.yaml")
Start from colandix/profiles/. Detector keys: docs/architecture.md.
Compliance report
from colandix.compliance import print_report
print_report(guard.compliance_report())
Documentation
- Site (GitHub Pages)
- Architecture
- Triggers by profile
- Testing
- Compliance (ANSSI)
Docs (local preview)
uv run mkdocs serve # http://127.0.0.1:8000, reloads on save
uv run mkdocs build # static output in site/ (gitignored; CI rebuilds on deploy)
mkdocstrings requires the package to be importable at build time. uv sync --all-groups installs colandix in dev mode alongside the docs dependencies, matching what the GitHub Actions workflow does.
Pre-deployment checklist
uv run pytest tests/ -q
uv run ruff check colandix tests
uv run mypy colandix
uv run mkdocs build
uv build
Manual checks:
- Version in
pyproject.tomlmatchescolandix/__init__.py. - docs/compliance.md updated if detectors or ANSSI scope changed.
-
pytest tests/test_detectors/test_ner.py -vpasses withfr_core_news_mdinstalled. -
notebooks/demo_colandix.ipynbruns top-to-bottom without errors. -
docs.ymlworkflow completes on a push tomain.
Publishing (maintainers)
uv build
uv publish
Set PyPI tokens and bump pyproject.toml version before publishing.
Contributing
- Fork the repo.
git checkout -b feature/your-changeuv run pytest tests/(~362 cases)- Open a Pull Request.
License
MIT — see LICENSE. © 2026 Gros Gradient
Pour les équipes ANSSI et security reviewers
La bibliothèque colandix est développée par Gros Gradient. La cartographie R25–R35, sanitized_text / action, et le périmètre bibliothèque sont dans docs/compliance.md (anglais). Le guide officiel ANSSI (IA générative) reste la référence réglementaire en français : PDF recommandations ANSSI.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file colandix-0.1.0.tar.gz.
File metadata
- Download URL: colandix-0.1.0.tar.gz
- Upload date:
- Size: 259.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df7c505005bf52942321522d7d7d04d875aed7744861e3d0fa0812d452e3a312
|
|
| MD5 |
62456c78ff942d412e04268f7b3da606
|
|
| BLAKE2b-256 |
08eb34b49ea64a87fa308db853ae09d35d28599d639ef8207fa27af6837376a6
|
File details
Details for the file colandix-0.1.0-py3-none-any.whl.
File metadata
- Download URL: colandix-0.1.0-py3-none-any.whl
- Upload date:
- Size: 39.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4aa0636fccfa66bd379c91a8b1b5fb681cdd50654e45a59dd4416e0e125c403
|
|
| MD5 |
c6c26f28010374fc52d0d8f1f5f533db
|
|
| BLAKE2b-256 |
b593f0db4bf200af4b47287ed514ecf835b0d56de8e659b053a3f37534bd8d31
|