Skip to content

Extract public serialization helpers#330

Merged
ramimbo merged 1 commit into
ramimbo:mainfrom
TateLyman:codex/refactor-public-formatters
May 25, 2026
Merged

Extract public serialization helpers#330
ramimbo merged 1 commit into
ramimbo:mainfrom
TateLyman:codex/refactor-public-formatters

Conversation

@TateLyman
Copy link
Copy Markdown
Contributor

@TateLyman TateLyman commented May 25, 2026

Refs #320

Summary

  • Extracted public response shaping from app/main.py into app/serializers.py, covering bounty rows, bounty summaries, ledger rows, activity/account accepted-work summaries, wallet rows, and transfer rows.
  • Kept route wiring, auth/session handling, admin flows, and request parsing in app/main.py; the extracted module now owns reusable public serialization behavior.
  • Added focused serializer tests so public capacity, accepted-work, and wallet response shapes are locked down independently of the route layer.

Validation

  • uv run --extra dev python -m pytest tests/test_serializers.py tests/test_api_mcp.py::test_bounty_api_reports_multi_award_capacity tests/test_activity.py -q -> 6 passed
  • uv run --extra dev python -m pytest tests/test_api_mcp.py tests/test_activity.py tests/test_wallet_api.py tests/test_security.py -q -> 154 passed
  • uv run --extra dev python -m pytest -q -> 290 passed
  • uv run --extra dev ruff check app/main.py app/serializers.py tests/test_serializers.py -> passed
  • uv run --extra dev ruff format --check app/main.py app/serializers.py tests/test_serializers.py -> passed
  • uv run --extra dev mypy app -> success
  • git diff --check -> passed

Summary by CodeRabbit

  • Tests

    • Added end-to-end serializer regression tests verifying stable public shapes/values for bounties, payouts, accounts, activity, ledger entries, and wallets.
  • Refactor

    • Moved public-facing serialization into a dedicated module, consolidating how bounties, awards, payout reconciliations, activity feeds, account summaries, and wallet data are presented to external callers.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 25, 2026

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Extracts serialization helpers from app/main.py into a new app/serializers.py, updates app/main.py to import those helpers, and adds end-to-end tests that assert public JSON shapes remain unchanged.

Changes

Serialization Module Extraction

Layer / File(s) Summary
Serializers module foundation and bounty serialization
app/serializers.py
Introduces serializers module and implements bounty_to_dict, bounty_awards_to_dict, and bounty_list_summary with MRWK formatting, remaining-awards calculation, and ISO timestamps.
Ledger and reconciliation serialization
app/serializers.py
Adds payout_reconciliation_to_dict and ledger_to_dict to serialize reconciliation checks and ledger entries (optional proof_hash), timestamps, and evidence references.
Activity helpers and aggregation
app/serializers.py
Adds helpers to build bounty/detail URLs and activity rows, free-text matching, and activity_to_dict which queries joined ledger/proof rows, de-duplicates, filters, aggregates contributors, and returns totals/recent lists.
Account accepted-work views and safe wrappers
app/serializers.py
Implements account_accepted_summary, accepted_work_for_account, empty_accepted_summary, and safe_ wrappers that return stable empty/zero shapes on exceptions.
Wallet and transfer serialization
app/serializers.py
Adds _wallet_timestamp, wallet_to_dict (includes balance via get_balance, nonce, normalized timestamps), and wallet_transfer_to_dict.
app/main.py refactor to use serializers module
app/main.py
Removes inline serializer implementations, updates imports to pull serializers from app.serializers, and drops unused datetime/Decimal and AcceptedPayoutCheck import.
Serializer end-to-end tests
tests/test_serializers.py
Adds tests test_bounty_serializers_preserve_public_capacity_fields and test_account_and_wallet_serializers_preserve_public_shapes validating public shapes and aggregated values.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ramimbo/mergework#295: Overlaps with extraction of safe accepted-work/account serialization helpers moved here.
  • ramimbo/mergework#294: Related payout reconciliation serialization refactor that this PR consolidates into app/serializers.py.
  • ramimbo/mergework#311: Adds a bounties summary endpoint that depends on bounty_list_summary moved in this PR.

Suggested reviewers

  • Karry2019web
  • weilixiong
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 54.17% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Extract public serialization helpers' directly and concisely describes the main change: moving serialization functions from app/main.py to a new app/serializers.py module.
Description check ✅ Passed The description covers the main summary, references the related issue, and includes comprehensive validation evidence, though some template sections like Evidence/Confusion and the test checklist are minimally addressed.
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

@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 on current head f674c58fe297674236dce9f276575a661156d973.

Evidence checked:

  • Inspected app/main.py, the new app/serializers.py, and tests/test_serializers.py.
  • Compared the extracted serializer helpers against the prior app/main.py implementations for bounty rows/summaries, payout reconciliation rows, ledger rows, activity/account accepted-work summaries, wallet rows, and wallet transfer rows.
  • Verified route-layer imports still call the extracted helpers and keep auth/session/request handling in app/main.py.
  • Verified the new serializer tests cover capacity fields, accepted-work summary/list shape, and wallet row shape.

Validation run locally:

  • python -m pytest tests/test_serializers.py tests/test_api_mcp.py::test_bounty_api_reports_multi_award_capacity tests/test_activity.py tests/test_wallet_api.py::test_wallet_api_register_lookup_and_transfer -q -> 7 passed.
  • python -m ruff check app/main.py app/serializers.py tests/test_serializers.py -> passed.
  • python -m ruff format --check app/main.py app/serializers.py tests/test_serializers.py -> passed.
  • python -m mypy app/main.py app/serializers.py -> success.
  • git diff --check origin/main...HEAD -> clean.

Residual risk is limited to moved helper behavior not covered by the focused tests, but the diff appears to preserve the existing public response shapes rather than changing semantics.

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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/serializers.py`:
- Around line 336-339: The helper _wallet_timestamp strips tzinfo then calls
isoformat, which is inconsistent with other serializers like
wallet_transfer_to_dict and can produce wrong times if inputs have non-UTC
tzinfo; change _wallet_timestamp to normalize datetimes to UTC (e.g., convert
via astimezone(timezone.utc) or otherwise ensure UTC) before formatting, and
update wallet_transfer_to_dict and any other serializers to call this single
helper so all timestamps are consistently normalized and serialized.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 6d1eb019-aeab-460d-bb52-c31544cc86fb

📥 Commits

Reviewing files that changed from the base of the PR and between 55608e3 and f674c58.

📒 Files selected for processing (3)
  • app/main.py
  • app/serializers.py
  • tests/test_serializers.py

Comment thread app/serializers.py
Comment on lines +336 to +339
def _wallet_timestamp(value: datetime) -> str:
if value.tzinfo is not None:
value = value.replace(tzinfo=None)
return value.isoformat()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial | 💤 Low value

Inconsistent timestamp serialization across functions.

_wallet_timestamp strips tzinfo before calling isoformat(), but wallet_transfer_to_dict (line 365) and other serializers use .isoformat() directly. If the datetime source changes from UTC-only to mixed timezones, stripping tzinfo without conversion could produce incorrect results.

Current model defaults (utc_now) make this safe, but consider aligning all timestamp handling for consistency.

Also applies to: 365-365

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/serializers.py` around lines 336 - 339, The helper _wallet_timestamp
strips tzinfo then calls isoformat, which is inconsistent with other serializers
like wallet_transfer_to_dict and can produce wrong times if inputs have non-UTC
tzinfo; change _wallet_timestamp to normalize datetimes to UTC (e.g., convert
via astimezone(timezone.utc) or otherwise ensure UTC) before formatting, and
update wallet_transfer_to_dict and any other serializers to call this single
helper so all timestamps are consistently normalized and serialized.

@TateLyman TateLyman force-pushed the codex/refactor-public-formatters branch from f674c58 to 78dfd13 Compare May 25, 2026 23:18
@TateLyman
Copy link
Copy Markdown
Contributor Author

Small follow-up after CodeRabbit flagged docstring coverage: added concise docstrings to the new public serializer functions.

Additional validation:

  • uv run --extra dev python -m pytest tests/test_serializers.py -q -> 2 passed
  • uv run --extra dev ruff check app/serializers.py -> passed
  • uv run --extra dev ruff format --check app/serializers.py -> passed
  • uv run --extra dev mypy app -> success

@ramimbo ramimbo merged commit f4fa763 into ramimbo:main May 25, 2026
1 of 2 checks passed
@ramimbo ramimbo added the mrwk:accepted Maintainer accepted for payout label May 25, 2026
@ramimbo ramimbo added the mrwk:paid Ledger payment recorded label 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.

3 participants