factflow-hygiene
Content sanitization adapters that run upstream of LLM and synthesis stages: deterministic PII redaction, LLM-based sensitivity classification, an LLM-based broken-access-control gate, and label-driven redaction. Built to hold one invariant — no Norwegian PII reaches a model — and to keep strictly-confidential and access-control-violating content out of synthesis.
Tier and role
Section titled “Tier and role”- Tier: workflow
- Import name:
factflow_hygiene - Source:
backend/packages/workflows/factflow-hygiene/
Adapters are consumed by type name in pipeline YAML (auto-discovered and registered), not imported. The package exposes no flat public API; each adapter lives in its own module.
Adapters
Section titled “Adapters”| Type | Class | Kind | injectable deps |
|---|---|---|---|
pii_redactor | PIIRedactorAdapter (pii/adapter.py) | deterministic | — |
sensitivity_classifier | SensitivityClassifierAdapter (sensitivity/classifier.py) | LLM-based | storage, llm_factory, db_pool |
anti_bac_gate | AntiBacGateAdapter (anti_bac/detector.py) | LLM-based | llm_factory, db_pool |
sc_redactor | SCRedactorAdapter (sensitivity/sc_redactor.py) | deterministic | db_pool |
They run as a fixed chain —
pii_redactor → sensitivity_classifier → anti_bac_gate → sc_redactor — ahead of
knowledge_diff. See the Hygiene workflow for the ordering
rationale and the residency invariant.
Behaviour
Section titled “Behaviour”pii_redactor— regex/pattern detection (Norwegian national IDs, IBANs, …) in two passes, then redaction. Reproducible: same input, same output.sensitivity_classifier— readsdata["sensitivity"]; if empty, classifies the redacted body via thellm_factory(llm_profile), writes the label into both the in-flightdataand the storage sidecar, and persists apipeline_sensitivity_findingsrow keyed by content hash for cross-run cache reuse.anti_bac_gate— assesses the content for org-wide-invariant (broken-access-control) violations via thellm_factory; on a violation, replaces the body in place with[REDACTED:BROKEN_ACCESS_CONTROL]and persists apipeline_anti_bac_findingsrow keyed by content hash + model profile.sc_redactor— when the resolved label isSTRICTLY_CONFIDENTIAL, replaces the document body with a placeholder so SC content never reaches synthesis; the label itself survives, so SC sources travel on as labelled-but-bodyless markers.
Dependencies
Section titled “Dependencies”- Workspace:
factflow-protocols,factflow-foundation,factflow-engine; thesensitivity_classifierandanti_bac_gatealso usefactflow-llm. - External services: an LLM provider (sensitivity and anti-BAC assessment) and PostgreSQL (the content-hash caches and findings tables).
Testing
Section titled “Testing”Tests at backend/packages/workflows/factflow-hygiene/tests/. Config-wiring tests assert
the adapters register and run in order before knowledge_diff; the classifier is tested
with mocked LLM clients — see .claude/skills/backend/llm-unit-testing/.
Related
Section titled “Related”- Hygiene workflow — operator-facing chain and ordering
factflow-knowledge— the synthesis stage hygiene protects- Adapter catalog — exact config fields per adapter