feat(hub): central mapDBError/writeDBErr error-sanitization helper (#74 foundation)#280
Merged
Conversation
…ients (#74) #74: ~470 handler sites do writeErr(w, 500, err.Error()), returning raw SQLite/driver text (constraint details, table/column names, query fragments, syntax errors) verbatim in JSON responses — information disclosure. This lands the foundation the sweep will use: - mapDBError(err) → client-safe (status, message): sql.ErrNoRows→404, SQLITE_CONSTRAINT→409, SQLITE_FULL→507, SQLITE_READONLY→503, context cancel/deadline→408, everything else (incl. syntax errors)→500 "internal error". No raw driver text ever reaches the client. - (*Server).writeDBErr(w, err): the safe drop-in for `writeErr(w, http.StatusInternalServerError, err.Error())` — maps via mapDBError, logs the RAW error server-side on any 5xx (operators keep full diagnostics), writes the sanitized envelope. Test drives a real in-memory UNIQUE violation → 409 and asserts the message does not leak SQL; plus ErrNoRows(+wrapped)→404, cancel→408, opaque→500. Follow-up (same issue): sweep the ~470 `writeErr(w, 500, err.Error())` sites to `s.writeDBErr(w, err)`, and the per-handler status-code fixes (#74.4: search FTS syntax→400, agent_turns ErrNoRows→404). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jun 14, 2026
physercoe
pushed a commit
that referenced
this pull request
Jun 14, 2026
Hub robustness sweep (#74–#79) + Projects-tab segmented sub-tabs. - ADR-045 D4 storage maintenance (#288) - raw-SQL-error no-leak sweep (#280/#283), rows.Err audit (#286), FTS/routing status codes (#287), owner-or-steward gate (#281), read-pool cap + rows.Close defer (#292), additive pagination (#293) - segmented Projects | Workspaces tabs (#289) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
What
#74 (CRITICAL): ~470 handler sites do
writeErr(w, http.StatusInternalServerError, err.Error()), returning raw SQLite/driver text (constraint details, table/column names, query fragments, syntax errors) verbatim in JSON responses — information disclosure.This PR lands the foundation the sweep will build on (no behavior change to existing sites yet):
mapDBError(err) → (status, safeMsg):sql.ErrNoRows→404,SQLITE_CONSTRAINT→409,SQLITE_FULL→507,SQLITE_READONLY→503, context cancel/deadline→408, everything else (incl. syntax errors)→500"internal error". Raw driver text never reaches the client.(*Server).writeDBErr(w, err): the safe drop-in for the leaky pattern — maps viamapDBError, logs the raw error server-side on any 5xx (operators keep full diagnostics), writes the sanitized envelope.Test
Drives a real in-memory UNIQUE violation → asserts 409 + message does not leak SQL; plus
ErrNoRows(and wrapped) → 404, context cancel → 408, opaque error → 500 generic.Follow-up (same issue, staged next)
Sweep the ~470
writeErr(w, 500, err.Error())sites →s.writeDBErr(w, err), plus the per-handler status-code fixes (#74.4: search FTS syntax → 400;agent_turnsErrNoRows→ 404). Mechanical; runs as its own reviewable PR.🤖 Generated with Claude Code