Skip to content

refactor(api): audit and fix inconsistent/incorrect HTTP status codes - #530

Open
Vyacheslav-Tomashevskiy wants to merge 1 commit into
Northgate-Systems:mainfrom
Vyacheslav-Tomashevskiy:refactor/416-http-status-audit
Open

refactor(api): audit and fix inconsistent/incorrect HTTP status codes#530
Vyacheslav-Tomashevskiy wants to merge 1 commit into
Northgate-Systems:mainfrom
Vyacheslav-Tomashevskiy:refactor/416-http-status-audit

Conversation

@Vyacheslav-Tomashevskiy

Copy link
Copy Markdown
Contributor

Closes #416.

What I found

Swept every route under src/app/api/ for status codes that don't match what actually happened, rather than just formatting/style. Three real correctness bugs and one consistency nit:

  1. GET /api/transactions returned 401 for database errors. Both the if (error) branch (query failure) and the outer catch-all returned unauthorizedResponse(). A DB/connection failure is a server problem, not "you're logged out" - a client that treats 401 as "redirect to login" would incorrectly log a user out just because the database hiccuped. Now 500.

  2. Three routes conflated "query failed" with "row not found." GET /api/transactions/[id], POST /api/stellar/submit, and POST /api/stellar/sign-and-submit all shared if (txError || !tx) return errorResponse("...", 404). Split them: a query error is now 500, a genuinely missing row is still 404.

  3. POST /api/stellar/send's "Insufficient balance" error fell through to a generic 500. The adjacent "Invalid recipient" error from the same buildSendTransaction() call is already special-cased to 400 in the catch block - insufficient balance is exactly the same class of "fix your input given your account's current state" client error, not a server fault. Added a matching branch.

  4. GET /api/stellar/rate built its own errorResponse("Unauthorized", 401) instead of the shared unauthorizedResponse() helper every other route uses - pure consistency fix, same behavior.

Verified

  • npx vitest run - 66/66 across all touched/new files (1 extended existing test file, 4 new: transactions/route, stellar/send, stellar/submit, stellar/sign-and-submit - each specifically asserting the query-error-vs-not-found split or the insufficient-balance status, not just the happy path).
  • npx eslint on all touched files - 0.
  • npx tsc --noEmit - 0 in touched files (same 5 pre-existing SafeUser errors elsewhere, reproduce on a clean checkout).
  • npm run build - compiles clean.
  • Live-verified against npm run dev: unauthenticated GET /api/transactions, POST /api/stellar/submit, and POST /api/stellar/send each still correctly return 401 - only the downstream-of-auth paths changed.

One thing worth flagging

npx vitest run on a clean checkout of this branch currently fails at collection with ReferenceError: isValidStellarPublicKey is not defined in validations.ts (from #424's merge, missing an import) - that's the same issue already fixed in the still-open #529, so I left it untouched here to avoid a third PR stepping on the same lines. npx vitest run --exclude "**/validations.test.ts" is the 66/66 above; once #529 lands the full suite here will be 79/79.

…closes Northgate-Systems#416)

Swept every route in src/app/api for status codes that don't match
what actually happened. Found and fixed three real correctness bugs,
plus one consistency nit:

1. GET /api/transactions returned 401 Unauthorized whenever the
   Supabase query itself failed (DB down, connection error, etc.),
   both in the `if (error)` branch and the outer catch-all. A query
   failure is a server problem, not "you're logged out" - a client
   that treats 401 as "redirect to login" would incorrectly log a
   user out because the database hiccuped. Now returns 500.

2. Three routes (GET /api/transactions/[id], POST /api/stellar/submit,
   POST /api/stellar/sign-and-submit) shared the same
   `if (txError || !tx) return errorResponse("...", 404)` pattern,
   collapsing "the lookup query failed" and "no row with this id"
   into the same 404. Split them: a query error is now 500, a missing
   row is still 404.

3. POST /api/stellar/send's catch-all let "Insufficient balance: ..."
   (thrown by buildSendTransaction when the account can't cover the
   send) fall through to the generic 500 branch, even though the
   adjacent "Invalid recipient" error from the same function is
   already special-cased to 400. Insufficient balance is exactly the
   same kind of "fix your input given your account's current state"
   client error, not a server fault - added a matching branch so both
   land on 400.

4. GET /api/stellar/rate built its own `errorResponse("Unauthorized", 401)`
   instead of using the shared unauthorizedResponse() helper every
   other route uses - purely a consistency fix, same behavior.

Verified: npx vitest run - 66/66 across all touched/new files
(1 restored/extended test file, 4 new: transactions/route,
stellar/send, stellar/submit, stellar/sign-and-submit - each
specifically asserting the query-error-vs-not-found split or the
insufficient-balance status, not just happy-path). Confirmed each new
"returns 500" assertion actually depends on the fix by checking it
against the pre-fix code path during development.

Note: `npx vitest run` on a clean checkout of this branch currently
fails at collection with `ReferenceError: isValidStellarPublicKey is
not defined` in validations.ts (from Northgate-Systems#424's merge, missing an import)
- that's a separate, already-open fix in Northgate-Systems#529 and out of scope here,
so it isn't touched in this diff. `npx vitest run --exclude
"**/validations.test.ts"` is the 66/66 above; the full suite will be
79/79 once Northgate-Systems#529 lands (it fixes that same file's now-invalid checksum
test fixture too).

npx eslint on all touched files - 0. npx tsc --noEmit - 0 in touched
files (same 5 pre-existing SafeUser errors elsewhere, reproduce on a
clean checkout). npm run build - compiles clean. Live-verified against
npm run dev: unauthenticated GET /api/transactions, POST
/api/stellar/submit, and POST /api/stellar/send each correctly still
return 401 (the auth-gate status wasn't touched, only the
downstream-of-auth paths were).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Sep 8, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the codex723's projects Team on Vercel.

A member of the Team first needs to authorize it.

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.

Audit all API routes for consistent HTTP status code usage

1 participant