Skip to content

Honor activity API pagination#918

Open
catcherintheroad-hub wants to merge 4 commits into
ramimbo:mainfrom
catcherintheroad-hub:codex/activity-api-pagination-799
Open

Honor activity API pagination#918
catcherintheroad-hub wants to merge 4 commits into
ramimbo:mainfrom
catcherintheroad-hub:codex/activity-api-pagination-799

Conversation

@catcherintheroad-hub
Copy link
Copy Markdown

@catcherintheroad-hub catcherintheroad-hub commented Jun 5, 2026

Bounty #799

Source report: #798 (comment)

Summary

  • Adds bounded canonical limit and offset support to the public /api/v1/activity endpoint.
  • Applies pagination after the existing query/account filtering while keeping totals and pending_totals representative of the full matching activity set.
  • Rejects repeated and non-canonical limit/offset query values before silently treating them as canonical intent.
  • Documents activity pagination fields and examples.

Production evidence before fix

Read-only checks against current production on 2026-06-05 UTC:

/api/v1/activity?limit=1 -> HTTP 200, contributors=150, first accounts [github:ckeplinger199, github:tatelyman, github:eliasx45], bytes=128283, sha256=8ee90b1eafb8
/api/v1/activity?limit=1&offset=1 -> HTTP 200, contributors=150, first accounts [github:ckeplinger199, github:tatelyman, github:eliasx45], bytes=128283, sha256=8ee90b1eafb8
/api/v1/activity?offset=1 -> HTTP 200, contributors=150, first accounts [github:ckeplinger199, github:tatelyman, github:eliasx45], bytes=128283, sha256=8ee90b1eafb8
/api/v1/activity?limit=01 -> HTTP 200, contributors=150, first accounts [github:ckeplinger199, github:tatelyman, github:eliasx45], bytes=128283, sha256=8ee90b1eafb8

Duplicate / scope check

Validation

  • uv run --python 3.12 --extra dev python -m pytest tests/test_activity.py tests/test_activity_routes.py tests/test_docs_public_urls.py -q -> 45 passed, 1 existing Starlette/httpx warning.
  • uv run --python 3.12 --extra dev ruff check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py docs/api-examples.md -> passed.
  • uv run --python 3.12 --extra dev ruff format --check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py -> 4 files already formatted.
  • uv run --python 3.12 --extra dev mypy app/activity.py app/serializers.py -> success.
  • uv run --python 3.12 --extra dev python scripts/docs_smoke.py -> docs smoke ok.
  • git diff --check origin/main...HEAD -> clean.
  • git merge-tree --write-tree origin/main HEAD -> clean tree abda6f4c7b8cc6d19c1ef4bc0fd2711b121cfce1.

Summary by CodeRabbit

  • New Features

    • Activity API supports paginated results via limit/offset (default page size 100) and returns pagination metadata.
  • Improvements

    • Activity lists (contributors, pending payouts, recent) are now served according to pagination parameters; totals still reflect the full filtered set.
  • Documentation

    • API examples updated to show pagination and multi-page retrieval.
  • Tests

    • Added tests for pagination behavior and for rejecting invalid/non-canonical pagination queries.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 5be093c3-d4fe-42ec-808d-496e8a1d6190

📥 Commits

Reviewing files that changed from the base of the PR and between cd8eefc and 85ea49d.

📒 Files selected for processing (2)
  • app/activity.py
  • tests/test_activity.py

📝 Walkthrough

Walkthrough

Adds limit/offset pagination to the /api/v1/activity endpoint: route accepts constrained limit and offset, validates them, forwards them through activity_context to activity_to_dict, and returns paginated slices plus pagination metadata in the response.

Changes

Activity API pagination

Layer / File(s) Summary
Pagination parameters and endpoint integration
app/activity.py, app/serializers.py
Add Annotated import; extend activity_context and the /api/v1/activity route to accept/validate limit and offset query params and pass them through to activity_to_dict.
Response payload slicing and pagination fields
app/serializers.py
activity_to_dict signature extended with limit/offset and now slices contributors, pending_payouts, and recent using [offset:offset+limit], and includes limit and offset in the returned query object.
Testing and API documentation
tests/test_activity.py, tests/test_activity_routes.py, tests/test_serializers.py, docs/api-examples.md
Add tests verifying pagination behavior and validation errors; update existing tests to expect limit/offset in activity shapes; add docs and curl example demonstrating second-page usage and updated sample response.

Possibly related PRs

  • ramimbo/mergework#380: Introduced prior activity context and endpoint wiring that this PR extends with pagination.
  • ramimbo/mergework#733: Changes pending_payouts handling in serializers; overlaps with this PR's slicing of pending_payouts.
  • ramimbo/mergework#821: Extended activity query filtering and shares code paths in activity_context/activity_to_dict.
🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Honor activity API pagination' directly names the changed surface and clearly summarizes the main change—adding pagination support to the /api/v1/activity endpoint.
Description check ✅ Passed The description includes all required sections from the template: Summary, Evidence (with production behavior and scope verification), Test Evidence (all checks listed and results documented), and MRWK (Bounty #799 referenced). All critical details are present and substantiated.
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.
Mergework Public Artifact Hygiene ✅ Passed PR adds pagination to /api/v1/activity without investment, price, or cash-out claims. Documentation correctly states pending work is not paid until treasury execution creates proof.
Bounty Pr Focus ✅ Passed PR changes only 6 files for /api/v1/activity pagination; no excluded surfaces altered. Tests verify limit/offset handling. Totals remain unsliced.

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


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

@catcherintheroad-hub
Copy link
Copy Markdown
Author

Follow-up for hosted CI failure on tests/test_serializers.py.

Updated head: 8c97892 Cover activity pagination defaults in serializer test.

Change since initial PR:

  • Added the new default limit: 100 and offset: 0 fields to the malformed-proof serializer regression's exact activity payload expectation.
  • No route or serializer behavior changed in the follow-up.

Updated validation:

  • uv run --python 3.12 --extra dev python -m pytest tests/test_serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_docs_public_urls.py -q -> 56 passed, 1 existing Starlette/httpx warning.
  • uv run --python 3.12 --extra dev python -m pytest -q -> 792 passed, 1 existing Starlette/httpx warning.
  • uv run --python 3.12 --extra dev ruff check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py docs/api-examples.md -> passed.
  • uv run --python 3.12 --extra dev ruff format --check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py -> 5 files already formatted.
  • uv run --python 3.12 --extra dev mypy app/activity.py app/serializers.py -> success.
  • uv run --python 3.12 --extra dev python scripts/docs_smoke.py -> docs smoke ok.
  • git diff --check origin/main...HEAD -> clean.
  • git merge-tree --write-tree origin/main HEAD -> clean tree ba7a420fdf81c77f6555e55c323dd508c0e25c58.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
docs/api-examples.md (2)

371-433: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the response example to match the pagination request.

Line 351 shows a request with limit=25&offset=25, but the response example at lines 383-384 shows "limit": 25, "offset": 0. Either update the response example to show "offset": 25, or clarify that the JSON response is for a different request (such as the query-filtered request at line 350, then add a separate pagination example).

📝 Proposed fix

Option 1: Update the response to match the paginated request at line 351:

   "query": "p3xill",
   "limit": 25,
-  "offset": 0,
+  "offset": 25,

Option 2: Add a note that the response is for the query-only request, then show a separate pagination response example after the curl at line 351.


435-438: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the 100-row cap explanation to reflect pagination.

Line 436 states that recent is "capped to the latest 100 matching rows." With pagination, recent is capped to limit rows starting from offset, not always 100.

📝 Proposed fix
 `contributors` is sorted by accepted MRWK amount, while `recent` is sorted by
-newest ledger sequence and capped to the latest 100 matching rows. Use
+newest ledger sequence and paginated using `limit` and `offset`. Use
 `proof_hash` with `/api/v1/proofs/<proof_hash>` to inspect the public proof
 payload for a payment.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: bbd823e0-403a-46d8-9220-78a3dbcee85a

📥 Commits

Reviewing files that changed from the base of the PR and between d4d0e48 and 8c97892.

📒 Files selected for processing (6)
  • app/activity.py
  • app/serializers.py
  • docs/api-examples.md
  • tests/test_activity.py
  • tests/test_activity_routes.py
  • tests/test_serializers.py

Comment thread app/activity.py
@catcherintheroad-hub
Copy link
Copy Markdown
Author

Follow-up for the docs review notes:

  • Updated the activity examples so the sample request matches the shown query/default offset response.
  • Replaced the stale recent-row 100-row cap wording with the current limit/offset pagination behavior.

Validation rerun:

  • uv run --python 3.12 --extra dev python scripts/docs_smoke.py
  • uv run --python 3.12 --extra dev python -m pytest tests/test_docs_public_urls.py -q
  • git diff --check origin/main...HEAD
  • git merge-tree --write-tree origin/main HEAD

@catcherintheroad-hub
Copy link
Copy Markdown
Author

Follow-up for the pagination control-character review note.

Updated head: 85ea49d Reject activity pagination controls early.

Change:

  • Explicitly reject control characters in limit and offset before repeated/noncanonical integer checks.
  • Added regressions for limit controls and for repeated limit/offset values where one value contains a control character, so the API reports the control-character error instead of masking it as a repeat.

Validation rerun:

  • uv run --python 3.12 --extra dev python -m pytest tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py tests/test_docs_public_urls.py -q
  • uv run --python 3.12 --extra dev ruff check app/activity.py tests/test_activity.py docs/api-examples.md
  • uv run --python 3.12 --extra dev ruff format --check app/activity.py tests/test_activity.py
  • uv run --python 3.12 --extra dev mypy app/activity.py app/serializers.py
  • uv run --python 3.12 --extra dev python scripts/docs_smoke.py
  • git diff --check origin/main...HEAD
  • git merge-tree --write-tree origin/main HEAD

Copy link
Copy Markdown
Contributor

@pqmfei pqmfei left a comment

Choose a reason for hiding this comment

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

Reviewed PR #918 at current head 85ea49dbc4eff3b9b304c86aa12f4fc5af1f6a65 as a non-author.

Evidence checked:

  • inspected app/activity.py, app/serializers.py, docs/api-examples.md, tests/test_activity.py, tests/test_activity_routes.py, and tests/test_serializers.py;
  • verified /api/v1/activity now accepts bounded canonical limit and offset, rejects control-character, repeated, and non-canonical pagination params before using the coerced integers, and preserves existing q/account guards;
  • verified activity_to_dict() keeps aggregate totals over the full matching activity set while applying offset:offset + limit slices to contributors, pending_payouts, and recent;
  • confirmed the latest follow-ups addressed the stale docs example/cap wording and the control-character masking order for pagination params;
  • checked #838 public bounty row 109 is open with 30 effective awards remaining, and scripts/review_bounty_candidates.py --repo ramimbo/mergework --reviewer pqmfei --format text still reports PR #918 as candidate_for_fresh_review.

Validation on this exact head:

  • .\.venv\Scripts\python.exe -m pytest tests\test_activity.py tests\test_activity_routes.py tests\test_serializers.py tests\test_docs_public_urls.py -q -> 56 passed, 1 existing Starlette/httpx warning.
  • .\.venv\Scripts\python.exe -m ruff check app\activity.py app\serializers.py tests\test_activity.py tests\test_activity_routes.py tests\test_serializers.py docs\api-examples.md -> passed.
  • .\.venv\Scripts\python.exe -m ruff format --check app\activity.py app\serializers.py tests\test_activity.py tests\test_activity_routes.py tests\test_serializers.py -> 5 files already formatted.
  • .\.venv\Scripts\python.exe -m mypy app\activity.py app\serializers.py -> success.
  • .\.venv\Scripts\python.exe scripts\docs_smoke.py -> docs smoke ok.
  • git diff --check origin/main...HEAD -> clean.
  • git merge-tree --write-tree origin/main HEAD -> clean tree 95c4ae00c0c95aaf8ac0578bf5f77b41503cf256.

GitHub state before review: hosted Quality, readiness, docs, and image checks is successful; mergeStateStatus=UNSTABLE only because CodeRabbit is still pending on the latest head, so maintainers should still account for any later bot feedback before merging.

Scope: read-only review of public activity API pagination and docs/tests. No admin-token APIs, bounty creation, payout execution, treasury mutation, ledger mutation, wallet behavior, private data, credentials, exchange, bridge, cash-out, or MRWK price behavior was used or changed.

Copy link
Copy Markdown
Contributor

@szx19970521 szx19970521 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 85ea49d for the activity API pagination change.

What I checked:

  • �pp/activity.py: limit/offset are bounded, reject control characters, reject repeated params, and reject noncanonical integer forms before forwarding into the activity context.
  • �pp/serializers.py: pagination slices contributors, pending_payouts, and
    ecent after filtering while preserving full aggregate totals.
  • docs/api-examples.md: pagination wording and examples now match the current response shape; earlier CodeRabbit docs comments are addressed.
  • Tests cover default response shape, limit/offset paging, invalid pagination values, and control-character masking cases.

Validation run locally on this head:

  • python -m pytest tests/test_serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_docs_public_urls.py -q -> 56 passed, 1 existing Starlette/httpx warning.

uff check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py docs/api-examples.md -> passed.

uff format --check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py -> 5 files already formatted.

  • mypy app/activity.py app/serializers.py -> success.
  • python scripts/docs_smoke.py -> docs smoke ok.

Hosted Quality is green and the latest CodeRabbit pass reports no actionable comments. I did not find blocking issues.

Copy link
Copy Markdown
Contributor

@alan747271363-art alan747271363-art left a comment

Choose a reason for hiding this comment

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

Reviewed PR #918 at current head 85ea49dbc4eff3b9b304c86aa12f4fc5af1f6a65 against current origin/main (d7e9b530fffec7bd774da7708597648096a37393).

The activity pagination changes still validate on the branch itself, but this PR is now blocked by a current-main merge conflict in app/activity.py. GitHub now reports mergeStateStatus=DIRTY / mergeable=CONFLICTING, and I reproduced the conflict locally:

git merge-tree --write-tree $(git rev-parse origin/main) HEAD
# Auto-merging app/activity.py
# CONFLICT (content): Merge conflict in app/activity.py

Validation on this exact head before posting:

  • python -m pytest tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py tests/test_docs_public_urls.py -q -> 56 passed, 1 existing Starlette/httpx warning.
  • python -m ruff check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py docs/api-examples.md -> passed.
  • python -m ruff format --check app/activity.py app/serializers.py tests/test_activity.py tests/test_activity_routes.py tests/test_serializers.py -> 5 files already formatted.
  • python -m mypy app/activity.py app/serializers.py -> success.
  • python scripts/docs_smoke.py -> docs smoke ok.
  • git diff --check origin/main...HEAD -> clean.

Requested changes until the branch is rebased/resolved against current origin/main and the same focused activity/docs checks are rerun. The hosted Quality and CodeRabbit checks are green on the PR head, but they do not remove the current merge conflict.

Scope checked: public activity API pagination and related serializer/docs/tests only. No admin APIs, wallet behavior, payout execution, treasury mutation, ledger mutation, private data, credentials, exchange, bridge, cash-out, or MRWK price behavior was used.

Copy link
Copy Markdown

@heickerv1001-dev heickerv1001-dev left a comment

Choose a reason for hiding this comment

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

Bounty #838 review: I rechecked current head 85ea49d on app/activity.py, app/serializers.py, tests/test_activity.py, tests/test_activity_routes.py, and docs/api-examples.md. The new limit/offset flow paginates after filtering, keeps totals representative of the full matching set, and the invalid/repeated/control-char cases are covered in tests. I also checked the open PR list for overlapping /api/v1/activity pagination work and did not find another active PR on the same scope. GitHub still reports mergeable_state=dirty, so this needs a rebase before it can merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants