Skip to content

fix(bounties): non-sequential public ids, 404-on-DB-error, error handling & payment redirect#30

Merged
ralyodio merged 2 commits into
masterfrom
fix/bounty-post-error-handling
Jun 17, 2026
Merged

fix(bounties): non-sequential public ids, 404-on-DB-error, error handling & payment redirect#30
ralyodio merged 2 commits into
masterfrom
fix/bounty-post-error-handling

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Fixes the bounty 404 and the enumerable numeric-id problem, plus the original create-error handling.

Changes

Non-sequential public IDs (numeric ids were enumerable / leaked count)

  • New lib/id.ts generatePublicId() (base62 via crypto); mirrored in migrate.mjs.
  • Migration adds bounties.public_id, backfills existing rows, adds a UNIQUE index.
  • All public bounty URLs now use public_id; integer PK kept internally for joins/FKs.
  • POST /api/bounties generates + returns public_id; CoinPay redirect_url, metadata.bounty_id, and the funding webhook all key off public_id.
  • Detail page, GET route, claim route (preserving Fix: prevent race condition in bounty claim #24's atomic update via the resolved numeric id), listing links, and auth returnTo resolve by public_id.

404 on a real bounty

  • The detail page's getBounty had catch { return null }, turning a DB error (e.g. the SQLite Cloud free node pausing) into notFound(). An existing bounty rendered as 404. Errors now surface instead of masquerading as not-found.

Create error handling + payment redirect (original fix)

  • POST /api/bounties wrapped in try/catch → proper JSON 500 instead of an opaque non-JSON crash.
  • New-bounty page redirects to data.pay_url (the field the API returns) instead of the nonexistent checkout_url.

Verification

  • Migration applied to prod (backfilled the 1 existing row).
  • tsc clean; next build passes with SESSION_SECRET unset (all bounty routes build).

Note: based on top of #29 (lazy SESSION_SECRET).

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

ralyodio and others added 2 commits June 17, 2026 02:46
The POST /api/bounties handler had no try/catch around the DB insert,
so any DB failure (e.g. SQLite Cloud free node paused) returned a
non-JSON 500. The browser's res.json() then threw, surfacing the
opaque "Something went wrong. Please try again." with no detail.

- Wrap the insert + CoinPay payment logic in try/catch, returning a
  proper JSON 500 { error: 'Failed to create bounty. Please try again.' }.
- Fix the new-bounty page redirect: it checked data.checkout_url, but
  the API returns data.pay_url. Users were never sent to CoinPay to
  fund the bounty; now they are redirected to pay_url.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bounty URLs exposed the sequential integer primary key (/bounties/1),
which is enumerable and leaks the total count. Switch all public bounty
URLs to a non-sequential, URL-safe public_id while keeping the integer
PK internally for joins/FKs.

- lib/id.ts: generatePublicId() (base62 via crypto), mirrored in
  migrate.mjs for backfill.
- Migration: add bounties.public_id, backfill existing rows, add a
  UNIQUE index.
- POST /api/bounties generates a public_id and returns it; CoinPay
  redirect_url + metadata.bounty_id and the funding webhook now key off
  public_id.
- Detail page, GET route, claim route, listing links, and auth returnTo
  all resolve by public_id.
- Fix the 404 bug: the detail page's getBounty swallowed DB errors and
  returned null, so a paused/erroring DB made a real bounty render as
  404. Let query errors surface instead of masquerading as not-found.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ralyodio ralyodio force-pushed the fix/bounty-post-error-handling branch from df56e88 to 5e47b16 Compare June 17, 2026 02:47
@ralyodio ralyodio merged commit 340f670 into master Jun 17, 2026
5 checks passed
@ralyodio ralyodio deleted the fix/bounty-post-error-handling branch June 17, 2026 02:47
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