You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#393 covered the seven refusals in _validate_manifest that one valid-manifest fixture can reach, and #394 landed them. That issue explicitly deferred the rest:
Not in scope: the 20 other CythonOverlayManifestError sites, including the JSON-parsing and canonical-JSON refusals at :638, :749, and the _require_* helpers from :1986 down. Those are worth covering too, and they can follow.
This is that follow-up. These refusals run before_validate_manifest, on the raw bytes of an overlay directory's manifest.json, which is external input.
Verification
Against main at 44e4f50, each refusal neutered in turn, running tests/test_packaging.py:
native overlay manifest is not valid JSON NOTHING NOTICED
native overlay manifest is not canonical JSON NOTHING NOTICED
artifacts must be an array NOTHING NOTICED
native overlay manifest contains duplicate fields NOTHING NOTICED
What to do
Cover the parse-stage refusals, in src/hflow/packaging.py:
:638 native overlay manifest is not valid JSON
:675 artifacts must be an array
:749 native overlay manifest is not canonical JSON
:2067 native overlay manifest contains duplicate fields
The canonical-JSON and duplicate-fields ones are the interesting pair. Both exist because a manifest that parses is not necessarily the manifest that was signed: re-serialized JSON with different key order, or a document with a repeated key where json.loads silently keeps the last, would otherwise pass. A test that only feeds it garbage will not reach either.
Pattern to copy
#394 landed the shape at tests/test_packaging.py: build a real overlay with build_cython_overlay, rewrite manifest.json, assert the specific CythonOverlayManifestError, then assert nothing was applied (sources intact, no artifacts, no installed manifest, RECORD byte-identical). The helpers _read_manifest_payload and _write_manifest_payload are already there.
Note that _write_manifest_payload writes with indent=2, sort_keys=True, which is canonical, so a canonical-JSON test needs to write the bytes directly rather than through that helper.
Definition of done
Each of the four refusals is the only failure when its own raise is neutered.
The canonical-JSON case uses a payload that is valid JSON and semantically identical to the original, differing only in serialization, so it proves the refusal is about form rather than content.
The duplicate-fields case uses raw bytes with a repeated key, since no Python dict can express it.
The _require_* helpers from :1986 down (must be an object, has unexpected fields, must be an integer, must be positive, must use POSIX separators, must remain within its root, must be a lowercase SHA-256). Sixteen small refusals sharing one shape; they want a parametrized test of their own and would swamp this issue.
Prerequisite
These tests build a real native overlay, so they need a system C compiler (cc). See the development setup in CONTRIBUTING.md; #398 added that prerequisite this afternoon.
Validation
uv sync --locked --all-extras
uv run ruff check
uv run ruff format --check
uv run ty check
uv run pytest -q
#393 covered the seven refusals in
_validate_manifestthat one valid-manifest fixture can reach, and #394 landed them. That issue explicitly deferred the rest:This is that follow-up. These refusals run before
_validate_manifest, on the raw bytes of an overlay directory'smanifest.json, which is external input.Verification
Against
mainat44e4f50, each refusal neutered in turn, runningtests/test_packaging.py:What to do
Cover the parse-stage refusals, in
src/hflow/packaging.py:The canonical-JSON and duplicate-fields ones are the interesting pair. Both exist because a manifest that parses is not necessarily the manifest that was signed: re-serialized JSON with different key order, or a document with a repeated key where
json.loadssilently keeps the last, would otherwise pass. A test that only feeds it garbage will not reach either.Pattern to copy
#394 landed the shape at
tests/test_packaging.py: build a real overlay withbuild_cython_overlay, rewritemanifest.json, assert the specificCythonOverlayManifestError, then assert nothing was applied (sources intact, no artifacts, no installed manifest, RECORD byte-identical). The helpers_read_manifest_payloadand_write_manifest_payloadare already there.Note that
_write_manifest_payloadwrites withindent=2, sort_keys=True, which is canonical, so a canonical-JSON test needs to write the bytes directly rather than through that helper.Definition of done
raiseis neutered.Not in scope
The
_require_*helpers from:1986down (must be an object,has unexpected fields,must be an integer,must be positive,must use POSIX separators,must remain within its root,must be a lowercase SHA-256). Sixteen small refusals sharing one shape; they want a parametrized test of their own and would swamp this issue.Prerequisite
These tests build a real native overlay, so they need a system C compiler (
cc). See the development setup in CONTRIBUTING.md; #398 added that prerequisite this afternoon.Validation