1
0
Fork 0
llm-ingestion-pipeline-secu.../src/llm_ingestion_guard
Kjell Tore Guttormsen 58704834b6 feat(okf): the mapping class gets one expressible form, typed and allowlisted
OKF v0.2 writes its whole trust and provenance layer as mappings, and T2 gave
the mapping class no expressible form. A consumer measured 0 of 53 upstream
concepts through the gate on 0.3.4, 1.0.0 and 1.1.0. That was a contract
collision, not a calibration setting: SPEC.md @ 62432a09 uses flow mappings in
its own 5.1/5.2 examples, and 11 carries a hard MUST for consumers ("MUST treat
a bare `verified` mapping as a one-element list") that presupposes they parse.

Admitted: a flow mapping, as a value or as a block-list item, whose every key is
on a nine-name allowlist and whose every leaf is a plain scalar run through the
unchanged dangerous-value and mapping-construct predicates. The form is safe
because the allowlist inspects every key -- the blanket refusal was the
enforcement, not the point.

Refused, each on its own rule and ground-truthed against PyYAML 6.0.3: a key off
the allowlist, a nested collection, a quoted leaf, a duplicate key, an empty or
unclosed mapping, trailing junk, and {a:b} (which PyYAML reads as the KEY a:b).
A refused mapping still raises rather than degrading into a string, so the 1.1.0
type-confusion defect is not reopened, and the block, dotted and inline-colon
routes still raise.

`resource` is deliberately off the allowlist though SPEC.md 5.1 names it inside
a `sources` entry: it is a pointer rather than a label and the only key T3
exists for, so admitting it would let `executor: { resource: skills/run.md }`
carry an executable-code pointer through in typed clothes -- the door-C route
closed in 1.1.0. It costs nothing today, because the conformant carrier for
sources[].resource is a block sequence of block mappings, which stays refused.

Mapping leaves are scanned like every other frontmatter value (T1). Coverage
matrix 130/130 (new row: the off-allowlist key). No exported surface, detector
behaviour or calibration changed.
2026-08-21 21:04:51 +02:00
..
__init__.py release: 1.1.0 -- the first behaviour change shipped under the freeze 2026-08-13 22:58:36 +02:00
active_content.py docs(census): the two wiki corpora are measured, and the tightening is thinner than zero looked 2026-08-13 20:22:18 +02:00
calibration.py feat(active-content): raw HTML graded on carrier, and a tag naming no target is inert 2026-08-12 00:42:44 +02:00
contract.py feat(sanitize,fence,neutralize): reject oversize input instead of half-transforming it 2026-08-02 21:13:08 +02:00
coverage.py feat(okf): the mapping class gets one expressible form, typed and allowlisted 2026-08-21 21:04:51 +02:00
disposition.py feat(disposition): separate the assessment axis from the action 2026-08-10 20:55:46 +02:00
entropy.py refactor(calibration): consolidate tunable thresholds into calibration.py 2026-07-15 09:44:53 +02:00
fence.py feat(sanitize,fence,neutralize): reject oversize input instead of half-transforming it 2026-08-02 21:13:08 +02:00
grounding.py feat(grounding): SourceGroundingCheck protocol + pass-through default — the semantic-poisoning seam (TDD) [skip-docs] 2026-07-04 22:44:41 +02:00
injection_lexicon.json fix(lexicon): two quadratic patterns, reachable through the output gate too 2026-07-31 21:50:51 +02:00
lexicon.py fix(lexicon): two quadratic patterns, reachable through the output gate too 2026-07-31 21:50:51 +02:00
neutralize.py fix(active-content): raw-html graded two inert shapes HIGH, and the fix moved a second surface 2026-08-11 16:56:31 +02:00
okf.py feat(okf): the mapping class gets one expressible form, typed and allowlisted 2026-08-21 21:04:51 +02:00
output.py fix(zwj): the zero-width check tested identity, so every emoji-composed document was hard-blocked 2026-08-11 22:14:47 +02:00
report.py feat: scaffold package + report and sanitize modules (TDD) 2026-07-04 09:24:20 +02:00
sanitize.py fix(zwj): the zero-width check tested identity, so every emoji-composed document was hard-blocked 2026-08-11 22:14:47 +02:00