chore(api): tighten error responses + document response patterns - #191
Merged
Conversation
Two concrete issues in error response bodies:
1. Awards routes (4 files) leaked raw error.message to clients in their
typed `{ success: false, error }` responses. A catch over a DB query
can surface column names, constraint names, or stack frames in the
response body — useful in dev, a soft information disclosure in prod.
Fixed: the real error stays in console.error for server-side
observability; the client gets 'Internal server error'.
2. LoTW download routes (2 files) returned a `debug: {...}` object
alongside credential-error responses, exposing internal state like
`has_username: bool`, `credential_source`, and station identifiers
to a 400 response. Leftover from the QRZ sync debug-strip pass
(#189) — the frontend never consumed these fields. Stripped.
The discriminated-union `{ success, data, error }` shape used by
`/api/awards/*` and `/api/cloudlog/*` stays — they're documented
contracts with multiple consumers (frontend checks `data.success`;
cloudlog is a public Cloudlog-compatible API). The `details:` field
on install/cron error responses also stays — it's admin/diagnostic
flow and not reachable by untrusted callers.
CLAUDE.md updated:
- Documents both acceptable response patterns and when each applies
- Adds explicit "don't leak raw error.message" rule with an example
- Notes the cloudlog/* external API contract
- Refreshed the Logging section now that the no-console rule (from
#189) has landed; points new code at src/lib/logger.ts
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two concrete issues with error response bodies; both touched lightly so the PR stays small.
1. Awards routes stop leaking raw
error.message(4 files)src/app/api/awards/{dxcc,was}/{progress,summary}/route.tshadcatchblocks returningerror: error instanceof Error ? error.message : 'Internal server error'inside their typed responses. A failure on a DB query can surface column names, constraint names, or stack frames in the response body — useful in dev, a soft information-disclosure in prod. Fixed: the real error stays inconsole.errorfor server-side observability; the client gets'Internal server error'.2. LoTW download routes drop
debug: {...}blocks (2 files)src/app/api/lotw/download{,-contact}/route.tsreturned adebug:object alongside credential-error responses, exposinghas_username/has_password/credential_source/station identifiers. Leftover from the QRZ debug-strip pass (#189) — the frontend never consumed these fields.What I deliberately did not change
{ success, data, error }discriminated union in/api/awards/*stays. Four frontend components branch ondata.success; it's an established contract./api/cloudlog/*{ success, ...}responses stay. It's a public Cloudlog-compatible API for 3rd-party logging software — changing the shape breaks integrations.details:field on install/cron error responses stays. Admin/diagnostic flow only, not reachable by untrusted callers.CLAUDE.md
Updated to document:
error.message" rule with an exampleno-consolerule (chore(logging): strip debug console.log noise + enforce no-console lint rule #189) has landed; points new code atsrc/lib/logger.tsTest plan
npm run lint→ unchanged from baseline (chore(lint): drive ESLint warnings to zero #190 still pending merge)npm run typecheck→ cleannpm run build→ succeedsdebug:block in DevTools🤖 Generated with Claude Code