Skip to content

Extract bounty API routes from app.main#393

Merged
ramimbo merged 1 commit into
ramimbo:mainfrom
rebel117:fix-390-extract-bounty-api-routes
May 26, 2026
Merged

Extract bounty API routes from app.main#393
ramimbo merged 1 commit into
ramimbo:mainfrom
rebel117:fix-390-extract-bounty-api-routes

Conversation

@rebel117
Copy link
Copy Markdown

@rebel117 rebel117 commented May 26, 2026

Problem

app/main.py was 1427 lines with bounty listing, CRUD, payment, close, reconciliation, and webhook-events routes all defined inline. This made the file harder to navigate and review independently from page routes, wallet routes, auth routes, etc.

Changes

Moved bounty API route registration into app/bounty_api.py:

  • list_bounties_by_status() — search/filter with status normalization, LIKE escaping, and issue-number lookup
  • GET /api/v1/bounties and /api/v1/bounties/summary
  • GET /api/v1/bounties/{bounty_id}
  • POST /api/v1/bounties (create, admin-only)
  • POST /api/v1/bounties/{bounty_id}/pay (admin-only)
  • POST /api/v1/bounties/{bounty_id}/close (admin-only)
  • GET /api/v1/reconciliation/payouts (admin-only)
  • GET /api/v1/admin/webhook-events (admin-only)
  • _payout_response_from_proof() and _existing_payout_proof_for_submission() helpers

The extracted register_bounty_api_routes() returns list_bounties_by_status and get_bounty_detail so page routes in app/main.py can call them without duplicating the search logic.

Complexity reduced

app/main.py drops from 1427 to 1196 lines (−231 lines). Bounty CRUD/payment/close routes are now independently reviewable. The pattern matches existing extraction modules (register_account_routes, register_activity_routes, register_bounty_attempt_routes).

Verification

python -m pytest              # 384 passed
python -m ruff format --check .  # 66 files formatted
python -m ruff check .        # All checks passed
python -m mypy app            # Success: no issues found
git diff --check              # no whitespace errors

No public API, MCP, ledger, wallet, webhook, admin, or page behavior changed.

Refs #390

Summary by CodeRabbit

Release Notes

  • New Features

    • Bounty API introduces comprehensive endpoints for managing bounties including listing with status and text filtering, creating bounties, viewing details with award information, processing payments with proof tracking, closing bounties, generating payout reconciliation reports, and providing admin access to webhook events.
  • Tests

    • Added extensive test coverage for all Bounty API routes validating list operations, filtering, detail retrieval, creation, payment processing, closure, reconciliation, and webhook functionality.

Review Change Stack

Moves bounty listing, CRUD, payment, close, and reconciliation route
registration out of the main application module into a focused
app/bounty_api module.

What moved:
- list_bounties_by_status search/filter logic
- GET /api/v1/bounties and /api/v1/bounties/summary
- GET /api/v1/bounties/{bounty_id}
- POST /api/v1/bounties (create)
- POST /api/v1/bounties/{bounty_id}/pay
- POST /api/v1/bounties/{bounty_id}/close
- GET /api/v1/reconciliation/payouts
- GET /api/v1/admin/webhook-events
- Payout response shaping helpers

main.py drops from 1427 to 1196 lines. The bounty page routes in
main.py now call through the returned functions from
register_bounty_api_routes, keeping the same public behavior.

13 new route-level tests cover status filtering, query search,
auth gating on admin-only endpoints, and error responses.

Checks: 384 passed, ruff format/check clean, mypy clean.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5fe2de25-b414-400e-9b3a-3e28b5d0c879

📥 Commits

Reviewing files that changed from the base of the PR and between a1795ed and 0111eaa.

📒 Files selected for processing (3)
  • app/bounty_api.py
  • app/main.py
  • tests/test_bounty_api.py

📝 Walkthrough

Walkthrough

This PR refactors bounty-related REST API endpoints from app/main.py into a dedicated app/bounty_api.py module. The new module registers GET/POST endpoints for listing, filtering, creating, paying, and closing bounties, plus payout reconciliation and admin webhook events, with helper functions for payout response formatting and idempotency checking. Integration wiring in app/main.py and comprehensive route tests complete the refactoring.

Changes

Bounty API Module Extraction

Layer / File(s) Summary
Module setup and payout helpers
app/bounty_api.py (imports, helpers)
Module imports FastAPI, SQLAlchemy, ledger, and serialization utilities. Helper functions _payout_response_from_proof and _existing_payout_proof_for_submission parse stored proofs and query for existing payout records to support idempotent payment handling.
Public read endpoints: list, summary, details
app/bounty_api.py (GET endpoints)
GET endpoints for /api/v1/bounties (with status/text filtering and issue-number matching), /api/v1/bounties/summary, /api/v1/admin/webhook-events, and /api/v1/bounties/{bounty_id} fetch bounty data, optional filters are validated and escaped, and responses are enriched with derived fields.
Admin write endpoints: create and close
app/bounty_api.py (POST endpoints)
POST /api/v1/bounties creates a new bounty from request JSON and returns the created bounty with created_by metadata; admin authentication required. POST /api/v1/bounties/{bounty_id}/close marks a bounty closed with optional reference and closed_by fields; ledger errors map to HTTP 400.
Admin payment operations: reconciliation and pay
app/bounty_api.py (payment routes)
GET /api/v1/reconciliation/payouts runs payout reconciliation and returns summary plus check records. POST /api/v1/bounties/{bounty_id}/pay validates submission URL, constructs verifier payload, calls pay_bounty, and shapes response. If submission already paid, performs idempotent lookup and returns HTTP 409; other ledger errors become HTTP 400.
Integration: imports and route delegation in main.py
app/main.py
Import statements updated to remove inlined bounty helpers and add register_bounty_api_routes. The function is called during app initialization, returns list_bounties_by_status and api_bounty handlers for use by HTML routes, and wires all REST endpoints into the FastAPI app.
Comprehensive test coverage
tests/test_bounty_api.py
New pytest module with a FastAPI TestClient fixture and route tests covering bounty listing (status filtering, invalid status error), bounty details (404 for missing id, 400 for invalid), and auth enforcement (401 for unauthenticated requests to create, pay, close, reconciliation, and webhook-events endpoints).

Sequence Diagram

sequenceDiagram
  participant Admin
  participant BountyAPI
  participant Ledger
  Admin->>BountyAPI: POST /api/v1/bounties/{id}/pay
  BountyAPI->>BountyAPI: validate_public_url(), normalize input
  BountyAPI->>Ledger: pay_bounty() with verifier
  alt Already paid
    Ledger-->>BountyAPI: LedgerError("submission already paid")
    BountyAPI->>BountyAPI: _existing_payout_proof_for_submission()
    BountyAPI-->>Admin: HTTP 409 already_paid payload
  else Success
    Ledger-->>BountyAPI: Proof object
    BountyAPI->>BountyAPI: _payout_response_from_proof()
    BountyAPI-->>Admin: HTTP 200 payout response
  else Validation error
    Ledger-->>BountyAPI: LedgerError
    BountyAPI-->>Admin: HTTP 400 error detail
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • ramimbo/mergework#311: Both PRs implement the same /api/v1/bounties/summary functionality (filtering by status/q and returning a listing summary), with this PR refactoring/relocating the summary route into app/bounty_api.py rather than keeping it in app/main.py.

Suggested labels

mrwk:accepted

Suggested reviewers

  • tolga-tom-nook
  • weilixiong
  • bitdamii
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and accurately summarizes the primary change: extracting bounty API routes from the main application file into a separate module.
Description check ✅ Passed The description comprehensively covers the problem, changes made, complexity reduction, and verification results. All template sections are adequately addressed with specific details.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

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.

Reviewed current head $(git rev-parse --short HEAD) for the bounty API route extraction.

Evidence checked:

  • Inspected app/bounty_api.py, app/main.py, and tests/test_bounty_api.py; the extracted registration keeps the existing route dependencies explicit (require_admin_token, JSON/body validators, settings, and db URL) and returns the callback hooks that app.main still uses for bounty pages.
  • Verified search/status behavior remains covered in the new focused test file, including query escaping/status filtering and issue-number search paths.
  • Re-ran the focused behavior and static checks locally:
    • python -m pytest tests/test_bounty_api.py tests/test_bounty_pages.py tests/test_bounty_attempts.py -q -> 24 passed
    • python -m ruff check app/bounty_api.py app/main.py tests/test_bounty_api.py -> passed
    • python -m ruff format --check app/bounty_api.py app/main.py tests/test_bounty_api.py -> passed
    • python -m mypy app/main.py app/bounty_api.py -> passed
    • git diff --check origin/main...HEAD -> passed

No blockers found.

Copy link
Copy Markdown
Contributor

@tolga-tom-nook tolga-tom-nook left a comment

Choose a reason for hiding this comment

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

Reviewed current head 0111eaa for PR #393. No blockers from this pass.

Evidence checked:

  • Inspected app/bounty_api.py, the removed bounty/admin/reconciliation route registrations in app/main.py, and tests/test_bounty_api.py.
  • Verified the extracted register_bounty_api_routes() keeps the existing listing, summary, detail, admin webhook-events, create, pay, close, and payout reconciliation route shapes wired through injected helpers/settings.
  • Checked the payout idempotency path still returns the existing proof payload on submission already paid, and that invalid bounty ids still pass through positive_bounty_id() before DB access.
  • Confirmed the new focused tests cover public list/detail validation plus auth gates for create/pay/close/reconciliation/webhook-events.

Validation run locally on head 0111eaa:

  • ./.venv/bin/python -m pytest tests/test_bounty_api.py tests/test_api_mcp.py::test_health_status_and_bounty_api tests/test_api_mcp.py::test_bounty_api_reports_multi_award_capacity tests/test_api_mcp.py::test_bounty_api_reports_paid_multi_award_as_exhausted tests/test_api_mcp.py::test_bounty_api_reports_closed_multi_award_as_unavailable -q -> 17 passed
  • ./.venv/bin/python -m pytest -q -> 384 passed
  • ./.venv/bin/python -m ruff check app/bounty_api.py app/main.py tests/test_bounty_api.py -> passed
  • ./.venv/bin/python -m ruff format --check app/bounty_api.py app/main.py tests/test_bounty_api.py -> passed
  • ./.venv/bin/python -m mypy app -> passed

@ramimbo ramimbo merged commit 7609aee into ramimbo:main May 26, 2026
2 checks passed
@ramimbo ramimbo added mrwk:accepted Maintainer accepted for payout mrwk:paid Ledger payment recorded labels May 26, 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.

4 participants