Skip to content

Reject boolean bounty identifiers#245

Closed
TUPM96 wants to merge 1 commit into
ramimbo:mainfrom
TUPM96:codex/bounty-228-reject-bool-bounty-ids
Closed

Reject boolean bounty identifiers#245
TUPM96 wants to merge 1 commit into
ramimbo:mainfrom
TUPM96:codex/bounty-228-reject-bool-bounty-ids

Conversation

@TUPM96
Copy link
Copy Markdown
Contributor

@TUPM96 TUPM96 commented May 25, 2026

Refs #228

Summary

  • Add a shared service-layer positive integer guard that rejects booleans before they can alias 1.
  • Apply the guard to bounty creation, bounty lookup, bounty payout, and bounty close paths.
  • Add regression coverage for boolean issue_number, max_awards, and bounty_id values.

Repro Before Fix

A direct service call with issue_number=True or bounty_id=True was accepted because Python treats True as integer 1. That could create a bounty for issue #1, or pay/close bounty id 1, instead of rejecting malformed identifiers.

Verification

  • uv run --python 3.12 --extra dev python -m pytest tests/test_ledger.py -q -> 18 passed
  • uv run --python 3.12 --extra dev python -m pytest -q -> 207 passed, 2 warnings
  • uv run --python 3.12 --extra dev ruff check . -> all checks passed
  • uv run --python 3.12 --extra dev ruff format --check . -> 37 files already formatted
  • 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, PayPal details, or MRWK price claims are included.

Copilot AI review requested due to automatic review settings May 25, 2026 09:05
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR tightens validation around integer identifiers used in ledger bounty operations, ensuring booleans (which are int subclasses in Python) are rejected and adding regression tests for those cases.

Changes:

  • Added _positive_int helper to validate “positive, non-boolean int” inputs and reused it in create_bounty, pay_bounty, and close_bounty.
  • Updated find_bounty_by_issue to validate issue_number via _positive_int.
  • Added tests to ensure boolean issue_number, max_awards, and bounty_id are rejected with clear LedgerErrors.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
tests/test_ledger.py Adds regression tests covering boolean inputs for issue numbers, max awards, and bounty IDs.
app/ledger/service.py Centralizes positive-int validation and applies it to bounty creation and mutation paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread app/ledger/service.py
Comment on lines +152 to +157
def _positive_int(value: int, field: str) -> int:
if isinstance(value, bool) or not isinstance(value, int):
raise LedgerError(f"{field} must be an integer")
if value <= 0:
raise LedgerError(f"{field} must be positive")
return value
Comment thread app/ledger/service.py
Comment on lines 431 to 437
def find_bounty_by_issue(session: Session, repo: str, issue_number: int) -> Bounty | None:
clean_issue_number = _positive_int(issue_number, "issue_number")
return session.scalar(
select(Bounty).where(Bounty.repo == repo, Bounty.issue_number == issue_number).limit(1)
select(Bounty)
.where(Bounty.repo == repo, Bounty.issue_number == clean_issue_number)
.limit(1)
)
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.

Evidence checked:

  • Inspected app/ledger/service.py and confirmed _positive_int() rejects booleans/non-integers before True can alias issue or bounty id 1, while still preserving the existing positive checks and the max_awards upper bound.
  • Confirmed create_bounty() now uses cleaned issue_number / max_awards values consistently for duplicate lookup, reservation math, and persisted bounty fields.
  • Confirmed find_bounty_by_issue(), pay_bounty(), and close_bounty() all pass their ids through the same guard before database lookup or ledger mutation.
  • Inspected tests/test_ledger.py coverage for boolean issue_number, boolean max_awards, boolean bounty_id on payout/close, and the post-failure state checks that the bounty remains open and Alice receives no balance.
  • Ran local validation on PR head 92c848c: focused boolean-id tests -> 2 passed; broader ledger/webhook suite -> 31 passed; Ruff check passed; Ruff format check already formatted; git diff --check origin/main...HEAD -> clean.
  • Checked GitHub shows clean merge state and hosted Quality, readiness, docs, and image checks successful.

No secrets, wallet material, private deployment values, payout details, or MRWK price claims were used.

Copy link
Copy Markdown
Contributor

@ayskobtw-lil ayskobtw-lil 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 review.

Evidence checked:

  • Inspected app/ledger/service.py and tests/test_ledger.py; _positive_int() rejects booleans before Python can treat True as id/issue 1, while preserving the existing positive checks and max_awards upper bound.
  • Confirmed create_bounty() now stores and searches by the cleaned issue_number/max_awards values, so duplicate detection and reserve sizing use the validated integers.
  • Confirmed find_bounty_by_issue(), pay_bounty(), and close_bounty() validate direct service-layer identifiers before reading or mutating bounty rows.
  • Verified the mutation regression leaves the bounty open with awards_paid == 0 and no payout balance after boolean bounty_id attempts.
  • Ran python -m pytest tests/test_ledger.py::test_create_bounty_rejects_boolean_issue_number_or_awards tests/test_ledger.py::test_bounty_mutations_reject_boolean_bounty_id tests/test_ledger.py::test_create_bounty_rejects_non_positive_issue_number tests/test_ledger.py::test_close_bounty_releases_unpaid_awards -q -> 4 passed.
  • Ran python -m ruff check app/ledger/service.py tests/test_ledger.py -> passed.
  • Ran python -m ruff format --check app/ledger/service.py tests/test_ledger.py -> 2 files already formatted.
  • Ran git diff --check origin/main...HEAD -> clean.

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

@ramimbo ramimbo added the mrwk:rejected Submission rejected label May 26, 2026
@ramimbo
Copy link
Copy Markdown
Owner

ramimbo commented May 26, 2026

Closing this stale small-fix PR to clear the filled #228/#292 queue. #292 is now filled, no fresh small-fixes round is open, and this remaining work is not accepted in this pass.

@ramimbo ramimbo closed this May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mrwk:rejected Submission rejected

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants