1
0
Fork 0

feat(okf): bundle-import iterator (mode b) — per-concept validate+stamp, aggregate disposition, log.md (T7, TDD, +8)

This commit is contained in:
Kjell Tore Guttormsen 2026-07-06 09:32:50 +02:00
commit 320a40244f
2 changed files with 171 additions and 0 deletions

View file

@ -25,6 +25,7 @@ from llm_ingestion_guard.okf import (
stamp_concept,
trust_for,
format_log_entry,
import_bundle,
Origin,
Channel,
OKFFrontmatterError,
@ -303,3 +304,77 @@ def test_format_log_entry_prepends_timestamp():
stamp = stamp_concept("a/b", Report(), Origin.INTERNAL, Channel.AUTOMATIC)
line = format_log_entry(stamp, timestamp="2026-07-06T07:00:00Z")
assert line.startswith("2026-07-06T07:00:00Z")
# --- T7: bundle-import iterator (mode b) --------------------------------------
# A received bundle is validated per concept, not as one unit: one bad concept
# is rejected (fail-secure) and recorded, while the rest are still validated.
_CLEAN_A = (
"---\ntype: table\ntitle: Users\ndescription: The users table.\n"
"---\nA clean paragraph about the users table.\n"
)
_CLEAN_B = (
"---\ntype: table\ntitle: Orders\ndescription: The orders table.\n"
"---\nA clean paragraph about the orders table.\n"
)
def test_import_bundle_all_clean_warns():
result = import_bundle({"tables/users.md": _CLEAN_A, "tables/orders.md": _CLEAN_B})
assert len(result.concepts) == 2
assert all(c.error is None for c in result.concepts)
assert all(c.stamp is not None for c in result.concepts)
assert result.disposition is Disposition.WARN
def test_import_bundle_iterates_per_concept_not_whole_unit():
# a reserved-name concept is rejected, but the good concept is still validated
result = import_bundle({"index.md": _CLEAN_A, "tables/users.md": _CLEAN_B})
by_path = {c.path: c for c in result.concepts}
assert by_path["index.md"].disposition is Disposition.FAIL_SECURE
assert by_path["index.md"].error is not None
assert by_path["tables/users.md"].error is None
assert by_path["tables/users.md"].disposition is Disposition.WARN
def test_import_bundle_rejects_bad_resource():
doc = "---\ntype: table\nresource: http://insecure.example/x\n---\nbody\n"
c = import_bundle({"tables/x.md": doc}).concepts[0]
assert c.disposition is Disposition.FAIL_SECURE
assert c.error is not None
def test_import_bundle_rejects_dangerous_frontmatter():
doc = "---\ntype: &a table\n---\nbody\n"
c = import_bundle({"tables/x.md": doc}).concepts[0]
assert c.disposition is Disposition.FAIL_SECURE
assert c.error is not None
def test_import_bundle_flags_injection_concept():
poisoned = "---\ntype: table\n---\n" + _INJECTION + "\n"
c = import_bundle({"tables/x.md": poisoned}).concepts[0]
assert c.disposition in (Disposition.QUARANTINE_REVIEW, Disposition.FAIL_SECURE)
def test_import_bundle_aggregate_is_most_severe():
poisoned = "---\ntype: table\n---\n" + _INJECTION + "\n"
result = import_bundle({"a/clean.md": _CLEAN_A, "a/bad.md": poisoned})
assert result.disposition in (Disposition.QUARANTINE_REVIEW, Disposition.FAIL_SECURE)
def test_import_bundle_log_has_line_per_concept():
log = import_bundle({"tables/users.md": _CLEAN_A, "tables/orders.md": _CLEAN_B}).log()
assert len(log.strip().splitlines()) == 2
assert "tables/users" in log and "tables/orders" in log
def test_import_bundle_records_origin_channel_on_stamp():
result = import_bundle(
{"tables/users.md": _CLEAN_A}, origin=Origin.INTERNAL, channel=Channel.MANUAL
)
stamp = result.concepts[0].stamp
assert stamp.trust is Trust.TRUSTED
assert stamp.origin is Origin.INTERNAL
assert stamp.channel is Channel.MANUAL