Skip to content

fix(payout): hold ambiguous transfers, close announce/cancel races, review follow-ups - #57

Merged
CodeWithEugene merged 3 commits into
mainfrom
fix/review-followups
Sep 28, 2026
Merged

CodeWithEugene merged 3 commits into
mainfrom
fix/review-followups

Conversation

@CodeWithEugene

Copy link
Copy Markdown
Owner

Follow-ups from the review of #52, plus two auth UI tweaks.

Money path

  • executePayout stores the attempt reference when it claims the payout. If the transfer call throws (timeout, dropped connection), it asks Paystack about that attempt before deciding: success confirms, failed/reversed/not_found retries, pending/unknown holds PROCESSING for the sweep. This removes a double-pay window. The Paystack port gains a not_found status.
  • announceWinners and both cancel paths use conditional status updates, so a cancel racing an announce can't both succeed.

Security and ops

  • Per-action rate-limit keys (register, event-cancel, judge-invite) instead of one shared mutate: counter.
  • Hourly purge of expired RateLimitBucket rows.
  • /api/health returns 503 when the payment or chain port can't resolve.
  • CSP connect-src allows the Sentry ingest origin from the public DSN.
  • Removed the unused direct pg dependency.

SEO and copy

  • robots.txt blocks /organizer and /organizer/ without hiding the public /organizers/<slug> pages.
  • Removed em/en dashes from user-facing strings; Title Case fixes.

Auth UI

  • Auth form cards are square and span the ruled column, so their top and bottom rules meet the vertical hairlines. Sign-in and sign-up headings are centered.
  • Every password field (sign in, sign up, reset, account settings) gets a show/hide toggle.

Test plan

  • tsc --noEmit, lint, build
  • pnpm test: 471 tests, including new ones for the ambiguous-transfer matrix, not_found/unknown/success after a thrown transfer, both race guards (verified failing without the guards), and the rate-limit purge
  • Auth pages checked in the browser at 1440px and 375px, light and dark

…eview follow-ups

Money path:
- executePayout stores the attempt reference at claim time and, when the
  transfer call throws, asks Paystack what happened before deciding:
  success confirms, failed/reversed/not_found retries, pending/unknown holds
  PROCESSING for the sweep. Paystack port gains a not_found status.
- announceWinners and both cancel paths use conditional status updates, so
  a cancel and an announce racing each other can't both win.

Security and ops:
- Per-action rate-limit keys (register, event-cancel, judge-invite).
- Hourly purge of expired RateLimitBucket rows.
- /api/health reports 503 when the payment or chain port can't resolve.
- CSP connect-src allows the Sentry ingest origin from the public DSN.
- Drop the unused direct pg dependency (pg-boss brings its own).

SEO and copy:
- robots.txt blocks /organizer and /organizer/ without hiding /organizers.
- Remove em/en dashes from user-facing strings; Title Case fixes.
@CodeWithEugene
CodeWithEugene merged commit bbb6d6a into main Sep 28, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Preview — 63d92405 Deployed Sep 28, 2026 by vercel[bot]
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.

1 participant