Addresses the four release-critical blockers from Timmy's review of PR #42:
1. Guard enum/allowlist membership against unhashable JSON (lists/dicts) in
form.state, receipt.signed_by, and validate_transition target.
2. Require audience_choice.source_issue to be a positive non-bool integer.
3. Make power/scar/cost deltas structured (before -> after), not prose.
4. Remove tracked .pyc bytecode; prove clean checkout stays clean after tests.
Adds 21 new negative tests across HostileJsonFailClosedTests,
SourceIssueValidationTests, and StructuredDeltaTests.
Based on PR #42 head (0b74302). Vincent retains full authorship of the
canon validator, lifecycle model, and r2 review response; this branch
contains only the integration fixes needed to make the stated security
contract true at hostile-input boundaries.
Refs: #19, PR #42
Rebased onto PR #12 head (47ca557). Vincent-only delta, no add/add conflict,
no tracked bytecode. All seven review items fixed:
3. schema_version bumped to 2 and ENFORCED (rejects v1, rejects missing)
2. audience_choice requires the chosen form to be the SOLE survivor and
every other form to be archive_ghost
5. receipts require non-empty action + exact power/scar/cost deltas;
provenance is structured {source_issue:int, pull:int|commit:hex}
6. true configured signer allowlist (frozenset); human:anyone rejected
7. non-empty audience source fields; malformed containers/items return
errors and never raise (fail-closed)
New negative tests for every reproduced bypass. Full clean-checkout suite:
51/51 pass; __pycache__ gitignored so a clean checkout stays clean.
Closes#19
Refs: #3, #13, PR #12, PR #18