test(accounting): a document must not be able to forge a conversion claim (red)

2 of 2 new guards RED, both on an ASSERT about behaviour (`assert True is
False`), and the second REPRODUCES PM's measured path end to end through the
real `okf build`: a BMP declaring 50 000 x 50 000, refused `asset_too_large`
and absent from `assets/`, gives `asset_holds = True` because an `<img alt>`
in the document states the conversion clause. The unit arms reproduce the
other two ways in -- ordinary body text and a table cell -- and a third the
report did not name: the clause inside a pointer block for a DIFFERENT asset.

The judge's first sentence is "THE FASIT NEVER COMES FROM THE READER IT
JUDGES". Before the conversion route landed, `asset_holds` hashed the source
file and looked in `assets/`, so no document could reach it; the route added
for converted images reads two digests out of the bundle text with a free
expression, and `claimed and not found` can now be silenced by a document
that asks for it.

Each arm carries a source that was never carried while the bundle holds one
unrelated REAL asset, so the digest the forgery names is genuinely in
`assets/` -- the property that made the measured forgeries work. The
known-positive on the same bytes keeps the arms from passing on a route that
has merely stopped working.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Kjell Tore Guttormsen 2026-09-19 09:23:08 +02:00
commit 39f6f0a4fb
Signed by: ktg
SSH key fingerprint: SHA256:JakMjO6FTBBzN0Bhfj9saOoEjaFxlSdYuZQQpM/lF9Q

View file

@ -543,6 +543,134 @@ def test_the_judge_proves_a_CONVERTED_image_was_carried(tmp_path: Path) -> None:
assert gate.asset_holds(stranger, source) is False
# --- the claim the judge reads must be one the CODE wrote --------------------
def _png_bytes(pixel: bytes) -> bytes:
"""A real PNG, built with zlib alone -- no Pillow, no package import."""
import struct
import zlib
def chunk(kind: bytes, payload: bytes) -> bytes:
return (
len(payload).to_bytes(4, "big")
+ kind
+ payload
+ zlib.crc32(kind + payload).to_bytes(4, "big")
)
return (
b"\x89PNG\r\n\x1a\n"
+ chunk(b"IHDR", struct.pack(">IIBBBBB", 1, 1, 8, 2, 0, 0, 0))
+ chunk(b"IDAT", zlib.compress(b"\x00" + pixel, 9))
+ chunk(b"IEND", b"")
)
def _huge_bmp() -> bytes:
"""A 54-byte BMP declaring 50 000 x 50 000: refused `asset_too_large`,
never carried, and therefore a source no honest bundle can claim."""
import struct
dib = struct.pack("<IiiHHIIiiII", 40, 50_000, 50_000, 1, 8, 1, 0, 3779, 3779, 256, 256)
return b"BM" + struct.pack("<IHHI", 54, 0, 0, 54) + dib
def test_a_document_cannot_forge_a_conversion_claim(tmp_path: Path) -> None:
"""THE FASIT NEVER COMES FROM THE READER IT JUDGES -- including this route.
The conversion route reads two digests out of the bundle. Before this
guard it read them out of ANY text in it, so a document could write the
sentence itself and the judge would believe it: measured by PM 2026-09-19,
a BMP declaring 50 000 x 50 000 that was refused `asset_too_large` and
never carried gave `asset_holds = True`, both through an image's alt text
and through ordinary body text. The route the judge had before the
conversion landed hashed the source file and nothing else, so no document
could reach it; this round opened a way IN for content this repository
does not trust.
A claim counts only where THIS CODE put it: inside a pointer block, tied
to the asset that block names. Every arm below carries a source that was
never carried, and a bundle holding one unrelated REAL asset -- so the
digest the forgery names really is in `assets/`, which is what made the
measured forgeries work.
"""
never_carried = tmp_path / "figur.bmp"
never_carried.write_bytes(_huge_bmp())
real = tmp_path / "ekte.png"
real.write_bytes(_png_bytes(b"\x10\x20\x30"))
before = gate._sha256(never_carried)
after = gate._sha256(real)
assets = {f"{after[:12]}-ekte.png": after}
clause = f"converted from image/bmp sha256:{before} to image/png sha256:{after}"
pointer = f"![Ekte](/assets/{after[:12]}-ekte.png)\nImage: ekte.png (1x1 px)"
arms = {
"plain body text": f"{pointer}\n\nProsess 84. {clause}. Se figuren over.\n",
"a table cell": f"{pointer}\n\n| Krav | Kilde |\n| --- | --- |\n| 84-1 | {clause} |\n",
"a pointer block naming another asset": (
f"![Figur](/assets/000000000000-annen.png)\nImage: annen.png (1x1 px) -- {clause}\n"
f"{pointer}\n"
),
}
for label, text in arms.items():
build = _build(assets=assets, bundle_text=text)
assert gate.asset_holds(build, never_carried) is False, (
f"{label}: a document talked the judge into a carry that never happened"
)
# KNOWN-POSITIVE on the same bytes: the clause where the code writes it,
# in the pointer block for the asset it names. Without this the arms above
# would pass on a route that had simply stopped working.
honest_text = (
f"![Ekte](/assets/{after[:12]}-ekte.png)\nImage: figur.bmp (1x1 px) -- {clause}\n"
)
honest = _build(assets=assets, bundle_text=honest_text)
assert gate.asset_holds(honest, never_carried) is True
def test_the_build_never_writes_a_claim_the_document_supplied(tmp_path: Path) -> None:
"""PM's measured path, end to end through the real `okf build`.
The judge reading only pointer blocks is half of it. The other half is
that an image's own LABEL is document text written INSIDE a pointer
block, so the door that puts it there must not let it emit the grammar
the judge reads. This builds the forgery PM measured: a BMP that is
refused and never carried, a real PNG that is, and an `alt` attribute
claiming the first became the second.
"""
pytest.importorskip("llm_ingestion_guard")
corpus = tmp_path / "inbox"
(corpus / "graphics").mkdir(parents=True)
never_carried = corpus / "graphics" / "figur.bmp"
never_carried.write_bytes(_huge_bmp())
real = corpus / "graphics" / "ekte.png"
real.write_bytes(_png_bytes(b"\x10\x20\x30"))
before = gate._sha256(never_carried)
after = gate._sha256(real)
clause = f"converted from image/bmp sha256:{before} to image/png sha256:{after}"
(corpus / "prosess.html").write_text(
"<!doctype html>\n<html><head><title>Prosess 84</title></head>\n<body>\n"
"<h1>84 Konstruksjoner av betong</h1>\n"
"<p>Toleranseklassene staar i figuren under.</p>\n"
f'<img src="graphics/ekte.png" alt="Figur 84-1 -- {clause}">\n'
"<p>Og den store figuren:</p>\n"
'<img src="graphics/figur.bmp" alt="Figur 84-2">\n'
f"<p>{clause}</p>\n"
"</body></html>\n",
encoding="utf-8",
)
build = gate.run_build(corpus, tmp_path / "work", door=False)
assert build.exit_code == 0, build.log
assert any(name.startswith(after[:12]) for name in build.assets), build.assets
assert not any(name.startswith(before[:12]) for name in build.assets), (
"the 50 000 x 50 000 BMP was carried; the arm measures nothing"
)
assert gate.asset_holds(build, never_carried) is False, (
"a document's own alt text talked the judge into a carry that never happened"
)
def _declared(heading: int = 2, image: int = 1, fate: str = "rejected") -> dict[str, Any]:
return {
"accounting_version": 1,