Reusable, minimal, dependency-light defensive layer for LLM ingestion (write-time) pipelines — sanitize, fence, tool-less quarantined transform, capability isolation, output-scan-before-persist, fail-secure.
Find a file
Kjell Tore Guttormsen 9b75bf0bb7 feat(contract): tool-less + credential-allowlist + env-scoping quarantine asserters (TDD) [skip-docs]
Module 9 of the build order — the differentiator. Where the other modules
detect and report, these are pure functions that ENFORCE an invariant and
raise: the write-time analogue of runtime least-privilege. They harden the
call a pipeline makes around its quarantined transform; the library makes no
model call itself.

Three asserts, matching the reusable-contract checklist (BRIEF §6 steps 3-4):
- assert_tool_less(request): the model request carries no tool surface —
  tools/functions/tool_choice/function_call/mcp_servers, populated. Covers
  both Anthropic and OpenAI request shapes; empty/None is genuinely tool-less.
- assert_credential_allowlist(env, allowed): the process env holds no
  credential beyond this stage's allowlist (subset = least-privilege; the
  enrichment stage sees only the model key, never the publish credential).
- scoped_env(env, allowed): the isolation primitive — strips off-allowlist
  credentials, keeps PATH etc.; the assert then passes by construction.

Generalized from claude-code-llm-wiki tools/wiki_ingest/enrich.py
assert_quarantine (a pipeline-specific gate) into framework-agnostic pieces.
Two deliberate safety choices inherited from the reference: credential
detection is name-based (env VALUES are never read — value-scanning is the
output module's job); and a raised ContractViolation names only the offending
KEY, never a value, so it is safe to route to an alert channel (minimal-alert,
BRIEF §6 step 8). CREDENTIAL_NAME_RE ported verbatim from the proven reference.

23 new tests; 161 green total.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HyRCQMocjZ6SmSQ6JidJ2k
2026-07-04 20:44:20 +02:00
docs docs(plan): add end-to-end showcase pipeline test as the final deliverable 2026-07-04 17:23:17 +02:00
src/llm_ingestion_guard feat(contract): tool-less + credential-allowlist + env-scoping quarantine asserters (TDD) [skip-docs] 2026-07-04 20:44:20 +02:00
tests feat(contract): tool-less + credential-allowlist + env-scoping quarantine asserters (TDD) [skip-docs] 2026-07-04 20:44:20 +02:00
.gitignore chore: repo scaffolding via /repo-init 2026-07-04 08:39:23 +02:00
CHANGELOG.md chore: repo scaffolding via /repo-init 2026-07-04 08:39:23 +02:00
CLAUDE.md chore: repo scaffolding via /repo-init 2026-07-04 08:39:23 +02:00
LICENSE feat: scaffold package + report and sanitize modules (TDD) 2026-07-04 09:24:20 +02:00
pyproject.toml feat: scaffold package + report and sanitize modules (TDD) 2026-07-04 09:24:20 +02:00
README.md docs: design brief for reusable LLM ingestion-pipeline security library 2026-07-04 06:18:32 +02:00

llm-ingestion-pipeline-security

A reusable, minimal, dependency-light defensive layer for LLM ingestion pipelines — the write-time siblings of query-time chatbot guardrails.

Where mature guardrails (LLM Guard, NeMo Guardrails, Rebuff, Vigil, …) sit between a user and a model at query time, this library hardens the other shape: untrusted content flowing through an LLM enrichment/summarization/extraction step into a persisted, downstream-consumed artifact (RAG corpus, knowledge base, wiki). It packages the architectural contract — sanitize → fence → tool-less quarantined transform → per-stage capability isolation → scan output before commit → fail-secure — as composable, framework-agnostic code.

Status: brief / pre-implementation. Start with the design brief:

The contract is extracted from a working reference implementation (the claude-code-llm-wiki Stage B enrichment pipeline).