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:
parent
ad532f3c6d
commit
39f6f0a4fb
1 changed files with 128 additions and 0 deletions
|
|
@ -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"\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"\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"\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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue