Skip to content

Reject unserializable proof metadata values#257

Merged
ramimbo merged 1 commit into
ramimbo:mainfrom
SylvainWinning:codex/mergework-228-proof-metadata-values
May 25, 2026
Merged

Reject unserializable proof metadata values#257
ramimbo merged 1 commit into
ramimbo:mainfrom
SylvainWinning:codex/mergework-228-proof-metadata-values

Conversation

@SylvainWinning
Copy link
Copy Markdown
Contributor

Bounty #228

Summary

  • Reject verifier_result dictionaries that contain values canonical JSON cannot serialize.
  • Raise a controlled LedgerError before payout submission/proof rows or award counters are mutated.
  • Add a regression for {"label": "mrwk:accepted", "raw": object()} that verifies no payment state is recorded.

Repro before fix

A direct pay_bounty() call with verifier_result={"label": "mrwk:accepted", "raw": object()} raised a raw TypeError: Object of type object is not JSON serializable while building proof metadata, instead of failing closed with a ledger validation error before payout state changes.

This is distinct from the existing non-string metadata-key and non-object metadata-shape PRs: this PR covers JSON-incompatible values inside an otherwise object-shaped metadata dict.

Verification

  • Red before fix: uv run --python 3.12 --extra dev python -m pytest tests/test_ledger.py::test_pay_bounty_rejects_non_json_serializable_verifier_result_values -q failed with the raw TypeError.
  • uv run --python 3.12 --extra dev python -m pytest tests/test_ledger.py::test_pay_bounty_rejects_non_json_serializable_verifier_result_values -q -> 1 passed
  • uv run --python 3.12 --extra dev python -m pytest tests/test_ledger.py -q -> 17 passed
  • uv run --python 3.12 --extra dev python -m pytest -q -> 206 passed, 2 warnings
  • uv run --python 3.12 --extra dev ruff format --check . -> 37 files already formatted
  • uv run --python 3.12 --extra dev ruff check . -> all checks passed
  • uv run --python 3.12 --extra dev python -m mypy app -> success
  • uv run --python 3.12 --extra dev python scripts/docs_smoke.py -> docs smoke ok
  • uv run --python 3.12 --extra dev python scripts/check_agents.py -> AGENTS.md ok
  • git diff --check -> clean

No secrets, wallet material, private vulnerability details, deployment values, payout details, or MRWK price claims are included.

Copy link
Copy Markdown

@weilixiong weilixiong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review ✅ APPROVED

LOW — rejects unserializable proof metadata via canonical_json. Clean validation. MW #219.

Copy link
Copy Markdown

@Thanhdn1984 Thanhdn1984 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed for bounty #219.

Evidence checked:

  • app/ledger/service.py now validates the cleaned verifier_result with canonical_json(clean) before writing the proof metadata.
  • The new test covers an object() value, expects LedgerError, and verifies no payout/submission/proof side effects plus unchanged reserve balance.

Result: looks correct and aligned with the issue. No changes requested.

Copy link
Copy Markdown
Contributor

@MolhamHamwi MolhamHamwi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers found on current head 8dd1502.

Evidence checked:

  • Inspected app/ledger/service.py::_clean_proof_metadata(); the new canonical_json(clean) validation runs before returning metadata, so unserializable values fail before proof/submission rows are created.
  • Confirmed the raised LedgerError wraps TypeError/ValueError from JSON canonicalization and leaves the existing control-character validation path intact.
  • Inspected tests/test_ledger.py; the regression exercises pay_bounty() with an object() metadata value and verifies no award count, balance, submission, or proof side effects are persisted.
  • Ran pytest tests/test_ledger.py -q (17 passed), ruff check app/ledger/service.py tests/test_ledger.py, ruff format --check app/ledger/service.py tests/test_ledger.py, and git diff --check origin/main...HEAD.

No secrets, wallet/private-key material, payout credentials, private deployment values, private vulnerability details, or MRWK price claims were reviewed or disclosed.

@wangedmund77-cmyk
Copy link
Copy Markdown

No blockers from my review.

Evidence checked:

  • Inspected app/ledger/service.py and tests/test_ledger.py; verifier metadata is now canonical-JSON checked before payout state is recorded, and the regression asserts awards/submissions/proofs remain unchanged after rejection.
  • Ran uv run --extra dev pytest tests/test_ledger.py -q on PR branch pr-257: 17 passed.
  • Ran uv run --extra dev ruff check app/ledger/service.py tests/test_ledger.py: all checks passed.

The added guard converts the previous serialization failure class into a controlled LedgerError before mutation.

Copy link
Copy Markdown
Contributor

@TateLyman TateLyman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers from my pass. The metadata guard catches JSON-canonicalization failures before payout mutation, which is the right boundary for proof payload integrity.

Evidence checked:

  • Inspected _clean_proof_metadata() in app/ledger/service.py; the new canonical_json(clean) call runs after control-character validation and before returning metadata to the payout/proof creation path.
  • Inspected tests/test_ledger.py; the regression drives pay_bounty() with an object() metadata value and then verifies no awards, submission, proof, contributor balance, or reserve balance side effects.
  • Ran uv run pytest tests/test_ledger.py::test_pay_bounty_rejects_non_json_serializable_verifier_result_values tests/test_ledger.py::test_bounty_reserve_and_payout_conserve_supply -q -> 2 passed.
  • Ran uv run ruff check app/ledger/service.py tests/test_ledger.py, uv run ruff format --check app/ledger/service.py tests/test_ledger.py, uv run mypy app, and git diff --check origin/main...HEAD -> passed.
  • Checked hosted Quality, readiness, docs, and image checks metadata -> success.

Non-blocking note: this is focused on value serializability; separate key-shape validation remains covered by the neighboring proof-metadata-key work.

@ramimbo ramimbo merged commit 0938b59 into ramimbo:main May 25, 2026
1 check passed
@ramimbo ramimbo added mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded labels May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants