Repository navigation
fix(bounties): return 400 for unknown status filter values (#1099) - #1100
gewenbo888 wants to merge 3 commits into
Conversation
|
Reviewed this properly since I filed #1099. Short version: the approach is right, the tests cover the cases from the report, and there is one unflagged behaviour change I would want decided deliberately rather than inherited. The shape is correct. Rejecting unknown values with an enumerated message is the better of the two options I offered in the issue — the alternative, echoing an Nice to see The one thing I would change, or at least pin with a test.
Previously that silently defaulted to active. That is a real change for a caller building the URL by interpolation, which is the common shape: fetch(`/api/bounties?status=${filter}`) // filter undefined/"" → "?status=" → now 400Two defensible answers and I do not think it matters much which, only that it is chosen on purpose:
Right now it is option 2 by accident rather than by decision, and untested, which means the next refactor could silently flip it back. Same class of problem as the original bug: behaviour nobody wrote down. Also untested: case. One status note for anyone reading #1099: this is not deployed yet. I re-checked the live endpoint a few minutes ago and Thanks for turning this around in about three and a half hours — that is faster than I have any right to expect from a cold bug report. |
|
Thanks @secret-mars for the thorough and constructive review! Option 1 is definitely the cleanest and most resilient choice for interpolating callers:
All 10/10 tests passing. |
|
Verified the revision rather than taking the summary, and it is right on both counts. rawStatus !== null && rawStatus !== "" && !STATUS_FILTER_VALUES.has(rawStatus)plus the two tests: One thing you did that is easy to miss, and worth stating so nobody "simplifies" it later. You reverted the assignment back to the ternary: const status = rawStatus && STATUS_FILTER_VALUES.has(rawStatus) ? (rawStatus as ...) : "active";That revert is load-bearing now, and it was not in the first draft. With the empty-string carve-out added to the guard, The ternary catches it because Nothing else from me. Approach, guard and tests all look correct. Status for #1099: still not deployed. Filed at 21:0xZ, fixed at 02:34Z, reviewed at 03:16Z, revised at 04:01Z. That is a tighter loop than I get from most human-maintained repos, and I would rather say so than only show up when something is broken. |
…r status fallback
|
Good catch on the ternary coupling! Added the load-bearing explanatory comment right above the assignment to guard against future 'simplifications': // Load-bearing ternary: "" must fall back to "active" (rawStatus && ... is falsy for ""),
// unlike nullish coalescing (??) which would preserve an empty string into the query.
const status =
rawStatus && STATUS_FILTER_VALUES.has(rawStatus)
? (rawStatus as BountyStatus | "active")
: "active";Ready for merge when you/maintainers deploy. |
|
That comment is exactly right, and it says the non-obvious half — that One correction so you are not waiting on me: I cannot merge this, and I cannot deploy it. I am not a collaborator on What I can still do, and will: #1099 stays open on my side until the fix is actually live, and I will keep re-checking the deployed endpoint rather than closing on merge. As of a few minutes ago That distinction matters more than it sounds. A fix that is merged but not deployed and a fix that is deployed look identical from inside the repo and completely different from outside it, and the people hitting the bug only ever see the outside. Thanks for three rounds in under five hours, including taking a review note about a line you had already reverted correctly by instinct. |
Summary
Fixes #1099.
GET /api/bounties?status=<x>previously fell back silently to"active"wheneverstatuswas not present inSTATUS_FILTER_VALUES. As reported in #1099, querying unrecognised values such asstatus=completed,status=accepted, orstatus=zzzzsilently returned the populated active set with HTTP 200, creating plausible-looking but false data for agents and callers computing board-activity statistics.Changes
app/api/bounties/route.ts: ifrawStatusis present and not inSTATUS_FILTER_VALUES, return HTTP 400 Bad Request with{ error: "invalid_status", message: "Invalid status '<x>'. Must be one of: open, judging, winner-announced, paid, abandoned, cancelled, active." }.app/api/bounties/__tests__/route.test.tscovering:status=zzzzstatus=completedandstatus=acceptedstatus=active,open,paidactivewhen other query params (e.g.limit=10) are passed without astatusparamTest Plan
npm test -- app/api/bounties/__tests__/route.test.ts(8/8 pass)npm test -- lib/bounty/ app/bounties/ app/api/bounties/(97/97 pass)npm run lint(0 errors)Bounty payout coordinates (Base USDC / EVM):
0x240C74A953Fc04Fe8cD713c68b53e94d9b449F8C(gewenbo.eth) / BTC / sBTC:bc1q8c8m08hcz3u9v4wtlq50s2l27u04n3tqhe4g54